在 ASP .NET Core 中,如何给定路由(例如 /api/users/28
)查看将使用哪个 Controller 以及将使用哪个操作?例如,在这种情况下,它将是 UsersController
及其 Get(int id)
操作。
如果有一种方法可以访问某种可以告诉我这一点的路由器,我会很高兴,这样我就不必自己复制内部路由系统了。我只是无法使用有关 ASP .NET Core 路由的官方文档找到它。
编辑 1 我的问题不是重复的。我不是在寻找确定路线是否存在的选项 - 我想知道确切的操作和 Controller 将处理它。
编辑 2 这是我当前的代码以及我尝试过的代码:
var httpContext = new DefaultHttpContext();
httpContext.Request.Path = "/api/users/28";
httpContext.Request.Method = "GET";
var context = new RouteContext(httpContext);
//throws an exception: AmbiguousActionException: Multiple actions matched.
var bestCandidate = _actionSelector.SelectBestCandidate(context,
_actionDescriptorCollectionProvider.ActionDescriptors.Items);
最佳答案
看起来 IActionSelector
只匹配 HTTP 方法等,完全忽略路由模板。
感谢Sets回答和https://blog.markvincze.com/matching-route-templates-manually-in-asp-net-core/ ,我想出了以下解决方案:
public ManualActionSelector(IActionSelector actionSelector, IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
{
_actionSelector = actionSelector;
_actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;
}
public ActionDescriptor GetMatchingAction(string path, string httpMethod)
{
var actionDescriptors = _actionDescriptorCollectionProvider.ActionDescriptors.Items;
// match by route template
var matchingDescriptors = new List<ActionDescriptor>();
foreach (var actionDescriptor in actionDescriptors)
{
var matchesRouteTemplate = MatchesTemplate(actionDescriptor.AttributeRouteInfo.Template, path);
if (matchesRouteTemplate)
{
matchingDescriptors.Add(actionDescriptor);
}
}
// match action by using the IActionSelector
var httpContext = new DefaultHttpContext();
httpContext.Request.Path = path;
httpContext.Request.Method = httpMethod;
var routeContext = new RouteContext(httpContext);
return _actionSelector.SelectBestCandidate(routeContext, matchingDescriptors.AsReadOnly());
}
public bool MatchesTemplate(string routeTemplate, string requestPath)
{
var template = TemplateParser.Parse(routeTemplate);
var matcher = new TemplateMatcher(template, GetDefaults(template));
var values = new RouteValueDictionary();
return matcher.TryMatch(requestPath, values);
}
// This method extracts the default argument values from the template. From https://blog.markvincze.com/matching-route-templates-manually-in-asp-net-core/
private RouteValueDictionary GetDefaults(RouteTemplate parsedTemplate)
{
var result = new RouteValueDictionary();
foreach (var parameter in parsedTemplate.Parameters)
{
if (parameter.DefaultValue != null)
{
result.Add(parameter.Name, parameter.DefaultValue);
}
}
return result;
}
它首先尝试通过模板匹配所有路由。它调用 IActionSelector
,剩下的由它来完成。你可以像这样使用它:
var action = GetMatchingAction("/api/users/28", "GET"); // will return null if no matching route found
关于c# - 查看将从路由执行哪个 Controller 和操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46038337/