Swashbuckle 5 can't find my ApiControllers

Bill Sambrone picture Bill Sambrone · Aug 5, 2015 · Viewed 27.3k times · Source

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

Answer

Sumit Maingi picture Sumit Maingi · Sep 8, 2016

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.