简体   繁体   English

如何为具有不同参数的同一Controller方法设置不同的路由?

[英]How to set different routes for the same Controller method with different parameters?

I have the ReportController that llooks like this: 我有看起来像这样的ReportController:

public IActionResult ReportDetails(int? reportId){
    ....
}

and

public IActionResult ReportDetails(int? reportId, bool ? approved) {
    ....
}

and I tried to do some routing, bu it failed. 我尝试做一些路由,但失败了。 Actual code written in Startup.cs: 用Startup.cs编写的实际代码:

app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "ReportDetailsValidation",
                    template: "descriptionValidation",
                    defaults: new { controller = "Report", action = "ReportDetails", reportId ="{reportId}", approved = "{approved}" }
                    );

                routes.MapRoute(
                    name: "ReportDetails",
                    template: "description",
                    defaults: new { controller = "Report", action = "ReportDetails"} 
                    );

                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

As I have seen I need to match the following URL's: 如我所见,我需要匹配以下URL:
/Report/ReportDetails?reportId=7 for the first and / Report / ReportDetails?reportId = 7为第一个
/Report/ReportDetails?reportId=7&approved=True for second / Report / ReportDetails?reportId = 7&approved =真是

You can follow this link to understand routing 您可以点击此链接了解路由

[HttpGet("Report/ReportDetails/{reportId}")] 
[HttpGet("Report/ReportDetails/{reportId}/{approved}")]
public IActionResult ReportDetails(int? reportId, bool? approved) {
....
}

You can create an ActionMethodSelectorAttribute . 您可以创建一个ActionMethodSelectorAttribute In your controller you can add your attribute to both methods to enable matching the correct method to the URL. 在控制器中,您可以将属性添加到两个方法中,以使正确的方法与URL匹配。

You could for example make a ParameterExistsAttribute that decides if the method is suitable and then use 例如,您可以创建一个ParameterExistsAttribute来确定该方法是否合适,然后使用

[ParameterExists('approved', false)]
public IActionResult ReportDetails(int? reportId){
    ....
}

[ParameterExists('approved', true)]
public IActionResult ReportDetails(int? reportId, bool ? approved) {
    ....
}

The puzzle on how to implement such an attribute remains an exercise to the reader. 有关如何实现此类属性的难题仍然是读者的一项练习。 (It's not so difficult.) (不是那么困难。)

As an example here's an attribute that selects an API call, based on the value of a parameter. 举例来说,这是一个根据参数值选择API调用的属性。

public class FormPostFilterAttribute : ActionMethodSelectorAttribute
{
  private readonly string _elementId;
  private readonly string _requiredValue;

  public FormPostFilterAttribute(string elementId, string requiredValue)
  {
    _elementId = elementId;
    _requiredValue = requiredValue;
  }

  public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
  {
    if (string.IsNullOrEmpty(controllerContext.HttpContext.Request.Form[_elementId]))
    {
      return false;
    }

    return (controllerContext.HttpContext.Request.Form[_elementId] == _requiredValue);
  }
}

You can't do that, like have 2 methods with identical name with different parameters, because you should get AmbiguousActionException . 您不能那样做,就像有两个名称相同但参数不同的方法一样,因为您应该获得AmbiguousActionException

ASP Core Action Selector does not care about Action's parameters during select action. 在选择操作期间,ASP核心操作选择器不关心操作的参数。 Therefore you can't have 2 actions correspond one route template. 因此,您不能有2个动作对应一个路由模板。 The only workaround is to play with action constraints (like HttpGet and HttpPost). 唯一的解决方法是使用操作约束(例如HttpGet和HttpPost)。 You can check it yourself on GitHub . 您可以在GitHub上自行检查 (See SelectBestCandidate method) (请参见SelectBestCandidate方法)

Theoretically if parameters matters the logic to choose between actions based on parameters should be in SelectBestActions method, but it ignores parameters. 从理论上讲,如果参数很重要,则应在SelectBestActions方法中使用基于参数在操作之间进行选择的逻辑,但它将忽略参数。

In you case good option seems to be to have just 1 method: 在您的情况下,好的选择似乎只有一种方法:

public IActionResult ReportDetails(int? reportId, bool? approved) {
    ....
}

and then check if approved is NULL ( /Report/ReportDetails?reportId=7 ), then implement 1st logic, otherwise( /Report/ReportDetails?reportId=7&approved=True ) implement 2nd logic. 然后检查是否认可的数据为NULL( / Report / ReportDetails?reportId = 7 ),然后执行第一种逻辑,否则( / Report / ReportDetails?reportId = 7&approved = True )实现第二种逻辑。 If logic contains many lines you can extract them in new method and call it. 如果逻辑包含许多行,则可以在新方法中提取它们并调用它。

public IActionResult ReportDetails(int? reportId, bool? approved) {
     if (approved != null)
     {
        //implement logic for 2nd case(approved=True)
     }
     //implement logic for 1st case (just reportId=7)
}

You could use RouteAttribute 您可以使用RouteAttribute

[Route("ReportDetails/{reportId}")]
public IActionResult ReportDetails(int? reportId){
....
[Route("ReportDetails/{reportId}/{approved}")]
public IActionResult ReportDetails(int? reportId, bool ? approved) {
....

Your URLs would then be; 您的网址应为;

/Report/ReportDetails/7 for the first and / Report / ReportDetails / 7,第一个和

/Report/ReportDetails/7/True for second / Report / ReportDetails / 7 / True秒

This will work with the default startup.cs 这将与默认的startup.cs一起使用

app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SetActualResponseType使用相同方法在同一控制器中使用不同的路由 - SetActualResponseType with same method in the same controller with different routes 不同路由的同一控制器中的 AmbiguousActionException - AmbiguousActionException in same controller for different routes 如何在同一控制器的不同路由中封装通用请求处理 - How to encapsulate common request handling in different routes in same controller 将两条不同的路线映射到同一控制器动作 - Map two different routes to the same controller action 在同一控制器上调用不同方法的控制器方法 - A controller method that calls a different method on the same controller WebAPI控制器相同的动作不同的参数 - WebAPI controller same action different parameters 使用不同的参数调用相同的方法-如何使用多线程? - Calling same method with different parameters - How to use multithreading? 如何使用Moq为不同的参数设置两次方法 - How to set up a method twice for different parameters with Moq 具有相同动作名称和不同参数的C#MVC路由 - C# MVC Routes with same action name and different parameters 如何在同一个控制器中使用不同的参数调用不同的GET方法? - How can I call different GET Methods in the same Controller utilizing different parameters?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM