不同领域中非常相似的控制器的最佳实践

时间:2013-11-27 15:24:00

标签: c# asp.net asp.net-mvc asp.net-mvc-4

我的asp.net MVC应用程序有一个区域“公司”和一个区域“管理员”。

公司可以对公司区域的用户进行CRUD。我在公司区域为此创建了一个UsersController。 管理员可以在管理区域中对公司的用户执行CRUD。我在Admin区域为此创建了一个CompanyUsersControllers。

两个控制器都有非常相似的代码,我想知道重用大部分代码的最简洁方法是什么。

在编写这个问题时,我想我可以使用虚拟ActionResults创建一个抽象的UsersControllerBase类。我做了这个,它适用于公司区域。我在UsersController类的overriding方法上定义属性,并在每个重写方法中调用相应的抽象方法。

以下是基类的示例:

[UsersControllerBase.cs]
public virtual ActionResult Edit(string slug)
{
    var user = UserRepository.GetBySlug(slug);

    if (user.CompanyId != CurrentUser.CompanyId)
    {
        throw new SecurityException(CurrentUser.Id + " attempted to edit a user that does not belong to his company");
    }

    var model = user.ToViewModel();
    AddListsTo(model);

    return View(model);
}

相应的覆盖:

[Company/UsersController.cs]
[HttpGet, GET("/company/users/{slug}/edit")]
public override ActionResult Edit(string slug)
{
    return base.Edit(slug);
}

问题是Edit in Admin / CompanyUsersController.cs中有一个额外的参数“companySlug”,用于查找我们当前正在编辑用户的公司。 正如您在上面的代码中所看到的,在Company / Userscontroller.cs中,我们只是从CurrentUser派生出公司。

处理此问题的最佳方法是什么?

TD;博士 我有2个具有相同命名操作的控制器,它们具有几乎相同的方法体但参数不同。我想尽可能多地重用代码。请问我如何c#。

3 个答案:

答案 0 :(得分:3)

如果这两种方法具有不同的签名,我认为将其作为基类方法实现是不值得的,尽管这并非不可能。我将在基类上创建一个受保护的帮助器方法,并将共享代码放入其中。像这样(对您的Repository API做一些假设):

[UsersControllerBase.cs]
protected virtual ActionResult Edit(User user)
{
    var model = user.ToViewModel();
    AddListsTo(model);

    return View(model);
} 

[Admin/CompanyUsersController.cs]
[HttpGet, GET("/admin/users/{companySlug}/{slug}/edit")]
public ActionResult Edit(string companySlug, string slug)
{
    var user = UserRepository.GetBySlug(companySlug, slug);
    return base.Edit(user);
}

[Company/UsersController.cs]
[HttpGet, GET("/company/users/{slug}/edit")]
public ActionResult Edit(string slug)
{
    var user = UserRepository.GetBySlug(slug);

    if (user.CompanyId != CurrentUser.CompanyId)
    {
        throw new SecurityException(CurrentUser.Id + " attempted to edit a user that does not belong to his company");
    }        
    return base.Edit(user);
}

答案 1 :(得分:1)

如果其他控制器中的编辑操作有一个额外的参数,那么在我看来它不应该是基本编辑操作的覆盖。我将在派生控制器中使用两个参数创建单独的Edit操作,并使覆盖Edit操作返回404。

[HttpGet]
public override ActionResult Edit(string slug)
{
    return HttpNotFound();
}

[HttpGet]
public ActionResult Edit(string slug, string companySlug)
{
    // some code...
}

答案 2 :(得分:0)

不值得实现basecontroller,因为类似的方法有不同的参数。 即使它们具有相同的签名,代码也更清晰,更易读,易懂和可维护,同时专注于保持控制器尽可能轻量级,而不是增加太多复杂性以节省一些重复的代码行。