【问题标题】:Multiple URLs same action method多个 URL 相同的操作方法
【发布时间】:2018-03-05 13:29:39
【问题描述】:

我需要在不同的控制器之间共享操作方法。以以下 2 个控制器为例:

public class AController : Controller
{
       public ActionResult Index()
       {
           //print AController - Index
       }

       public ActionResult Test()
       {
           //print test
       }
}

public class BController : Controller
{
     public ActionResult Index()
     {
         //print BController - Index
     }
}

两个控制器都有一个不同的 Index 方法。但是,可以从两个控制器调用 Test 方法。所以我希望在输入以下网址时执行 Test() 方法:

  • 控制器/测试
  • B 控制器/测试

我将不胜感激有关如何实现这一目标的任何建议。

【问题讨论】:

  • 两个不同的端点做同样的事情有什么意义?
  • XY Problem。您的要求是可能的,但它不太可能是您问题的最佳解决方案(无论是什么)。

标签: asp.net asp.net-mvc routing


【解决方案1】:

假设 Test() 操作的实现对于两个控制器是相同的,将其重构为一个公共服务:

public interface ITestService {
    string Test();
}

public TestService: ITestService {
    public string Test() {
        // common implementation
        return "The test result";
    }
}

然后设置Dependency Injection获取该服务。

然后您的控制器可以使用公共服务。

public class AController : Controller {

    private readonly ITestService _testService;

    public AController(ITestService testservice) {
        _testService = testservice;
    }

    public ActionResult Test() {
        var vm = new TestViewModel();
        vm.TestResult = _testService.Test();
        return View("Test", vm);
    }
}

public class BController : Controller {

    private readonly ITestService _testService;

    public BController(ITestService testservice) {
        _testService = testservice;
    }

    public ActionResult Test() {
        var vm = new TestViewModel();
        vm.TestResult = _testService.Test();
        return View("Test", vm);
    }
}

因为视图Test.cshtml 是由两个控制器渲染的,所以它应该放在Views\Shared\ 文件夹中。

【讨论】:

    【解决方案2】:

    您可以定义自己的路线,如下所述:https://docs.microsoft.com/aspnet/core/mvc/controllers/routing

    所以你可以定义尽可能多的路由指向“AController”中的“Test”方法,就像这样:

    routes.MapRoute("Atest", "AController/Test",
            defaults: new { controller = "AController", action = "Test" });
    routes.MapRoute("Btest", "BController/Test",
            defaults: new { controller = "AController", action = "Test" });
    

    但是您必须在“默认”路由之前定义它们,否则输入的 URL 将匹配默认路由条件,因此它将进入该路由。

    也可以直接在方法的顶部定义路由。

    public class AController : Controller
    {
        [Route("/Some/Route")]
        public ActionResult Test() 
        {
        }
    }
    

    【讨论】:

      【解决方案3】:

      我想提出一个替代解决方案。创建一个由其他两个继承的基本控制器类。无论你拥有什么,都会成为孩子们的一部分。

      public class BaseController : Controller
      {
          public ActionResult Index()
          {
              //print AController - Index
          }
      
          // Add more methods to be shared between the other controllers
      }
      
      public class AController : BaseController 
      {
          // Has Index method already from parent
      
          // Unique method for A
          public ActionResult Test()
          {
              //print test 1
          }
      }
      
      public class BController : BaseController
      {
          // Has Index method already from parent
      
          // Unique method for B
          public ActionResult Test()
          {
              //print test 2
          }
      }
      

      这在一个地方实现了实际功能。我们将此方法用于许多没有问题的项目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多