Mat*_*zen 5 c# routing asp.net-core
在ASP .NET Core中,如何给路由(例如/api/users/28)来查看将使用哪个控制器以及将使用哪个动作?例如,在这种情况下,它将是UsersController它的Get(int id)动作。
如果有一种方法可以告诉我这点,我很乐意,这样我就不必自己复制内部路由系统。我只是无法使用ASP .NET Core路由上的官方文档来找到它。
编辑1我的问题不是重复的。我不在寻找确定路由是否存在的选项-我想知道什么确切的动作和控制器会处理它。
编辑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);
Run Code Online (Sandbox Code Playgroud)
它看起来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;
}
Run Code Online (Sandbox Code Playgroud)
它首先尝试通过模板匹配所有路由。它称为IActionSelector,它会完成其余的工作。你可以这样使用它:
var action = GetMatchingAction("/api/users/28", "GET"); // will return null if no matching route found
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1308 次 |
| 最近记录: |