Swashbuckle 5 не может найти мои ApiControllers

Я нахожусь в точке, где мне действительно нужна документация по API для моего проекта WebAPI 2, и я использовал пакет NuGet Swashbuckle 5. Из коробки я могу нажать {myrooturl} / swagger, и появится пользовательский интерфейс, но там нет контроллеров, методов или чего-либо еще. Только мое название: [базовый URL: /EM.Services, версия API: v1]

Я взглянул на документацию Swashbuckle, и, поскольку я использую OWIN, размещенный на IIS, я изменил SwaggerConfig с помощью:

c.RootUrl(req => req.RequestUri.GetLeftPart(UriPartial.Authority) + req.GetRequestContext().VirtualPathRoot.TrimEnd('/'));

в соответствии с этим документом:

Я также настроил сборку проекта для создания XML-документов и указал на него свой SwaggerConfig с помощью:

    private static string GetXmlCommentsPath()
    {
        // tried with an without the \bin
        return String.Format(@"{0}\bin\EM.Services.XML", AppDomain.CurrentDomain.BaseDirectory);
    }

Я не уверен, что XML-документы, работающие / не работающие, имеют к этому какое-либо отношение, поскольку у меня нет абсолютно никаких контроллеров на странице swagger-ui.

Как бы то ни было, весь мой контроллер наследуется от BaseController, который, в свою очередь, наследуется от ApiController.

Что-то не так с моим WebApiConfig?

    public static void Register(HttpConfiguration config)
    {

        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

        config.Filters.Add(new ValidateModelAttribute());

        config.Filters.Add(new BaseAuthenticationAttribute());

        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
        jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
    }

Все мои конкретные контроллеры выглядят так (я пробовал заменить BaseController на ApiController, и изменений нет):

[RoutePrefix("api/whatever")]
public class FooController : BaseController

а мой базовый контроллер (пока) мало что делает, просто имеет атрибут:

[BuildClaims]
public abstract class BaseController : ApiController

Пустая страница сохраняется при использовании IIS Express или полнофункционального IIS.

Обновление: пример надуманного контроллера, который я сделал, который действительно прост. Он также не отображается, так как у меня все еще есть шаблонный интерфейс swagger, в котором ничего нет.

/// <summary>
/// I am a test
/// </summary>
[RoutePrefix("api/dummy")]
public class DummyController : ApiController
{
    [HttpGet]
    [Route("foo")]
    public int Foo()
    {
        return 42;
    }
}

person Bill Sambrone    schedule 05.08.2015    source источник


Ответы (11)


Я застрял ... и эти ответы мне не полностью помогли ... хотя и привели меня туда. Просто чтобы сэкономить время другим людям:

Вы должны передать http-конфигурацию из OWIN, а затем зарегистрироваться в ней вместо использования класса GlobalConfiguration следующим образом:

//starup.cs
public void Configuration(IAppBuilder app)
    {
        Config = new HttpConfiguration();
        WebApiConfig.Register(Config);

        app
            .UseResponseLogging()
            .UseRequestLogging()
            .UseHttpErrors()
            .UseExceptionLogging()
            .UseWebApi(Config);

        HandlerConfig.Register(Config);

        SwaggerConfig.Register(Config);
    }

и в файле конфигурации swagger измените метод регистрации на:

public static void Register(HttpConfiguration config)
    {
        var thisAssembly = typeof(SwaggerConfig).Assembly;

        config
            .EnableSwagger(c =>
                {...

Надеюсь это поможет.

person Sumit Maingi    schedule 08.09.2016
comment
Спасибо! Это сработало для меня, но, кроме того, мне также пришлось удалить строку в самом верху файла SwaggerConfig.cs ([assembly: PreApplicationStartMethod ...). Прежде чем я удалил его, я получал ошибку несоответствия количества параметров - person HitLikeAHammer; 01.05.2018
comment
@HitLikeAHammer После удаления строки выше я получаю 404. - person Prashant Yadav; 12.09.2018
comment
Спасибо! Мне также пришлось удалить атрибут PreApplicationStartMethod. - person inliner49er; 03.02.2019

Я нашел проблему. После создания пустого тестового проекта я заметил, что WebApiConfiguration регистрируется из запуска приложения global.asax, а не из класса запуска OWIN (как я).

Поскольку Swagger / Swashbuckle подключается к GlobalConfiguration, а также с учетом того, что запуск OWIN и Global.asax живут в разных контекстах (я думаю), исправление состоит в том, чтобы подключить ваш материал WebAPI для регистрации из Global.asax и использовать объект приложения OWIN WebAPI.

Соответствующие биты:

   // global asax
    protected void Application_Start(object sender, EventArgs e)
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
       // ... more stuff
    }

   //startup.cs
   public void Configuration(IAppBuilder app)
    {
        // This must happen FIRST otherwise CORS will not work.
        app.UseCors(CorsOptions.AllowAll);

        HttpConfiguration config = new HttpConfiguration();

        ConfigureAuth(app);

        // webapi is registered in the global.asax
        app.UseWebApi(config);

    }

После переустановки, как указано выше, теперь я могу видеть контроллеры и действия в пользовательском интерфейсе Swagger.

person Bill Sambrone    schedule 07.08.2015

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

using Swashbuckle.Application;
using System.Web.Http;

public static class SwaggerExtensions
{
    public static HttpConfiguration EnableSwagger(this HttpConfiguration httpConfiguration)
    {
        httpConfiguration
            .EnableSwagger(c => c.SingleApiVersion("v1", "A title for your API"))
            .EnableSwaggerUi();
        return httpConfiguration;
    }
}

Затем в моем Startup.cs

public class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        HttpConfiguration httpConfiguration = new HttpConfiguration();

        httpConfiguration
            .EnableSwagger()    // <==== EXTENSION METHOD <==== //
            .MapHttpAttributeRoutes();

        httpConfiguration.Routes.MapHttpRoute(
            "DefaultApi",
            "api/{controller}/{id}",
            new {id = RouteParameter.Optional});

        appBuilder
            .UseWebApi(httpConfiguration);
    }
}
person chris31389    schedule 25.07.2017
comment
Да, это сработало для меня, теперь чванство может обнаруживать контроллеры моего веб-API - person Simple Code; 18.03.2018

Все эти решения работают для меня, но все они просто неприятные уловки для моей проблемы. После нескольких часов исследования я обнаружил, что проблема в том, что я также использую Glimpse (или другие пакеты, которые меняют таблицу маршрутов).

Вот отличное резюме: https://github.com/domaindrivendev/Swashbuckle/issues/468#issuecomment-139246748

  1. Glimpse добавляет прокси замка поверх HttpWebRoute. Итак, HostedHttpRouteCollection - это коллекция RouteProxy, а не HttpWebRoute.
  2. В классе APIExplorer есть метод FlattenRoutes, который выполняет цикл foreach через HostedHttpRouteCollection.
  3. Реализация GetEnumerator HostedHttpRouteCollection специально ищет HttpWebRoute. См. Код ниже. Поскольку glimpse добавил прокси, перечислитель всегда возвращает 0 маршрутов !!

    public override IEnumerator GetEnumerator()
    {
         // Here we only care about Web API routes.
         return _routeCollection
             .OfType()
             .Select(httpWebRoute => httpWebRoute.HttpRoute)
             .GetEnumerator();
    }

Боюсь, что решения нет, вы можете выбрать то, что хотите использовать: Swashbuckle или Glimpse, но не оба вместе.

Конечно, вы можете попробовать использовать один из этих обходных путей, но есть риск неожиданного поведения и сложных ошибок.

person Marek Dorda    schedule 29.08.2017

У меня была такая же проблема, и ничего из этого мне не помогло.

После некоторого возни я понял, что маршруты, которые я пометил как [System.Web.Mvc.Route("visit")], не были обнаружены чванством.

    [HttpGet]
    // ROUTE ATTRIBUTE NOT FOUND BY SWAGGER
    [System.Web.Mvc.Route("visit")]
    public string Visit()
    {

но [System.Web.Http.Route("visit")]

    [HttpGet]
    // ROUTE ATTRIBUTE *IS* FOUND BY SWAGGER
    [System.Web.Http.Route("visit")]
    public string Visit()
    {

Я не уверен на 100%, но если это важно, я тоже перешел с

 public class MyAPIController : Controller

to:

 public class MyAPIController : System.Web.Http.ApiController

Точнее, я удалил оператор using для System.Web.Mvc, но код указан в иллюстративных целях.

Надеюсь, это поможет кому-то еще в будущем :) Удачи!

person Alex C    schedule 15.11.2017
comment
Я просто потратил час на отладку своих контроллеров, пытаясь заставить их появиться в Swagger. Оказывается, он извлекал маршрут из System.Web.Mvc вместо System.Web.Http. Как только я его переключил, все заработало как шарм. Спасибо! - person Rob W.; 03.05.2018

Swashbuckle находится поверх слоя метаданных WebApi ApiExplorer. Он берет описания операций из ApiExplorer и затем сопоставляет их с описаниями Swagger.

Поскольку ваш контроллер наследуется от BASECONTROLLER, а не от APICONTROLLER, он не будет работать.

Согласно комментарию Джима Уолли

 private IEnumerable<ApiDescription> GetApiDescriptionsFor(string apiVersion)
    {
        return (_options.VersionSupportResolver == null)
            ? _apiExplorer.ApiDescriptions
            : _apiExplorer.ApiDescriptions.Where(apiDesc => _options.VersionSupportResolver(apiDesc, apiVersion));
    }

это метод, с помощью которого Swashbuckle получает все вызовы API. Требуется IApiExplorer. Что, если он не был изменен для чего-то другого, потребуется предоставленный ApiExplorer по умолчанию. Который содержит информацию только о вещах, которые наследуются от ApiController.

Репозиторий Swashbuckle git. просто найдите GetApiDescriptionsFor, и вы сразу перейдете к методу

person gh9    schedule 05.08.2015
comment
Есть ли пакет документации API, который поддерживает этот сценарий? Кроме того, я создал фиктивный контроллер, который наследуется от ApiController, как обычный контроллер, и который также не отображается в пользовательском интерфейсе swagger. - person Bill Sambrone; 05.08.2015
comment
Я не знаю, есть ли пакет API, который делает это из коробки. Если вы могли бы опубликовать код для фиктивного контроллера или просто загрузить свой проект куда-нибудь, чтобы я мог посмотреть, мы могли бы решить эту проблему - person gh9; 05.08.2015
comment
добавлен фиктивный контроллер - person Bill Sambrone; 05.08.2015
comment
извините, я не знаю, почему не подходит фиктивный контроллер - person gh9; 05.08.2015
comment
Я не уверен, что эта оценка полностью верна. Я могу видеть контроллеры, которые напрямую не реализуют APIController при использовании Swashbuckle / swagger в локальном проекте webapi. Я также тестировал производный контроллер в отдельном классе, и он все еще был найден в образце проекта. Я вижу ту же проблему, что и OP, в моей реальной реализации. - person Jim Wooley; 06.08.2015
comment
@JimWooley достаточно честно, я обновил свой ответ, почему он должен работать только с вещами, унаследованными от ApiController. - person gh9; 06.08.2015

У меня было множество проблем с интеграцией Owin + Swashbuckle, и ни один из этих ответов не помог мне все исправить. Короче говоря, мне удалось все решить и создать репозиторий с открытым исходным кодом, который будет использоваться в качестве шаблона для всех, кому это нужно.

Проверьте: ASPSwaggerOwinTemplate

person Crimson7    schedule 25.04.2019
comment
После сравнения моих кодов с вашим Startup.cs я, наконец, не понял, что пошло не так, но это помогло моей проблеме, и она наконец решена - person Mahyar Mottaghi Zadeh; 16.07.2019

Я нашел эту ссылку очень полезной. Это конкретное решение относится к API Microsoft.Azure.Mobile.Server, но оно решило проблему для меня.

Сервер мобильных приложений Azure и Swagger

person Rod Hartzell    schedule 28.03.2017

У меня тоже была эта проблема с использованием OWIN. Проблема была решена путем установки только Swashbuckler Core, как предложено в здесь, и путем редактирования файла Startup.cs как показано ниже:

// Startup.cs
            // ...
            HttpConfiguration config = new HttpConfiguration();
            // ...
            config
                .EnableSwagger(c =>
                {
                    ////add if there's custom root path
                    //c.RootUrl(req =>
                    //    req.RequestUri.GetLeftPart(UriPartial.Authority) +
                    //    req.GetRequestContext().VirtualPathRoot.TrimEnd('/'));

                    c.SingleApiVersion("v1", "A title for your API");
                })
                .EnableSwaggerUi();
            // ...
            appBuilder.UseWebApi(config);
person Nae    schedule 03.04.2020

Я был знаком с версией Swashbuckle ядра .NET, которая автоматически расширяла контроллеры. Когда я работал над API фреймворка (неосновным), когда мне наконец удалось что-то показать, я был сбит с толку, потому что не знал, как нажать «Показать / скрыть», и все еще думал, что это не работает.

введите описание изображения здесь

Вы можете расширить его по умолчанию следующим образом:

.EnableSwaggerUi(c => {
    c.DocExpansion(DocExpansion.List);
});
person JohnOpincar    schedule 04.01.2021

В моем случае у меня была проблема, аналогичная Alex C. Мне пришлось сделать 2 вещи, чтобы исправить это:

Во-первых, у меня был оператор импорта об использовании MVC, примерно так:

using System.Web.Mvc;

Я удалил этот оператор импорта, и это решило половину проблемы. Еще я заметил, что в одном из контроллеров, которые отображались в Swashbucke, была аннотация, подобная этой

[RoutePrefix("v1/Awesome")]

Где Awesome - имя контроллера AwesomeController. Поэтому я поместил эту аннотацию префикса маршрута прямо перед объявлением моего класса, и теперь он отображается в интерфейсе Swagger.

[RoutePrefix("v1/Amazing")]
public class AmazingController : ApiController

Так что, если у кого-то еще есть эта проблема, вы можете проверить, нужно ли вам добавлять префикс маршрута, как это сделал я.

person SendETHToThisAddress    schedule 09.02.2021