我对MVC和EF (来自web表单)完全陌生,所以如果这个问题很愚蠢,我很抱歉;)
我需要建立一个应用程序,用户登录到使用AspIdentity,也与社区表联系。登录后,他们只能看到社区特定站点范围内的数据。我已经建立了应用程序,但我正在努力解决如何它将只拉取基于社区ID的数据…在web表单中,我会自己构建所有这些逻辑:/
基本上有内置的标识表和我定义的标识表(社区、家庭、居民等)。
看起来像是一个简单的应用程序,但我没有看到任何这样做的教程。
谢谢!
发布于 2015-05-16 00:39:49
你可以从两个方面着手。如果用户只属于一个社区,那么您可以简单地使用该用户的社区来限制您的查询。从本质上讲,您将执行以下操作:
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的内容。然后,在服务的操作中,你会有类似这样的东西:
public ActionResult Foo(string community)
{
...同样,您只需按照上面的社区限制查询即可。但是,如果您遵循这种方法,那么您可能还需要执行一些操作,比如创建一个自定义Authorize属性来验证您的用户是否真正属于该社区。
发布于 2015-05-17 02:47:13
以下是我将如何处理它,看看它是否至少能让你开始行动起来。我采用了Visual Studio附带的一个干净的MVC web项目:

我还将借鉴StackOverflow的社区概念,在那里你有不同类型的访问者和适用的内容。(在这个例子中,“程序员”有他们的问题集,而“设计师”有他们的问题集。)
最后,为简洁起见,我尝试排除未修改的文件部分。为简短起见,现有代码已替换为Snip注释。
继续前进!
基础设施
设置其他实体,为我们提供社区和特定于该社区的数据(问题)。
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; }
}将这些实体添加到ApplicationUser和ApplicationDbContext中。
~/Models/IdentityModels.cs
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人员已经为我们创建了一个占位符。
// 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
public class RegisterViewModel
{
/* snip */
[Required]
[Display(Name = "Community")]
public int CommunityId { get; set; }
}将这个输入到我们的控制器中。
~/Controllers/AccountController.cs
[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
@* 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控制器:
[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
}以及一个与之相伴的观点:
@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
@* Snip *@
<ul class="nav navbar-nav">
@* Snip *@
<li>@Html.ActionLink("Questions", "Questions", "Home")</li>
</ul>
@* Snip *@示例内容
创建一个非常基本的DbInitializer,它将填充一些我们可以使用的信息。因此,回到~/ModelsIdentityModels.cs文件:
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 (设计师)


https://stackoverflow.com/questions/30263436
复制相似问题