【发布时间】:2017-05-19 16:20:34
【问题描述】:
是否可以使用 ASP.NET Core MVC 路由器来确定是否可以成功重定向到特定位置?
我想注入 MVC 路由器并询问它,如果我想使用的路由是否存在,但我正在努力寻找要注入的正确类并且在 MVCRouter 中没有看到任何使用方法.
我也可以覆盖默认路由器并使用必要的方法对其进行扩展。
【问题讨论】:
标签: asp.net-core-mvc
是否可以使用 ASP.NET Core MVC 路由器来确定是否可以成功重定向到特定位置?
我想注入 MVC 路由器并询问它,如果我想使用的路由是否存在,但我正在努力寻找要注入的正确类并且在 MVCRouter 中没有看到任何使用方法.
我也可以覆盖默认路由器并使用必要的方法对其进行扩展。
【问题讨论】:
标签: asp.net-core-mvc
一种方法是将IActionSelector 注入到您的组件中。
该组件负责控制器动作选择,并且可以告诉您是否存在具有给定参数的路由(即使存在模棱两可的匹配)。
public class HomeController : Controller
{
private readonly IActionSelector _actionSelector;
public HomeController(IActionSelector actionSelector)
{
_actionSelector = actionSelector;
}
public IActionResult Index()
{
var routeData = new RouteData();
routeData.Values["action"] = "DoesNotExist";
routeData.Values["controller"] = "Home";
var routeContext = new RouteContext(HttpContext)
{
RouteData = routeData
};
IReadOnlyList<ActionDescriptor> candidates = _actionSelector.SelectCandidates(routeContext);
if (candidates == null || candidates.Count == 0)
{
//No actions matched
}
else
{
try
{
var actionDescriptor = _actionSelector.SelectBestCandidate(routeContext, candidates);
if(actionDescriptor == null)
{
//No action matched
}
//Action matched
}
catch (AmbiguousActionException)
{
//More than 1 action matched
}
}
return View();
}
}
这基本上就是MvcRouteHandler 所做的。首先找到所有可能的候选人,然后将其过滤到最佳候选人。如果它发现多个异常,它可能会抛出一个异常,你可能想要也可能不想处理。
我想如果你可以通过扩展一个组件来改变行为以某种方式更容易做到这一点,但是MvcRouteHandler 并不是那么容易扩展。如果没有操作匹配,它当前只记录一条消息,这不会影响返回值。而且我们不能真正改变那里的签名。
【讨论】:
IRouter,后者实现 RouteAsync(),这将在RouteContext-Object 中填充RouteData。但是创建IRouter 似乎很昂贵。关于这一点,如果路线存在(或至少仅出于学术目的),我可能不应该尝试检测......
RouteData,它在被RouteBase 命中之前完成,它调用TemplateMatcher 进行匹配。您实际上可以通过 HttpContext 访问IRoutingFeature,在中间件或任何地方访问填充的RouteData。您必须在 RouterMiddleware 运行后执行此操作,这将非常棘手,因为这实际上是调用 MVC 处理程序来调用您的操作的事情。