Customizing Swagger UI in ASP.NET Core

If you're not already using Swagger with your ASP.NET Core API, you should start. You get a completely out-of-the-box set of API docs and a ready-made testing platform, all with just a few lines of code. The one minor issue is that the Swagger UI comes branded with Swagger logos and such, and it's not easy or intuitive to make changes to that. Additionally, the ability to customize portions of the Swagger UI interface in ASP.NET Core has largely been a moving target, even to this day, so what help you can find online in this regard is either incomplete or outdated.

Here, I present the easiest path I found to customize portions of the UI while still retaining as much of the out-of-the-box goodness as possible.

Changing the route

By default, your Swagger UI loads up under /swagger/. If you want to change this, it's thankfully very straight-forward. Simply set the RoutePrefix option in your call to app.UseSwaggerUI in StartUp.cs:

public void Configure(...)  
{
    ...

    app.UseSwaggerUI(o =>
    {
        o.RoutePrefix = "docs";
    });
}

Now, it will load at /docs/. You can obviously change this to whatever you like. We're not quite done yet, though. SwaggerGen produces JSON schema documents that power Swagger UI. By default, these are served up under /swagger/{documentName}/swagger.json, where {documentName} is usually the API version. You don't have to change this, as it's more of an implementation detail, but if you want to mirror your Swagger UI route prefix, you'll need to make two changes. First, specify the RouteTemplate option in app.UseSwagger:

public void Configure(...)  
{
    ...

    app.UseSwagger(o =>
    {
        o.RouteTemplate = "docs/{documentName}/docs.json";
    });
}

Then, you'll need to change the Swagger Endpoint in app.UseSwaggerUI:

o.SwaggerEndpoint("/docs/v1/docs.json");  

Adding some style

The default color scheme Swagger UI employs for the header is a pretty abhorrent neon puke green. Thankfully, there is a hook to add in your own custom CSS. In your call to app.UseSwaggerUI, add the following line:

o.InjectStylesheet("/swagger-ui/custom.css");  

Then, under wwwroot in your project, add a new folder named swagger-ui. Inside that, add a new CSS file named custom.css. Finally, add whatever styles you'd like to override inside. However, note that the CSS specificity in Swagger UI's template is garbage. I think it adds style via JavaScript; though, I haven't looked at the code deeply enough to confirm. Regardless, I found I pretty much needed to add !important to just about everything to make it actually have any effect. Anyways, here's a few things I changed in mine:

#header {
    background: #222!important;
}
#select_document {
    background: #666!important;
}
input[name=baseUrl] {  
    display: none!important;
}
.logo__title {
    display: none!important;
}
#api_info a {
    color: #007bff!important;
    text-decoration: none!important;
}
#api_info a:hover,
#api_info a:focus,
#api_info a:active {
    color: #0056b3!important;
    text-decoration: underline!important;
}

Firstly, I changed the background color of the header and the document selector field. Next, I've turned off the display of the baseUrl field. This value is never going to change, so there's no point in showing it. The .logo__title bit is to remove the "swagger" name in the header. I just went with a logo image alone. Finally, I've changed the link styling of the API information area, which was also an abhorrent not-neon but-still-puke-colored green. Obviously, you can take this as far as you want. Simply pull up your browser's developer tools, inspect the thing you'd like to change, and then add some CSS to target that. Again, you'll likely need to make use of !important to have it actually apply.

Going further with JavaScript

Unfortunately, CSS can only get you so far. While you could use image replacement techniques to switch out the logo via a background image, I found it easier and more straight-forward to just use JavaScript to change the image source and such. Besides, once you've added some custom JavaScript, you can pretty much modify to your heart's content. The procedure here is pretty much the same as with adding custom CSS above. Add a custom.js file to the swagger-ui folder you created previously. Then, in add.UseSwaggerUI, add the following line:

o.InjectOnCompleteJavaScript("/swagger-ui/custom.js");  

My custom JavaScript is pretty basic: it just replaces some values on the img element and the a element that wraps it.

(function () {
    var logo = document.getElementById('logo');
    logo.href = "https://www.foo.com";

    var logoImg = document.getElementsByClassName('logo__img')[0];
    logoImg.alt = "Foo, Inc.";
    logoImg.src = "/swagger-ui/logo.svg";
    logoImg.width = 496;
})();

Changing the favicon

The last remaining vestige of the Swagger UI branding is the favicon. This one is a little tougher to fix as it's hard-coded to a path relative to the index.html page driving Swagger UI. Thankfully, however, it is possible to override with your own images, as long as you mirror the directory structure exactly, i.e. {prefix}/images. Since I used "docs" as my route prefix above, that would be docs/images. In other words, in wwwroot, create a folder named docs, and inside that create another folder named images. There, you'll need to add three files: favicon.ico, favicon-16x16.png, and favicon-32x32.png. With that in place, the favicon displayed in the browser should update to your favicon. If it doesn't, the old version may have already been cached. To fix this, simply load the image files directly in the browser and do a hard-refresh on each (CTRL+F5).

While you're at it, you might as well add these files to your document root, as well (i.e. directly under wwwroot). That way, your API itself will have a favicon displayed if you hit an endpoint via the browser. If you need help getting these favicon image files, I'd recommend using this Favicon Generator for ASP.NET Core. It's easy to use and covers just about every device configuration out there.

WTF? It's not working...

Just in case anyone else has moments of stupidity like I do, I should mention that all of this requires the ASP.NET Core StaticFiles middleware. That's technically a requirement for Swagger UI, itself, which is why I neglected to mention it at first. However, as I was applying these steps to another API, I was instantly confused by the fact that none of my changes were applying, at all. After a longer time than I'd care to admit, I finally realized that app.UseStaticFiles() was missing from my Configure method in Startup.cs. Apparently, even though Swagger UI has a dependency on it, it still works without it. The steps employed here, however, most assuredly do not.

Wrapping up

There's nothing really ground-shattering here, but if you've never customized things in Swagger UI before, the information is disparate and hard to find. Hopefully, this will serve to make things a little easier for those desperately searching the interwebs.

comments powered by Disqus