所以,我处于这种情况,我需要根据经过身份验证的用户的“角色”显示不同的视图。
我想知道哪种方法最好:
[Authorize(Roles="Admin")]
public ActionResult AdminList(int? divID, int? subDivID)
{
var data = GetListItems(divID.Value, subDivID.Value);
return View(data);
}
[Authorize(Roles = "Consultant")]
public ActionResult ConsultantList(int? divID, int? subDivID)
{
var data = GetListItems(divID.Value, subDivID.Value);
return View(data);
}
或者我应该做这样的事情
[Authorize]
public ActionResult List(int? divID, int? subDivID)
{
var data = GetListItems(divID.Value, subDivID.Value);
if(HttpContenxt.User.IsInRole("Admin"))
{ return View("AdminList", data ); }
if(HttpContenxt.User.IsInRole("Consultant"))
{ return View("ConsultantList", data ); }
return View("NotFound");
}
答案 0 :(得分:5)
如果动作在概念上相同,但显示不同,我会有一个动作,并根据您的鉴别器返回不同的视图。我会用你的第二个例子,稍加修改。请注意,如果用户没有合适的角色,则无需获取数据。
[Authorize]
public ActionResult List(int? divID, int? subDivID)
{
var view = HttpContext.User.IsInRole("Admin")
? "AdminList"
: (HttpContext.User.IsInRole("Consultant")
? "ConsultantList"
: null);
if (view == null)
{
return View("NotFound");
}
var data = GetListItems(divID.Value, subDivID.Value);
return View( view, data );
}
当然,当你引用一个可能为空的Nullable<int>
的值时,你会发现你有可能发生未处理的异常吗?
此外,如果经常这样做,您可以将视图前缀的构造重构为常用方法。
public string GetRolePrefix()
{
return HttpContext.User.IsInRole("Admin")
? "Admin"
: (HttpContext.User.IsInRole("Consultant")
? "Consultant"
: null);
}
然后将其称为
...
var prefix = GetRolePrefix();
if (prefix == null)
{
return View("NotFound"); // more likely "NotAuthorized" ???
}
...get model...
return View( prefix + "List", data );
答案 1 :(得分:5)
我更喜欢第二种方法,但我认为你的控制器可以整理一下。根据我的喜好,有太多的逻辑,随着更多的角色被添加,它可能会增长。
一种方法是将丑陋的角色检查代码重构为服务层(如果您使用的是IoC容器,则可以注入):
[Authorize]
public ActionResult List(int? divID, int? subDivID)
{
var permission = _userService.GetKeyRole(HttpContext.User);
if(permission != null)
{
var data = GetListItems(divID.Value, subDivID.Value);
return View(permission + "List", data );
}
return View("NotFound");
}
提取的方法:
public class UserService : IUserService
{
public string GetKeyRole(IPrincipal user)
{
if(user.IsInRole("Admin")) return "Admin";
if(user.IsInRole("Consultant")) return "Consultant";
return null;
}
}
答案 2 :(得分:-1)
这是第三种方法。它是Nate建议的两种方法的组合,在第二种方法中保留了逻辑的单一位置,但是将用户分成了与第一种方法相同的行为。
[ChildActionOnly]
public ActionResult List(int? divID, int? subDivID)
{
var data = GetListItems(divID.Value, subDivID.Value);
return View(data);
}
[Authorize(Roles="Admin")]
public ActionResult AdminList(int? divID, int? subDivID)
{
return List(divID, subDivID);
}
[Authorize(Roles = "Consultant")]
public ActionResult ConsultantList(int? divID, int? subDivID)
{
return List(divID, subDivID);
}
这里的技巧是MVC将尝试搜索请求操作命名的视图而不是产生输出的视图。因此,当您运行AdminList时,它实际上将返回带有AdminList视图的List操作。
编辑:是不是没有正确回答问题?让我重新解释一下我的答案。