Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swashbuckle 5 can't find my ApiControllers

I'm at a point where I really need API documentation for my WebAPI 2 project, and I used the Swashbuckle 5 NuGet package. Out of the box, I can hit {myrooturl}/swagger and a UI pops up, but there are no controllers, methods, or anything in there. Just my title: [ base url: /EM.Services , api version: v1 ]

I took a look at the Swashbuckle docs, and since I'm using OWIN which is hosted by IIS, I modified the SwaggerConfig with:

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

as per this doc: https://github.com/domaindrivendev/Swashbuckle/blob/1326e753ce9b3a823b3c156b0b601134692ffc58/README.md#transitioning-to-swashbuckle-50

I also setup the build of the project to generate the XML docs and pointed my SwaggerConfig to it with:

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

I'm not sure if the XML docs working/not-working has anything to do with it though, as I get absolutely no controllers on the swagger-ui page.

For what it's worth, all of my controller inherit from a BaseController, which in turn inherits from ApiController.

Is there something screwy with my 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"));     } 

My concrete controllers all look like this (I've tried subbing out BaseController for ApiController and there is no change):

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

and my Base controller doesn't do much (yet), just has an attribute:

[BuildClaims] public abstract class BaseController : ApiController 

The empty page persists across using IIS Express or full blown IIS.

Update: Example of a contrived controller I made that is really basic. It also does not show up, as I still have the boiler plate swagger ui with nothing in it.

/// <summary> /// I am a test /// </summary> [RoutePrefix("api/dummy")] public class DummyController : ApiController {     [HttpGet]     [Route("foo")]     public int Foo()     {         return 42;     } } 
like image 273
Bill Sambrone Avatar asked Aug 05 '15 18:08

Bill Sambrone


People also ask

Where is Swagger json located?

json). The Swagger UI can be found at http://localhost:<port>/swagger .

What is the default Swagger URL?

Add and configure Swagger middleware The generated document describing the endpoints appears as shown in OpenAPI specification (openapi. json). The Swagger UI can be found at https://localhost:<port>/swagger .

What is Swagger C#?

Swagger (OpenAPI) is a language-agnostic specification for describing REST APIs. It allows both computers and humans to understand the capabilities of a REST API without direct access to the source code. Its main goals are to: Minimize the amount of work needed to connect decoupled services.


2 Answers

I got stuck.. and these answers didn't help me fully... although they led me there. Just to save other people some time:

You have to pass the http config from OWIN and then register on that instead of using the GlobalConfiguration class like so:

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

and in the swagger config file, change the register method to:

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

Hope this helps.

like image 184
Sumit Maingi Avatar answered Oct 05 '22 23:10

Sumit Maingi


I found the problem. After creating an empty test project, I noticed that the WebApiConfiguration was being registered from the global.asax app start and not the OWIN startup class (like I did).

Since Swagger/Swashbuckle is hooking into the GlobalConfiguration and also given that OWIN startup and Global.asax live in different contexts (I think), the fix is to wire up your WebAPI stuff to register from Global.asax and to have OWIN's app object use WebAPI.

Relevant bits:

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

After rewiring as above, I can now see controllers & actions in swagger UI.

like image 25
Bill Sambrone Avatar answered Oct 05 '22 21:10

Bill Sambrone