Swashbuckle 5 找不到我的 ApiControllers

Swashbuckle 5 can't find my ApiControllers

我确实需要 API WebAPI 2 项目的文档,并且我使用了 Swashbuckle 5 NuGet 包。开箱即用,我可以点击 {myrooturl}/swagger 并弹出 UI,但其中没有控制器、方法或任何东西。只是我的标题:[ base url: /EM.Services , api version: v1 ]

我查看了 Swashbuckle 文档,由于我使用的是 IIS 托管的 OWIN,因此我修改了 SwaggerConfig:

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

根据此文档:https://github.com/domaindrivendev/Swashbuckle/blob/1326e753ce9b3a823b3c156b0b601134692ffc58/README.md#transitioning-to-swashbuckle-50

我还设置了项目的 build 以生成 XML 文档并将我的 SwaggerConfig 指向它:

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

我不确定 XML 文档 working/not-working 是否与它有任何关系,因为我在 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

我的 Base 控制器(目前)还没有做太多事情,只有一个属性:

[BuildClaims]
public abstract class BaseController : ApiController

使用 IIS Express 或完整的 IIS 时,空白页面仍然存在。

更新: 我制作的一个非常基本的人为控制器示例。它也没有出现,因为我仍然有样板招摇 ui,里面什么也没有。

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

Swashbuckle 位于 WebApi 的元数据层之上 ApiExplorer。它从 ApiExplorer 获取操作描述,然后将它们映射到 Swagger 描述。

由于您的控制器继承自 BASECONTROLLER 而不是 APICONTROLLER,因此它将无法工作

根据 JimWolley 的评论

 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 repo. just search for GetApiDescriptionsFor and it will take you straight to the method

我发现了问题。创建一个空的测试项目后,我注意到 WebApiConfiguration 是从 global.asax 应用程序启动而不是 OWIN 启动 class(就像我所做的那样)注册的。

由于 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 中的控制器和动作 UI。

我卡住了……这些答案并没有完全帮助我……尽管他们把我带到了那里。只是为了节省其他人一些时间:

您必须从 OWIN 传递 http 配置,然后在上面注册,而不是像这样使用 GlobalConfiguration class:

//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 =>
                {...

希望对您有所帮助。

我发现这个 link 非常有帮助。这个特定的解决方案特定于 Microsoft.Azure.Mobile.Server API 但它解决了我的问题。

Azure Mobile Apps Server and Swagger

我发现我遇到了同样的问题。我创建了一个扩展方法来帮助

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);
    }
}

所有这些解决方案都适用于我,但它们都只是针对我的问题的讨厌的黑客攻击。经过几个小时的调查,我发现问题是我还使用了 Glimpse(或其他更改路由 table 的包)。

这里有一个很好的总结:https://github.com/domaindrivendev/Swashbuckle/issues/468#issuecomment-139246748

  1. Glimpse adds castle proxies on top of HttpWebRoute. So HostedHttpRouteCollection is collection of RouteProxy and not HttpWebRoute.
  2. APIExplorer class has FlattenRoutes method which does a foreach loop over HostedHttpRouteCollection.
  3. GetEnumerator implementation of HostedHttpRouteCollection specifically look for HttpWebRoute. See the code below. Since glimpse has added proxies, enumerator always returns 0 routes!!

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

恐怕没有解决办法,你可以选择你想用的:SwashbuckleGlimpse,但是不是两个都在一起

当然,您可以尝试 运行 这些解决方法之一,但存在意外行为和棘手错误的风险。

我自己也遇到了同样的问题,none 帮助了我。

经过一番摸索后,我发现我标记为 [System.Web.Mvc.Route("visit")] 的路线并没有被 swagger 发现。

    [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

至:

 public class MyAPIController : System.Web.Http.ApiController

更准确地说,我删除了 System.Web.Mvc 的 "using" 语句,但列出代码是为了说明目的。

希望这对以后的其他人有帮助 :) 祝你好运!

我在 Owin + Swashbuckle 集成方面遇到了很多问题,none 这些答案为我解决了所有问题。长话短说,我设法解决了所有问题并创建了一个开源存储库,用作任何需要它的人的模板。

请检查:ASPSwaggerOwinTemplate

我在使用 OWIN 时也遇到了这个问题。通过按照 here 中的建议仅安装 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);

我熟悉 Swashbuckle 的 .NET 核心版本,它可以自动扩展控制器。当我在做一个框架(非核心)时API,当我终于设法展示一些东西时,我很困惑,因为我不知道点击show/hide并且仍然认为它不是正在工作。

您可以使用以下内容默认展开它:

.EnableSwaggerUi(c => {
    c.DocExpansion(DocExpansion.List);
});

就我而言,我遇到了与 Alex C 类似的问题。我必须做两件事来解决它:

第一件事是我有一个关于使用 MVC 的导入声明,像这样:

using System.Web.Mvc;

我删除了那个 import 语句,这解决了一半的问题。我注意到的另一件事是,在 Swashbucke 中出现的 的控制器之一有这样的注释

[RoutePrefix("v1/Awesome")]

其中Awesome是控制器AwesomeController的名字。所以我把那个路由前缀注释放在我的 class 声明之前,现在它出现在 Swagger 界面中

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

因此,如果其他人遇到此问题,您可以检查是否需要像我一样添加路由前缀。