【问题标题】:Swashbuckle 5 can't find my ApiControllersSwashbuckle 5 找不到我的 ApiControllers
【发布时间】:2015-10-28 16:20:49
【问题描述】:

我确实需要为我的 WebAPI 2 项目提供 API 文档,并且我使用了 Swashbuckle 5 NuGet 包。开箱即用,我可以点击 {myrooturl}/swagger 并弹出一个 UI,但其中没有控制器、方法或任何东西。只是我的标题:[基本网址:/EM.Services,api版本: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

我还设置了项目的构建以生成 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,而 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;
    }
}

【问题讨论】:

    标签: c# iis asp.net-web-api swashbuckle


    【解决方案1】:

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

    您必须从 OWIN 传递 http 配置,然后在其上注册,而不是像这样使用 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 =>
                    {...
    

    希望这会有所帮助。

    【讨论】:

    • 谢谢!这对我有用,但此外我还必须删除 SwaggerConfig.cs 文件最顶部的行([assembly: PreApplicationStartMethod...)。在我删除它之前,我收到了“参数计数不匹配”错误
    • @HitLikeAHammer 删除上述行后,我得到 404。
    • 谢谢!我还必须删除 PreApplicationStartMethod 属性。
    【解决方案2】:

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

    由于 Swagger/Swashbuckle 与 GlobalConfiguration 挂钩,并且考虑到 OWIN 启动和 Global.asax 存在于不同的上下文中(我认为),解决方法是将 WebAPI 内容连接到从 Global.asax 注册并拥有 OWIN app 对象使用 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 中看到控制器和操作。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 是的,它对我有用,现在 swagger 能够发现我的 web api 的控制器
      【解决方案4】:

      我自己也遇到了同样的问题,但这些都没有帮助我。

      经过一番折腾,我发现我标记为 [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 的“使用”语句,但列出的代码是为了说明目的。

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

      【讨论】:

      • 我刚刚花了一个小时调试我的控制器,试图让它们出现在 Swagger 中。事实证明,它是从 System.Web.Mvc 而不是 System.Web.Http 拉路线。我一切换它,它就像一个魅力。谢谢!
      【解决方案5】:

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

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

      1. Glimpse 在 HttpWebRoute 之上添加了城堡代理。所以 HostedHttpRouteCollection 是 RouteProxy 的集合,而不是 HttpWebRoute
      2. APIExplorer 类具有 FlattenRoutes 方法,该方法在 HostedHttpRouteCollection 上执行 foreach 循环。
      3. GetEnumerator 实现 HostedHttpRouteCollection 专门寻找 HttpWebRoute。请参阅下面的代码。自从瞥见 已添加代理,枚举器总是返回 0 条路由!!

        公共覆盖 IEnumerator GetEnumerator()
        {
             // 这里我们只关心 Web API 路由。
             返回 _routeCollection
                 .OfType()
                 .Select(httpWebRoute => httpWebRoute.HttpRoute)
                 .GetEnumerator();
        }

      恐怕没有解决方案,您可以选择要使用的:SwashbuckleGlimpse,但不能同时使用

      当然,您可以尝试使用其中一种解决方法,但存在意外行为和棘手错误的风险。

      【讨论】:

        【解决方案6】:

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

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

        根据 JimWolleys 的评论

         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

        【讨论】:

        • 是否有支持此方案的 API 文档包?另外,我创建了一个虚拟控制器,它像普通控制器一样从 ApiController 继承,并且也不会出现在 swagger ui 中。
        • 我不知道是否有开箱即用的 API 包。如果您可以发布虚拟控制器的代码或者只是将您的项目上传到我可以查看的地方,我们可以得到这个已解决
        • 添加了虚拟控制器
        • 对不起,我不知道为什么虚拟控制器没有出现
        • 我不确定这个评估是否完全正确。在本地 webapi 项目上使用 Swashbuckle/swagger 时,我能够看到不直接实现 APIController 的控制器。我还在一个单独的类中使用派生控制器进行了测试,它仍然可以在示例项目中找到。我在实际实施中看到了与 OP 相同的问题。
        【解决方案7】:

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

        请查看:ASPSwaggerOwinTemplate

        【讨论】:

        • 在将我的代码与您的 Startup.cs 进行比较后,我终于没有发现问题所在,但它对我的问题有所帮助并最终解决了
        【解决方案8】:

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

        Azure Mobile Apps Server and Swagger

        【讨论】:

          【解决方案9】:

          我在使用 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);
          

          【讨论】:

            【解决方案10】:

            我熟悉自动扩展控制器的 .NET 核心版本的 Swashbuckle。当我在开发一个框架(非核心)API 时,当我终于设法让一些东西显示出来时,我感到很困惑,因为我不知道点击显示/隐藏并且仍然认为它不起作用。

            您可以使用以下默认扩展它:

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

            【讨论】:

              【解决方案11】:

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

              第一件事是我有一个关于使用 MVC 的导入声明,如下所示:

              using System.Web.Mvc;
              

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

              [RoutePrefix("v1/Awesome")]
              

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

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

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-01-11
                • 2013-07-01
                • 1970-01-01
                相关资源
                最近更新 更多