22

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

Microsoft.AspNet.WebApi.HelpPage

SDammann.WebApi.Versioning

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

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

版本控制按预期工作。

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

Configuration.Services.GetApiExplorer().ApiDescriptions

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

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

编辑: 一开始,我不确定这是一个路由问题,但最近的评论似乎表明并非如此。这是我的 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 }
        );
    }
}
4

3 回答 3

11

您需要从 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>
}

这应该可以解决问题!

于 2013-05-03T09:08:40.953 回答
4

我不知道如何对帖子发表评论:(我认为这可能应该是在这个问题的标记答案下的评论,但 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 的说明更改处理程序后立即执行此操作。

于 2013-05-22T20:13:43.857 回答
1

我同意@mortware,web api 的默认路由意味着如果您使用默认Get()/Post()方法,您的 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*/ }

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

于 2013-02-18T18:01:00.117 回答