【问题标题】:Best practice ASP.NET Controller for Common Actions常见操作的最佳实践 ASP.NET 控制器
【发布时间】:2017-10-13 04:38:05
【问题描述】:

我有个小问题,

在很多示例中,我看到不返回任何视图或部分视图的控制器动作也被添加到同一个控制器中 - 现在在我的情况下,我有多个控制器,我需要运行相同的动作,例如

  • 控制器 A 将运行操作 A
  • 控制器 B 将运行操作 A

在控制器 A 和 B 中添加动作 A 看起来不对。

由于我正在使用 AJAX 对动作 A 进行 [HttpPost] 调用,因此,我希望它位于控制器中以便于 POST 访问,尽管我不想在两个控制器中添加相同的动作

我可以在控制器 A 中添加动作 A 并让控制器 B 访问从控制器 A 请求的相同动作,但我在想什么

**如果我创建一个名为

的新控制器怎么样

commonActionContoller

并在其中放入“ACTION A”,并在需要Action A时让所有东西都使用commonActionContoller?**

干杯

编辑:添加示例如下

一个具有 Person 和 Country 的示例应用程序,因此 Person 模型对于所有国家/地区都是相同的,但我们对每个国家/地区都有不同的 Controller,因此如果管理员想要将 Person 的模型与字段 IsEmpoyed 从 true 更新为 false,那么他们会去例如 {USA}/Index 控制器并将 true 切换为 false。现在,这对于 {AUS}/Index 和 {China}/Index 是相同的,因此将 IsEmpyed 更改为 true/false 的操作在所有控制器中都是相同的。为了完成这项工作,我不想将 Action IsEmplyed 添加到所有国家/地区控制器 - (想不出更好的例子) -

【问题讨论】:

  • action a 实际上是做什么的?
  • 但问题仍然存在:如果您从ControllerAControllerB 调用CommonAction,您会从哪里返回?我的意思是,您将如何确定调用此 CommonAction 的操作?
  • 这在我看来实际上是一个 REST API 和路由设计问题。您可能会提供有关您正在谈论的路线和行动性质的更多信息。 / 将其提取到服务中无法解决哪个特定问题?
  • 好吧,我阅读该示例的方式是您无缘无故地复制控制器。根据您提供的信息,我只会重新设计路由。意思是,我将有一个带有路由"{:country}/index" 的控制器,从路由中读取country 参数并从那里开始。首先,我认为每个国家都不需要控制器。再一次,我很确定你可能想重新考虑你的 rest api / routes 设计作为第一件事。更不用说如果所有“控制器”的某些东西都相同(如果它们应该分开),那么它本身就是控制器的候选者。
  • 好吧,那么您不应该切换/复制视图而不是控制器吗?

标签: c# asp.net-mvc


【解决方案1】:

您应该在两个 Controller 中编写 Action A。否则会违反Single responsibility principle。最佳实践是将实现代码从控制器移动到服务层。例如,如果您想为产品和子类别加载产品类别,那么代码将是这样的:

public interface ICategoryService
{
    List<Category> LoadCategory();
}

public class CategoryService : ICategoryService
{
    public List<Category> LoadCategory()
    {
        //code here
    }
}

public class ProductController : Controller
{
    private readonly ICategoryService _categoryService;
    public ProductController()
    {
        _categoryService = <inject dependency here>;
    }

    public ActionResult GetCategory()
    {
        var category = _categoryService.LoadCategory();
    }
}

public class SubCategoryController : Controller
{
    private readonly ICategoryService _categoryService;
    public SubCategoryController()
    {
        _categoryService = <inject dependency here>;
    }

    public ActionResult GetCategory()
    {
        var category = _categoryService.LoadCategory();
    }
}

【讨论】:

  • 我将不得不将我的 3 个动作重复到 8 个不同的控制器中 - 这不只是额外的代码行 - 可能有更好的方法来处理这个问题?在 8 个不同的控制器上重复相同的操作听起来是不对的。你有什么想法
  • 创建一个额外的服务层。
  • 我想我解释得不好 - 抱歉,我确实有一个服务层,但问题是我仍然必须从我的操作中调用该服务层,例如在下面的代码 [HttpPost] public ActionResult GetAccess(string accessCode) { var userToken = User.Identity.GetUserToken(); string errorMessage; if (!_userService.ClaimAccessCode(accessCode, userToken, out errorMessage)) Do something } 所以我仍然必须在每个控制器上添加 ACTION A 才能访问服务层
  • 代码优化并不总是好的。优化后,您可能会理解您的代码。但其他人必须面临理解您的代码的困难。
  • 好的,谢谢,是的,我所有的代码都在控制器之外,我只是从控制器操作中调用它
【解决方案2】:

这里的指导原则应该是关注点分离。

如果 ControllerA 和 ControllerB 具有特定的业务逻辑,并且添加 CommonActions 控制器可以为共享数据提供一个良好的隔离主页,这是一个很好的做法。

虽然很难回答,但没有更好地说明您的需求。

一个稍微好一点的例子可能是订单应用程序:

库存控制器 员工控制器

您可能不想要具有以下方法的 CommomController:

GetStoreClosingHours(int storeNumber);
GetTotalSales(int employeeId);
GetEmployeeComps(int employeeId);

IoC 和依赖注入也可能得到回报,具体取决于操作。任何控制器都可以调用如下方法:

GetLastLogonTime(thisEmployee);

毕竟,它实际上是一组设计您的应用程序的原则,最佳实践并不总是非常整齐地打包。我想说最重要的是选择灵活、可扩展的东西,然后坚持下去。

【讨论】:

  • 这是有道理的,一个具有个人和国家的示例应用程序,所以个人模型对于所有国家都是相同的,但我们对每个国家都有不同的控制器,所以如果管理员想要使用字段 @ 更新个人模型987654323@ 从 truefalse 然后他们转到例如 {USA}/Index 控制器并将 true 切换为 false。现在,这对于 {AUS}/Index 和 {China}/Index 是相同的,因此将 IsEmpyed 更改为 true/false 的操作在所有控制器中都是相同的。为了完成这项工作,我不想将 Action IsEmplyed 添加到所有国家/地区控制器 - (想不出更好的例子)
  • 在那种情况下...... IoC 或继承可能是一个很好的中间地带......虽然国家真的与就业有关吗? HrController 可能很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 2018-09-24
  • 1970-01-01
相关资源
最近更新 更多