ASP MVC 5组织项目以避免重复代码

时间:2016-06-24 09:04:42

标签: asp.net-mvc refactoring asp.net-mvc-areas service-layer

我正在构建一个asp mvc 5支持票证服务台应用程序。该应用程序将要求用户注册以提交支持服务单。用户操作是通过添加线程等注释来更新票证。

代理商将管理故障单并拥有其他权限来编辑故障单并创建内部和公共说明,并能够查看所有故障单。

网站管理员可以配置网站。

问题是,如果我有一个控制器称为票证控制器,则创建或编辑票证上的主要操作对于代理和用户都是类似的。不同之处在于,当用户创建故障单时,他们只能填写表单上的某些字段,代理可以在其中更新其他字段。

所以我最终得到的是我的控制器和视图中的很多if else语句,用于检查用户角色,以限制向不同类型的用户显示哪些表单字段和操作。此外,我的viewmodels向客户公开了他们不应该拥有权限的属性。

所以我的问题是你如何组织这种类型的设置。您是否为代理创建单独的区域并复制所有控制器和视图模型以满足此类用户的需要。

或者您是否只是为每个创建的不同类型的用户角色使用if then else语句来膨胀控制器和视图?

对于这个特定应用程序的最佳实践的一些建议将不胜感激。

为代理创建区域的唯一好处是我可以彻底改变代理门户的外观,具有不同的URL,例如。 mysite / agentdesk / ticket,它更容易维护,但代价是重复代码。

/ *当前控制器逻辑和视图模型* / 如您所见,in viewmodel公开了只有代理可以设置的状态和优先级属性。

在控制器的create方法中,您可以看到teneray操作符用于确定用户是否具有设置上述属性的正确角色。

public class TicketViewModel
{

      public int Id { get; set; }

      [Required]
      public string Subject { get; set; }

      [Required]
      public string Description { get; set; }

      // Only an agent can change the status
      [Required]
      public int Status { get; set; }

      // Only an agent can change the priority
      [Required]
      public int Priority { get; set; }


      public IEnumerable<StatusType> StatusTypes { get; set; }
      public IEnumerable<PriorityLevel> PriorityLevels { get; set; }

}

public class TicketController : Controller
{

    [Authorize]
    public ActionResult Create()
    {
        var viewModel = new TicketViewModel
        {
            StatusTypes = _context.StatusTypes.ToList(),
            PriorityLevels = _context.PriorityLevels.ToList()

        };

        return View(viewModel);
    }


    [Authorize]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(TicketViewModel viewModel)
    {
        if (!ModelState.IsValid)
        {
            viewModel.StatusTypes = _context.StatusTypes.ToList(),
            viewModel.PriorityLevels = _context.PriorityLevels.ToList()
            return View(viewModel);
        }

        bool agentRole = HttpContext.Current.User.IsInRole("Agent");

        var ticket = new Ticket
        {
            CreatedBy = User.Identity.GetUserId(),
            Subject = viewModel.Subject,
            Description = viewModel.Description,
            StatusId = agentRole ? viewModel.Status : 1,
            PriorityId = agentRole ? viewModel.Priority : 1
        };

        _context.Tickets.Add(ticket);
        _context.SaveChanges();

        return RedirectToAction("Index", "Tickets");
    }
}

1 个答案:

答案 0 :(得分:0)

我认为一个区域是最好的方式。简单的事实是,代码的复杂性将迅速失控,否则就会失控。根据某个角色显示/隐藏表单字段是一回事,但实际上,为了安全起见,这需要端到端地保护。换句话说,如果允许用户访问这些属性,您还需要检查操作内部仅使用值设置属性。即使没有允许的表单字段,发布您无法编辑的内容也是微不足道的。

要解决代码重复问题,请不要重复代码。听起来有点陈词滥调,但事实确实如此。您的操作中的类似代码可以分解为基本控制器或只是一些帮助程序类。您的视图中的类似代码可以分解为部分代码。基本上,两种情况下相同的任何东西都应该在两种情况下可以使用相同代码的地方。