Подтвердить что ты не робот

Как получить ASP.NET Web API, работающий с версиями и расширением страницы справки?

Я внедрил систему управления версиями в свое приложение WebAPI и очень хотел бы, чтобы она работала с новым расширением страницы справки из Microsoft.

Microsoft.AspNet.WebApi.HelpPage

SDammann.WebApi.Versioning

Проще говоря, я не знаю, как заставить их работать вместе. У меня есть 2 проекта:

  • AdventureWorks.Api(основное приложение хоста/корня)
  • AdventureWorks.Api.v1 (библиотека классов, содержащая первую версию API)

Управление версиями работает так, как ожидалось.

Я попытался установить пакет HelpPage в корневом приложении, и когда я перейду на страницу справки, похоже, что ни один из контроллеров не найден. Внутри я считаю, что он использует:

Configuration.Services.GetApiExplorer().ApiDescriptions

Это не возвращает никаких результатов, поэтому я получаю сообщение об ошибке.

Может ли кто-нибудь помочь мне в совместном использовании обоих этих пакетов?

Edit: Вначале я не был уверен, что это проблема маршрутизации, но последние комментарии, похоже, говорят о другом. Вот мой 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 }
        );
    }
}
4b9b3361

Ответ 1

Вам нужно получить XML файл документации из проекта Project AdventureWorks.Api.v1 и поместить его в папку bin проекта AdventureWorks.Api:

Затем добавьте эти строки в свой метод 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, и он отлично работает. Надеюсь, что это поможет значительно облегчить решение.

EDIT: Я понял, пытаясь снова помочь мне в том, что мой ответ не был очевиден.

ТОЛЬКО, что вам нужно сделать, чтобы получить рабочие страницы справки, заменяет глобальные конфигурации IApiExplorer, что он. Просто сделайте это сразу после того, как вы измените инструкцию для инструкций sdammans.

Ответ 3

Я согласен с @mortware, стандартная маршрутизация для web api означает, что ваш url должен выглядеть примерно так: "site/api/controllerName/", если вы используете методы Get()/Post() по умолчанию. Если вы используете специально названные методы, маршрут выглядит примерно так: "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, чтобы помочь вам точно определить причину