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; } }
json). The Swagger UI can be found at http://localhost:<port>/swagger .
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 .
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With