ASP.NET MVC操作返回不同的视图,或只是做了大量的操作?

时间:2010-03-12 20:41:36

标签: asp.net-mvc

所以,我处于这种情况,我需要根据经过身份验证的用户的“角色”显示不同的视图。

我想知道哪种方法最好:

[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");
}

3 个答案:

答案 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操作。

编辑:是不是没有正确回答问题?让我重新解释一下我的答案。