【问题标题】:WebApi Path differences when using RouteAttribute or implicit routing使用 RouteAttribute 或隐式路由时的 WebApi 路径差异
【发布时间】:2016-04-22 15:36:08
【问题描述】:

我一直在使用 WebApi,我试图了解使用路由属性与让 WebApi 根据函数名称自动创建路由的区别。我有很多这种形式的控制器:

public class MyController : RestControllerBase
{
    public async Task<HttpResponseMessage> GetData()
    {
        return _data;
    }

    [Route(ApiVersion.Version + "/MyController/{param}/specific/route")]
    public async Task<HttpResponseMessage> GetMoreData()
    {
        return _moreData;
    }
}

这个控制器和其他控制器都指定了一个路由注册表:

routingManager.RegisterVersionedHttpRoute(
                routeName: "MyController",
                routeTemplate: "MyController/{param}",
                defaults: new { controller = "MyController", param = RouteParameter.Optional },
                version: ApiVersion.Version);

当我构建和测试我的 API 时,两个端点都可以正确访问。

我还用一个基于命名空间的 HttpControllerSelector 覆盖(用于版本控制)。

我的问题是这两个路由,除了被特定的 http 路由调用的传统功能外,表现不同。例如,在我重写的控制器选择器中,我必须编写此逻辑以使控制器和路由正确映射:

private string GetControllerName(IHttpRouteData routeData)
{
    if (routeData.GetSubRoutes() != null)
    {
        // With route attribute
        var subroute = routeData.GetSubRoutes().FirstOrDefault();
        var dataTokenValue = subroute.Route.DataTokens["actions"];
        if (dataTokenValue == null) return null;
        var controllername = ((HttpActionDescriptor[])dataTokenValue).First().ControllerDescriptor.ControllerName.Replace("Controller", string.Empty);
        return controllername;
    }
    else
    {
        // Try Strategy for without route attribute.
        return (String)routeData.Values["controller"];
    }
}

private string GetVersion(IHttpRouteData routeData)
{
    var routeTemplate = "";
    if (routeData.GetSubRoutes() != null)
    {
        var subRouteData = routeData.GetSubRoutes().FirstOrDefault();
        if (subRouteData == null) return null;
        routeTemplate = subRouteData.Route.RouteTemplate;
    }
    else
    {
        routeTemplate = routeData.Route.RouteTemplate;
    }

    var index = routeTemplate.IndexOf("/");
    if (index == -1)
    {
        return Unversioned;
    }
    var version = routeTemplate.Substring(0, index).ToUpperInvariant();
    return version;
}

似乎具有显式属性的路由将具有可用的 route.GetSubroutes(),而隐式路由则不会。 这导致我编写了两种不同的方法来从传入请求中提取版本和控制器名称,然后才能正确路由它们。我可以忍受这一点,但 WebApi 内部的某些东西在路由之间造成了这种区别,这真的让我很困扰。

不幸的是,我随后开始使用 https://github.com/domaindrivendev/Swashbuckle 来记录我的 api 并遇到了类似的问题。 swagger 页面为具有 Route 属性的路由正确生成,但完全忽略了隐式路由。我怀疑导致此问题的问题与导致我的选择逻辑中的分支相同。

我一直在研究尽可能多的在线 ApiExplorer、WebAPI 和其他文档,但我一直无法找到使隐式/显式路由方法同质化的解决方案。这甚至可能是他们实现中的一个错误。

我应该从这里去哪里?

【问题讨论】:

    标签: c# .net asp.net-web-api routing


    【解决方案1】:

    所以这里的答案是 Web Api 2 存在错误或不一致 要验证,您可以运行此代码 sn -p。在我提到的情况下,ApiExplorer 不会返回未明确标记有路由属性的路径的结果。

            IApiExplorer apiExplorer = configuration.Services.GetApiExplorer();
            foreach (ApiDescription api in apiExplorer.ApiDescriptions)
            {
                Console.WriteLine("Uri path: {0}", api.RelativePath);
                Console.WriteLine("HTTP method: {0}", api.HttpMethod);
                foreach (ApiParameterDescription parameter in api.ParameterDescriptions)
                {
                    Console.WriteLine("Parameter: {0} - {1}", parameter.Name, parameter.Source);
                }
                Console.WriteLine();
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-24
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-26
      • 1970-01-01
      相关资源
      最近更新 更多