c# - 查看将从路由执行哪个 Controller 和操作?

标签 c# asp.net-core routing

在 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/

相关文章:

c# - 查看我的 ASP.NET 身份验证代码

c# - 从 React Native 访问 ASP.NET Core 2.1 Web API 时“无法验证 HTTPS 连接”

Angular 2复杂的嵌套路由

c# - ASP.NET MVC 5 中的路由可选参数

c# - 一个表可以通过等号复制到另一个表吗?如果没有,那又如何呢?

c# - 通过网络在应用程序之间进行通信

c# - 如何防止用户登录多个设备以及如何从之前的设备结束 session ?

ASP.NET Core EF6 身份

angular - 通过 Angular 中的路由路径发送数据

c# - 从 Word 中删除不需要的分节符?