【问题标题】:How do I get ASP.NET Web API working with versioning and the Help Page extension?如何让 ASP.NET Web API 与版本控制和帮助页面扩展一起使用?
【发布时间】:2014-04-09 00:06:49
【问题描述】:

我已经在我的 WebAPI 应用程序中实现了一个版本控制框架,并且非常希望让它与 Microsoft 的新帮助页面扩展程序一起使用。

Microsoft.AspNet.WebApi.HelpPage

SDammann.WebApi.Versioning

很简单,我不知道如何让它们一起工作。我有 2 个项目:

  • AdventureWorks.Api(主主机/根应用程序)
  • AdventureWorks.Api.v1(包含 API 第一版的类库)

版本控制按预期工作。

我尝试在根应用程序上安装 HelpPage 包,当我浏览到帮助页面时,似乎没有找到任何控制器。在内部我相信它使用:

Configuration.Services.GetApiExplorer().ApiDescriptions

这不返回任何结果,所以我得到一个错误。

谁能帮助我让这两个包一起工作?

编辑: 一开始,我不确定这是一个路由问题,但最近的 cmets 似乎另有建议。这是我的 RouteConfig.cs

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapHttpRoute(
            name: "SldExportAliasApi",
            routeTemplate: "api/v{version}/sld-export/{id}",
            defaults: new { id = RouteParameter.Optional, controller = "Export" }
        );

        routes.MapHttpRoute(
            name: "LinkRoute",
            routeTemplate: "api/v{version}/link/{system}/{deployment}/{view}",
            defaults: new { controller = "Link" }
        );

        routes.MapHttpRoute(
             name: "DefaultSubParameterApi",
             routeTemplate: "api/v{version}/{controller}/{id}/{param}",
             defaults: new { id = RouteParameter.Optional, param = RouteParameter.Optional }
        );

        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/v{version}/{controller}/{action}/{id}",
            defaults: new { action = "Index", id = RouteParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

【问题讨论】:

  • 由于找不到我要查找的 API,它自然会返回 404,即 /help/myapi 尝试查找名为“myapi”的控制器。由于 ApiExplorer 不包含这样的控制器,因此会出错。
  • 使用默认的 HelpPage 安装,您将无法请求“/help/myapi”,因为帮助页面注册的路由如下所示,而且这里的帮助是一个 MVC 控制器......我我错过了什么?: context.MapRoute( "HelpPage_Default", "Help/{action}/{apiId}", new { controller = "Help", action = "Index", apiId = UrlParameter.Optional });
  • 实际路由如下所示:'/help/api/{mycontrollername}' 注册在路由中。问题是当 HelpPage 扩展程序试图找到一个名为“{mycontrollername}”的控制器时却找不到。
  • 你能发布你的完整路线配置吗?
  • 愚蠢的问题,您的入口点是名为 GetWhatever 还是 PostWhatever,等等。或者至少用HttpPost/HttpGet等装饰?

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


【解决方案1】:

您需要从您的 AdventureWorks.Api.v1 项目中获取一个文档 XML 文件,并将其放在 AdventureWorks.Api 项目的 bin 文件夹中:

然后将这些行添加到您的 Application_Start 方法中:

// enable API versioning
        GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new RouteVersionControllerSelector(GlobalConfiguration.Configuration));
        GlobalConfiguration.Configuration.Services.Replace(typeof(IApiExplorer), new VersionedApiExplorer(GlobalConfiguration.Configuration));
        GlobalConfiguration.Configuration.Services.Replace(typeof(IDocumentationProvider),
                                new XmlCommentDocumentationProvider(System.IO.Path.GetDirectoryName(
                                    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) +
                                                                    "\\Adventure.Api.v1.XML"));

然后您可以查看您的 API 与文档。

有时无法正确获取版本号,并替换为???

要解决这个问题:

if (api.ActionDescriptor.ControllerDescriptor.ControllerType.Namespace != null)
    {
        var versionName = api.ActionDescriptor.ControllerDescriptor.ControllerType.Namespace.Replace(".Controllers", "").Split('.').Last();
        api.RelativePath = api.RelativePath.Replace("v???", versionName);
    }

到你的 ApiGroup.cshtml 就在这个地方:

@foreach (var api in Model)
{
    if (api.ActionDescriptor.ControllerDescriptor.ControllerType.Namespace != null)
    {
        var versionName = api.ActionDescriptor.ControllerDescriptor.ControllerType.Namespace.Replace(".Controllers", "").Split('.').Last();
        api.RelativePath = api.RelativePath.Replace("v???", versionName);
    }
    <tr>
        <td class="api-name"><a href="@Url.Action("Api", "Help", new { apiId = api.GetFriendlyId() })">@api.HttpMethod.Method @api.RelativePath</a></td>
        <td class="api-documentation">
        @if (api.Documentation != null)
        {
            <p>@api.Documentation</p>
        }
        else
        {
            <p>No documentation available.</p>
        }
        </td>
    </tr>
}

这应该可以解决问题!

【讨论】:

  • 这是一个很好的解决方案——我认为它做不到!感谢您抽出宝贵时间对此进行调查。
【解决方案2】:

我不知道如何对帖子发表评论 :( 我认为这可能应该是该问题的标记答案下的评论,但 SDamman 已更新,我需要做的就是这个

// enable API versioning                   
GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Dispatcher.IHttpControllerSelector), 
     new SDammann.WebApi.Versioning.RouteVersionedControllerSelector(GlobalConfiguration.Configuration));

GlobalConfiguration.Configuration.Services.Replace(typeof(IApiExplorer), new SDammann.WebApi.Versioning.VersionedApiExplorer(GlobalConfiguration.Configuration));

有一种名为 VersionedApiExplorer 的类型,它工作得很好。希望这有助于解决方案现在变得更容易。

编辑: 在尝试寻求帮助后,我意识到我的答案根本不明显。

要使帮助页面正常工作,您唯一需要做的就是替换全局配置 IApiExplorer,仅此而已。只需按照 sdammans 的说明更改处理程序后立即执行此操作即可。

【讨论】:

    【解决方案3】:

    我同意@mortware,如果您使用默认的Get()/Post() 方法,Web api 的默认路由意味着您的 url 应该看起来像“site/api/controllerName/”。如果您使用的是特定命名的方法,则该路由类似于“site/api/controllerName/methodName”。

    我也遇到了参数名称的困难。例如,如果在 /App_Start/WebApiConfig.cs 中指定的路线中有;

    // Controller with ID
    // To handle routes like `/api/VTRouting/1`
    config.Routes.MapHttpRoute(
        name: "ControllerAndId",
        routeTemplate: "api/{controller}/{id}",
        defaults: null,
        constraints: new { id = @"^\d+$" } // Only integers 
    );
    
    // Controllers with Actions
    // To handle routes like `/api/VTRouting/route`
    config.Routes.MapHttpRoute(
        name: "ControllerAndAction",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: null,
        constraints: new { id = @"^\d+$" } // Only integers 
    );
    

    那么你的http动词的方法参数必须有一个名为“id”的参数,例如;

    // url: site/api/controller/<int>
    public HttpResponseMessage Get(int id) { return null; /*dummy*/ }
    
    // url: site/api/controller/<int>
    public HttpResponseMessage Post(int id) { return null; /*dummy*/ }
    
    // url: site/api/controller/SomeAction/<int>
    public HttpResponseMessage SomeAction(int id) { return null; /*dummy*/ }
    

    如果你有类似的东西;

    public HttpResponseMessage Get(int myID) { return null; /*dummy*/ }
    

    它将不起作用,因为“myID”参数与路由中指定的{id} 不匹配。正如@OakNinja 指出的那样,我们需要您在 WebApiConfig.cs 中的路由来帮助您查明确切原因

    【讨论】:

      猜你喜欢
      • 2014-10-11
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-08
      • 2015-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多