是否有更好的方法来实现基于角色的acton和mvc中的视图而不是if / else?

时间:2012-07-16 23:02:23

标签: asp.net-mvc-3 asp.net-mvc-3-areas asp.net-roles

所以我在我的mvc .net应用程序中有三个角色,管理员,公司和员工,它们在一个单独的数据库中使用asp.net成员资格。我现在将.net成员资格移到另一个数据库中,因为每次我修改模型时,.net成员资格表都会被删除。

无论如何,我在action方法中使用if / else处理不同的角色。例如,在Index()操作中,我检查用户是否处于管理员角色,然后基于此创建模型和linq查询。如果用户在公司角色,不同的查询和用户在员工角色,不同的查询。检查下面的代码。 if条件传递给View后创建的模型。

我觉得这不是处理角色的最佳方式。这是处理角色的最佳方式吗?我也在考虑不同的领域,但我对不同的角色使用相同的观点,我认为它可能没有用处。

任何建议/想法都非常感激。

[Authorize]
    public class CompanyController : Controller
    {
        private MyDBContext db = new MyDBContext();

        //
        // GET: /Company/

        public ViewResult Index()
        {
            var viewModel = new CompanyIndexViewModel();
            if (Roles.IsUserInRole("administrators")) {
                viewModel = new CompanyIndexViewModel { Companies = db.Companies.ToList() };
            }
            else if (Roles.IsUserInRole("companies")) {
                viewModel = new CompanyIndexViewModel { Companies = db.Companies.Where(c => c.Username.ToLower().Equals(this.User.Identity.Name.ToLower())).ToList() };
            }
            else if (Roles.IsUserInRole("employees")) {
                string userName = this.User.Identity.Name.ToLower();
                var companies = db.Companies.Where(c => c.Appointments.Any(a =>
                                   a.Employee.Username.ToLower() == userName)).ToList();
                viewModel = new CompanyIndexViewModel { Companies = companies.ToList() };
            }

            return View(viewModel);
        }
....

2 个答案:

答案 0 :(得分:2)

我会做两件事:

首先,StanK所说的并将其从控制器动作中移出。但是,我会把它一起移出Controller。这种逻辑不应该真正驻留在Controller中(无论是在操作中,还是控制器中的私有方法)。

以这种方式思考:如果您了解哪些公司会发生变化,那么您将需要在各种不同的地方进行更改。

其次,我将为CompanyIndexViewModel创建一个构造函数,该构造函数接收了Company的列表,而不是像这样内联地初始化它。 CompanyIndexViewModel是否包含公司以外的任何其他内容?

// your controller
public ViewResult Index()
{
    var viewModel = CompanyIndexViewModel(CompanyService.GetCompaniesForCurrentUser());
    return View(viewModel);
}

理想情况下,您还可以让您的控制器依赖于代表“CompanyService”的接口,并将其注入您的控制器。

Take a look at this blog概述了使用Ninject和MVC 3.设置以后对你来说非常强大的东西是非常简单的。

如果你从我上面所述的内容中抽出一件事,最好从逻辑移出控制器开始。

答案 1 :(得分:1)

我会将构建公司列表的代码移动到它自己的方法来整理控制器操作,这也会使确定当前用户的公司列表的逻辑可以重复使用。

e.g。

private List<Company> GetCompaniesForCurrentUser()
{
    var userName = this.User.Identity.Name.ToLower();

    if (Roles.IsUserInRole("administrators"))
        return db.Companies.ToList();

    if (Roles.IsUserInRole("companies"))
        return db.Companies.Where(c => c.Username.ToLower().Equals(userName)).ToList();

    if (Roles.IsUserInRole("employees"))
        return db.Companies.Where(c => c.Appointments.Any(a =>
        a.Employee.Username.ToLower() == userName)).ToList();

    throw new AuthorizationException("User " + userName + " is not authorised.");

}


public ViewResult Index()
{
    var viewModel = new CompanyIndexViewModel { Companies = GetCompaniesForCurrentUser() };
    return View(viewModel);
}