首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVC 5实体框架6基于社区的应用程序

MVC 5实体框架6基于社区的应用程序
EN

Stack Overflow用户
提问于 2015-05-15 23:34:15
回答 2查看 66关注 0票数 1

我对MVC和EF (来自web表单)完全陌生,所以如果这个问题很愚蠢,我很抱歉;)

我需要建立一个应用程序,用户登录到使用AspIdentity,也与社区表联系。登录后,他们只能看到社区特定站点范围内的数据。我已经建立了应用程序,但我正在努力解决如何它将只拉取基于社区ID的数据…在web表单中,我会自己构建所有这些逻辑:/

基本上有内置的标识表和我定义的标识表(社区、家庭、居民等)。

看起来像是一个简单的应用程序,但我没有看到任何这样做的教程。

谢谢!

EN

回答 2

Stack Overflow用户

发布于 2015-05-16 00:39:49

你可以从两个方面着手。如果用户只属于一个社区,那么您可以简单地使用该用户的社区来限制您的查询。从本质上讲,您将执行以下操作:

代码语言:javascript
复制
var foo = db.Foos.SingleOrDefault(m => m.Id == id && m.CommunityId = user.CommunityId);
if (foo == null)
{
    return new HttpNotFoundResponse();
}

换句话说,在从数据库中提取项目以匹配用户社区时,只需添加一个额外的条件即可。这样,如果它属于他们的社区,用户将只会看到404以外的内容。

选项2是使社区成为URL的一部分,并使用它来限制您的查询,类似于上面的查询。例如,您可能有类似/awesome-community/foo的内容。然后,在服务的操作中,你会有类似这样的东西:

代码语言:javascript
复制
public ActionResult Foo(string community)
{
    ...

同样,您只需按照上面的社区限制查询即可。但是,如果您遵循这种方法,那么您可能还需要执行一些操作,比如创建一个自定义Authorize属性来验证您的用户是否真正属于该社区。

票数 0
EN

Stack Overflow用户

发布于 2015-05-17 02:47:13

以下是我将如何处理它,看看它是否至少能让你开始行动起来。我采用了Visual Studio附带的一个干净的MVC web项目:

我还将借鉴StackOverflow的社区概念,在那里你有不同类型的访问者和适用的内容。(在这个例子中,“程序员”有他们的问题集,而“设计师”有他们的问题集。)

最后,为简洁起见,我尝试排除未修改的文件部分。为简短起见,现有代码已替换为Snip注释。

继续前进!

基础设施

设置其他实体,为我们提供社区和特定于该社区的数据(问题)。

代码语言:javascript
复制
public class Community
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class Question
{
    public int Id { get; set; }

    public int CommunityId { get; set; }
    public virtual Community Community { get; set; }

    public string Title { get; set; }
}

将这些实体添加到ApplicationUserApplicationDbContext中。

~/Models/IdentityModels.cs

代码语言:javascript
复制
public class ApplicationUser : IdentityUser
{
    public int CommunityId { get; set; }
    public virtual Community Community { get; set; }

    /* Snip */
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public DbSet<Community> Communities { get; set; }
    public DbSet<Question> Questions { get; set; }

    /* Snip */
}

将社区附加到用户。声明使这件事变得非常容易,因为我们只是将附加信息附加到用户配置文件中。此外,Visual Studio人员已经为我们创建了一个占位符。

代码语言:javascript
复制
// This makes it easier to reference and makes sure we're consistent
public static class CustomClaimTypes
{
    public const string CommunityId = "http://stackoverflow.com/claims/communityid";
}

public class ApplicationUser : IdentityUser
{
    public int CommunityId { get; set; }
    public virtual Community Community { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        userIdentity.AddClaim(new Claim(CustomClaimTypes.CommnunityId, this.CommunityId.ToString()));
        return userIdentity;
    }
}

注意,我们已经添加了userIdentity.AddClaim(...) (和我们的静态类)。

演示

修改视图模型以适应我们的更改。

~/Models/AccountViewModels.cs

代码语言:javascript
复制
public class RegisterViewModel
{
    /* snip */

    [Required]
    [Display(Name = "Community")]
    public int CommunityId { get; set; }
}

将这个输入到我们的控制器中。

~/Controllers/AccountController.cs

代码语言:javascript
复制
[AllowAnonymous]
public ActionResult Register()
{
    ViewBag.Communities = GetCommunities();

    return View();
}

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        /* Snip */
    }
    ViewBag.Communities = GetCommunities();
    return View(model);
}

// The additional method we're calling above:
private IEnumerable<SelectListItem> GetCommunities()
{
    var db = ApplicationDbContext.Create();
    var communities = db.Communities.ToDictionary(k => k.Id, v => v.Name);
    return communities.Select(c => new SelectListItem
    {
        Text = c.Value,
        Value = c.Key.ToString()
    });
}

通过我们的视线把它冲出来。

~/Views/Account/Register.cshtml

代码语言:javascript
复制
@* Snip *@
<div class="form-group">
    @Html.LabelFor(m => m.CommunityId, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.DropDownListFor(m => m.CommunityId, (IEnumerable<SelectListItem>)ViewBag.Communities, new { @class = "form-control" })
    </div>
</div>
@* Snip *@

创建一个新动作Home控制器:

代码语言:javascript
复制
[Authorize]
public ActionResult Questions()
{
    var communityId = GetCommunityId();
    var db = ApplicationDbContext.Create();
    var community = db.Communities.SingleOrDefault(c => c.Id == communityId);
    var questions = db.Questions.Where(c => c.CommunityId == communityId).AsEnumerable();

    ViewBag.Message = community.Name;
    return View(questions);
}

// Helper that's probably better suited in a more common location
private Int32 GetCommunityId()
{
    var communityIdClaim = ((ClaimsPrincipal)User).Claims
        .FirstOrDefault(c => c.Type == CustomClaimTypes.CommnunityId);
    Int32 communityId;
    return communityIdClaim != null && Int32.TryParse(communityIdClaim.Value, out communityId)
        ? communityId
        : -1; // Erroneous id
}

以及一个与之相伴的观点:

代码语言:javascript
复制
@model IEnumerable<@* Your.Model.Namespace. *@Question>
@{
    ViewBag.Title = "Questions";
}

<h2>@ViewBag.Title</h2>
<h3>@ViewBag.Message</h3>

<table class="table">
    <thead>
        <tr>
            <td>Question</td>
        </tr>
    </thead>
    <tbody>
        @foreach (var question in Model)
        {
            <tr>
                <td>@question.Title</td>
            </tr>
        }
    </tbody>
</table>

向您的菜单添加链接。

`~/Views/Shared/_Layout.cshtml

代码语言:javascript
复制
@* Snip *@
<ul class="nav navbar-nav">
    @* Snip *@
    <li>@Html.ActionLink("Questions", "Questions", "Home")</li>
</ul>
@* Snip *@

示例内容

创建一个非常基本的DbInitializer,它将填充一些我们可以使用的信息。因此,回到~/ModelsIdentityModels.cs文件:

代码语言:javascript
复制
public class ApplicationDbInitializer : CreateDatabaseIfNotExists<ApplicationDbContext>
{
    protected override void Seed(ApplicationDbContext context)
    {
        var communities = new[]{
            new Community { Name = "Programmers" },
            new Community { Name = "Designers" }
        };

        var questions = new[]{
            new Question { Community = communities[0], Title = "How do I write my first application?" },
            new Question { Community = communities[0], Title = "What is unit testing?" },
            new Question { Community = communities[0], Title = "Inversion of Control: What is it?" },

            new Question { Community = communities[1], Title = "What is a StyleSheet?" },
            new Question { Community = communities[1], Title = "HTML5: What do I need to know?" },
            new Question { Community = communities[1], Title = "Is Silverlight still being used?" },
        };

        context.Communities.AddRange(communities);
        context.Questions.AddRange(questions);
        context.SaveChanges();
    }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    // for simplicity, let's add a static ctor within the context
    static ApplicationDbContext()
    {
        Database.SetInitializer(new ApplicationDbInitializer());
    }

    /* Snip */
}

给它一个通读

现在,您应该能够注册用户,并查看适用于他们所在社区的内容:

Paul (程序员)

Debby (设计师)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30263436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档