如何在ASP.NET Core中的ActionSelector中检索RouteValues

时间:2017-06-20 07:02:56

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

我已经创建了一个GitHub repo来更好地理解这里的问题。我在绑定到同一路径的两个不同控制器上有两个动作。

foo map bar

由于存在两个匹配的路由,因此默认的ActionSelector失败并显示:

  

'[...] AmbiguousActionException:匹配多个动作。 [...]”   这是可以理解的。

所以我想我可以实现我的own ActionSelector。在那里,我将实现逻辑,通过相同的逻辑解决多个路由的问题,具体取决于'标识符'路由值(代码中的line 27

如果'标识符'值是a - >然后是FirstController

如果'标识符'值为b - >然后是SecondController

依旧......

http://localhost/sameControllerRoute/{identifier}/values

[Route("sameControllerRoute")]
public class FirstController : Controller
{
    public FirstController()
    {
        // different EF Core DataContext than SecondController and possibly other dependencies than SecondController
    }

    [HttpGet("{identifier}/values")]
    public IActionResult Values(string identifier, DateTime from, DateTime to) // other parameters than SecondController/Values
    {
        return this.Ok("Was in FirstController");
    }
}

[Route("sameControllerRoute")]
public class SecondController : Controller
{
    public SecondController()
    {
        // different EF Core DataContext than FirstController and possibly other dependencies than FirstController
    }

    [HttpGet("{identifier}/values")]
    public IActionResult Values(string identifier, int number, string somethingElse) // other parameters than FirstController/Values
    {
        return this.Ok("Was in SecondController");
    }
}

但是我没有找到一个很好的解决方案来获取ActionSelector中的路由值。这也是可以理解的,因为ModelBinding还没有开始,因为MVC仍在试图找出路线。

一个肮脏的解决方案可能是以某种方式抓住 protected override IReadOnlyList<ActionDescriptor> SelectBestActions(IReadOnlyList<ActionDescriptor> actions) { if (actions.HasLessThan(2)) return base.SelectBestActions(actions); // works like base implementation foreach (var action in actions) { if (action.Parameters.Any(p => p.Name == "identifier")) { /*** get value of identifier from route (launchSettings this would result in 'someIdentifier') ***/ // call logic that decides whether value of identifier matches the controller // if yes return new List<ActionDescriptor>(new[] { action }).AsReadOnly(); // else // keep going } } return base.SelectBestActions(actions); // fail in all other cases with AmbiguousActionException } 和正则表达式。

但是我仍然希望你能提供一个更好的想法来检索路由值,即使ModelBinding还没有在请求管道中发生。

2 个答案:

答案 0 :(得分:0)

不确定您是否需要根据场景使用ActionSelector。因此,对于提供的代码,您的控制器使用不同类型的资源(因此他们期望不同的查询参数)。因此,最好使用不同的路由模板。像这样的东西:

  • FirstController:/sameControllerRoute/resourceA/{identifier}/values
  • SecondController:/sameControllerRoute/resourceB/{identifier}/values

在REST的范围内,当我们讨论/sameControllerRoute/{identifier}/values路由模板时,我们希望不同的identifier表示相同的资源类型,但资源名称不同。因此,作为API使用者,我们希望支持所有以下请求

/sameControllerRoute/a/values?from=20160101&to=20170202
/sameControllerRoute/b/values?from=20160101&to=20170202

/sameControllerRoute/a/values?number=1&somethingElse=someData
/sameControllerRoute/b/values?number=1&somethingElse=someData

在您的情况下情况并非如此

答案 1 :(得分:0)

我最终由ASP.NET团队实现了提议的solution。这是为了实现IActionConstrain,如下所示:

//displayText

https://github.com/aspnet/Entropy/blob/dev/samples/Mvc.ActionConstraintSample.Web/CountrySpecificAttribute.cs