WebApi使用RouteAttribute或隐式路由时的路径差异

时间:2016-04-22 15:36:09

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

我一直在使用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;
}

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

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

我已经在网上找到了尽可能多的ApiExplorer,WebAPI和其他文档,但我还没有找到解决方案来使隐式/显式路由方法同质化。它甚至可能是实施中的一个错误。

我应该从哪里离开?

1 个答案:

答案 0 :(得分:0)

所以这里的答案是Web Api 2存在错误或不一致 要进行验证,您可以运行此代码段。在我提到的情况下,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();
        }