如何使用不同的参数为同一个Controller方法设置不同的路由?

时间:2017-07-28 07:59:08

标签: c# asp.net asp.net-core routing

我有一个看起来像这样的ReportController:

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

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

我尝试做一些路由,但失败了。用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?}");
            });

正如我所见,我需要匹配以下网址:
第一个和第一个 / Report / ReportDetails?reportId = 7 / Report / ReportDetails?reportId = 7& approved = True for second

4 个答案:

答案 0 :(得分:0)

您可以按照此link了解路由

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

答案 1 :(得分:0)

您可以创建ActionMethodSelectorAttribute。在您的控制器中,您可以将属性添加到两个方法中,以便将正确的方法与URL匹配。

例如,您可以制作一个ParameterExistsAttribute来确定该方法是否合适,然后使用

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

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

关于如何实现这种属性的难题仍然是读者的练习。 (这并不困难。)

这里的示例是一个根据参数值选择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);
  }
}

答案 2 :(得分:0)

你不能这样做,就像有两个方法具有相同名称和不同参数一样,因为你应该得到 AmbiguousActionException

ASP核心操作选择器在选择操作期间不关心Action的参数。因此,您无法对应一个路径模板执行2个操作。唯一的解决方法是使用动作约束(如HttpGet和HttpPost)。 你可以check it yourself on GitHub。 (参见 SelectBestCandidate 方法)

理论上,如果参数很重要,基于参数的动作之间的选择逻辑应该在 SelectBestActions 方法中,但它会忽略参数。

在你的情况下,好的选择似乎只有一个方法:

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

然后检查被批准是否为NULL( / Report / ReportDetails?reportId = 7 ),然后实现第一个逻辑,否则( / Report / ReportDetails?reportId = 7& approved = True )实现第二个逻辑。如果逻辑包含许多行,您可以用新方法提取它们并调用它。

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)
}

答案 3 :(得分:0)

您可以使用RouteAttribute

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

您的网址将是;

/ Report / ReportDetails / 7表示第一个和

/ Report / ReportDetails / 7 / True for second

这适用于默认的startup.cs

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