← back to the blog


How To Use Swagger at ASP.NET MVC

Posted in Swagger, ASP.NET, ASP.NET MVC, WebAPI(Microsoft) by dake

What's Swagger?

Swagger could provide more rich document for your API. ASP.NET MVC also has Web API Helper page, but unlike Swagger, which is more powerful with client generation, discoverablity and more developer support. 

This blog will show how to use Swagger to ASP.NET MVC API project and provide list of how to.

With a Swagger-enabled API, you get interactive documentation, client SDK generation and discoverability.

Install-Package Swashbuckle

Following are few information relative with Swagger.

Use Azure API App template with Swagger

You can use Swagger with Visual Studio 2015, ASP.NET 4.5.2 Templates. Once you use Visual Studio and create web application by template Azure API App, at your solution you should see following Swagger at the package file.

You will find nuget library Swashbuckle, that .NET version of Swagger, if you want to use latest nuget version. You can use nuget to uninstall the package and install the latest nuget package again.

SwaggerConfig and EnableSwaggerUi and basic configuration

After install Swashbuckle, you will see a SwaggerConfig under your App_Start folder. This SwaggerConfig is the start point to enable Swagger. At the following, if you have already contains EnableSwaggerUI(x=>, then your setup is done. We should see the API document written by Swagger.

[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]

namespace WebApplication1
{
    public class SwaggerConfig
    {
        public static void Register()
        {
            var thisAssembly = typeof(SwaggerConfig).Assembly;

            GlobalConfiguration.Configuration 
                
                .EnableSwagger(c =>
                    // {...
                    // this will enable swagger UI
                .EnableSwaggerUi(c =>

Build solution and check the url {yoururl}/swagger or {yoururl/swagger/ui/index

Boom!!!, here you go, there's document. I have two Web API, TestController and ValuesController. As you can see it, it contains search feature and you can try it out!!?

However I also got following question when I first see these pages generate by Swagger.

  • Can I change this API document's UI, include logo, stylesheet?
  • Can I add javascript to this?
  • Can I change the URL instead of /swagger?
  • Can I add my own page to this auto generated page?
  • Can I make certain Web API not show?
  • Can I turn the swagger's API documents off at production, but only in development?

I might not cover all these question I have in my mind, but will give a try and list here.

Can I Use customized stylesheet for Swagger?

Let's assume i want to change following style, which change the header background color to #704C8F.

1. CSS file

.swagger-section #header {
    background-color: #704C8F;
    padding: 14px;
}

2. SwaggerConfig

.EnableSwaggerUi(c =>                   {
c.InjectStylesheet(Assembly.GetAssembly(typeof(WebApiApplication)), "WebApplication2.styles.swagger_test.css");

3. Global.ascx

How the WebApiApplication looks like

The SwaggerConfig's InjectStylesSheet's first parameter need to pass current application's assembly, second parameter is little tricky. The file name WebApplication2.styles.swagger_test.cssis Project Folder name.{folder name} and the file name.

namespace WebApplication2
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

4. styles file location

Also, this is very important, you have make the file BuildAction as Embedded Resource.

4. After 1 - 4 steps, how page looks like

 

Can I add my own Javascript file to Swagger API documents?

You are able to do it as following, assume you have a javascript file like this.

1. Javascript

(function () {
    function init() {

        console.info("init for my swagger function");

        $("#explore").click(function () {
            alert("you clicked explore");
        });
    }

    init();
})();

2. Javascript file location and Build Action Property


3. SwaggerConfig class

set the javascript path as string type like following.

   var myAssembly = Assembly.GetAssembly(typeof(WebApiApplication));
   c.InjectJavaScript(myAssembly, "WebApplication2.js.swagger_test.js");

4. Done, check the page

When the page load, you can see the javascript console message, now you can add javascript to the page, my next question is can I change the default Html?

Now, we know we can change javascript, css, can we change the entire HTML?

Yes, and the main feature will still work if you use the swagger's existing javascript. Following are how we can do it.

1. Html Files

This time I want to add two html, after create these html you also have to change Build Action as Embedded Resource again.

swagger_test.html

<h3>Bomm!!!!</h3>

OtherVersion.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Swagger UI My Own Version</title>
    <link rel="icon" type="image/png" href="images/favicon-32x32-png" sizes="32x32" />
    <link rel="icon" type="image/png" href="images/favicon-16x16-png" sizes="16x16" />
    <link href='css/typography-css' media='screen' rel='stylesheet' type='text/css' />
    <link href='css/reset-css&#
39; media='screen' rel='stylesheet' type='text/css' />
    <link href='css/screen-css' media='screen' rel='stylesheet' type='text/css' />
    <link href='css/reset-css' media='print' rel='stylesheet' type='text/css' />
    <link href='css/print-css' media='print' rel='stylesheet' type='text/css' />
    <link href='ext/WebApplication2-styles-swagger_test-css' media='screen' rel='stylesheet' type='text/css' />

    <script src='lib/jquery-1-8-0-min-js' type='text/javascript'></script>
    <script src='lib/jquery-slideto-min-js' type='text/javascript'></script>
    <script src='lib/jquery-wiggle-min-js' type='text/javascript'></script>
    <script src='lib/jquery-ba-bbq-min-js' type='text/javascript'></script>
    <script src='lib/handlebars-2-0-0-js' type='text/javascript'></script>
    <script src='lib/underscore-min-js' type='text/javascript'></script>
    <script src='lib/backbone-min-js' type='text/javascript'></script>
    <script src='swagger-ui-min-js' type='text/javascript'></script>
    <script src='lib/highlight-7-3-pack-js' type='text/javascript'></script>
    <script src='lib/jsoneditor-min-js' type='text/javascript'></script>
    <script src='lib/marked-js' type='text/javascript'></script>
    <script src='lib/swagger-oauth-js' type='text/javascript'></script>

    <!-- Some basic translations -->
    <!-- <script src='lang/translator.js' type='text/javascript'></script> -->
    <!-- <script src='lang/ru.js' type='text/javascript'></script> -->
    <!-- <script src='lang/en.js' type='text/javascript'></script> -->

    <script type="text/javascript">
    $(function () {
      var url = window.location.search.match(/url=([^&]+)/);
      if (url && url.length > 1) {
        url = decodeURIComponent(url[1]);
      } else {
        url = "http://petstore.swagger.io/v2/swagger.json";
      }

      // Get Swashbuckle config into JavaScript
      function arrayFrom(configString) {
        return (configString !== "") ? configString.split('|') : [];
      }

      function stringOrNullFrom(configString) {
        return (configString !== "null") ? configString : null;
      }

      window.swashbuckleConfig = {
        rootUrl: 'http://localhost:65343',
        discoveryPaths: arrayFrom('swagger/docs/v1'),
        booleanValues: arrayFrom('true|false'),
        validatorUrl: stringOrNullFrom('http://localhost:65343/validator'),
        customScripts: arrayFrom('ext/WebApplication2-js-swagger_test-js'),
        docExpansion: 'none',
        oAuth2Enabled: ('false' == 'true'),
        oAuth2ClientId: '',
        oAuth2ClientSecret: '',
        oAuth2Realm: '',
        oAuth2AppName: '',
        oAuth2ScopeSeperator: ' ',
        oAuth2AdditionalQueryStringParams: JSON.parse('{}')
      };

      // Pre load translate...
      if(window.SwaggerTranslator) {
        window.SwaggerTranslator.translate();
      }
      window.swaggerUi = new SwaggerUi({
        url: swashbuckleConfig.rootUrl + "/" + swashbuckleConfig.discoveryPaths[0],
        dom_id: "swagger-ui-container",
        booleanValues: swashbuckleConfig.booleanValues,
        onComplete: function(swaggerApi, swaggerUi){
          if (typeof initOAuth == "function" && swashbuckleConfig.oAuth2Enabled) {
            initOAuth({
              clientId: swashbuckleConfig.oAuth2ClientId,
              clientSecret: swashbuckleConfig.oAuth2ClientSecret,
              realm: swashbuckleConfig.oAuth2Realm,
              appName: swashbuckleConfig.oAuth2AppName,
              scopeSeparator: swashbuckleConfig.oAuth2ScopeSeperator,
              additionalQueryStringParams: swashbuckleConfig.oAuth2AdditionalQueryStringParams
            });
          }

          if(window.SwaggerTranslator) {
            window.SwaggerTranslator.translate();
          }

          $('pre code').each(function(i, e) {
            hljs.highlightBlock(e)
          });

          addApiKeyAuthorization();

          window.swaggerApi = swaggerApi;
          _.each(swashbuckleConfig.customScripts, function (script) {
            $.getScript(script);
          });
        },
        onFailure: function(data) {
          log("Unable to Load SwaggerUI");
        },
        docExpansion: swashbuckleConfig.docExpansion,
        jsonEditor: false,
        apisSorter: null, // default to server
        defaultModelRendering: 'schema',
        showRequestHeaders: false
      });

      if (window.swashbuckleConfig.validatorUrl !== '')
        window.swaggerUi.options.validatorUrl = window.swashbuckleConfig.validatorUrl;

      function addApiKeyAuthorization(){
        var key = encodeURIComponent($('#input_apiKey')[0].value);
        if (key && key.trim() != "") {
          var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("api_key", key, "query");
            window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
            log("added key " + key);
        }
      }

      $('#input_apiKey').change(addApiKeyAuthorization);

      // if you have an apiKey you would like to pre-populate on the page for demonstration purposes...
      /*
        var apiKey = "myApiKeyXXXX123456789";
        $('#input_apiKey').val(apiKey);
      */

      window.swaggerUi.load();

      function log() {
        if ('console' in window) {
          console.log.apply(console, arguments);
        }
      }
  });
    </script>
</head>

<body class="swagger-section">
    <h1>Damn, I love this! Swagger!</h1>

    <div id="message-bar" class="swagger-ui-wrap" data-sw-translate>&nbsp;</div>
    <div id="swagger-ui-container" class="swagger-ui-wrap"></div>
</body>
</html>

2. SwaggerConfig for Html

      c.CustomAsset("swagger_test", myAssembly, "WebApplication2.html.swagger_test.html");
                        c.CustomAsset("OtherVersion", myAssembly, "WebApplication2.html.OtherVersion.html");

3. That's it, let's check the browser.

Now, you're going to ask question, what's the URL. I didn't figure out at the first, but look like Swagger is using the file name as the url. Since their default page is /swagger/ui/index, so my new files' url will be /swagger/ui/OtherVersion and /swagger/ui/swagger_test

Following is one of the my new page, OtherVersion. Isn't this so sweet? As a developer when you use other UI Framework, if you can replace CSS, Javascript and HTML but keep their original logic. That's just fantastic.

Add .NET XML comment for swagger's API description

ASP.NET WebAPI's default api helper document also looks for dll's xml comment for description. We can do that in swagger too.

1. Project property

First thing you need to do is go to the project contains the API controller to check the XML documentation file, so when build the solution visual studio will update the xml with comment you add to the class. Also, swagger later will read the xml's comment as description of the API too.

2. SwaggerConfig setting

The next important thing is, swagger has not register the API xml, you can add as following.

 c.IncludeXmlComments(string.Format(@"{0}\bin\APIDemo.XML", System.AppDomain.CurrentDomain.BaseDirectory));

Following are example of the WebAPI controller and the API Model class' xml document.

/// <summary>
    /// my product
    /// </summary>
    public class Product
    {
        /// <summary>
        /// product id
        /// </summary>
        public Guid GuidId { get; set; }
        /// <summary>
        /// product Id
        /// </summary>
        public int ProductId { get; set; }
        /// <summary>
        /// product name
        /// </summary>
        public string ProductName { get; set; }
        /// <summary>
        /// product price
        /// </summary>
        public decimal Price { get; set; }
        /// <summary>
        /// product unit
        /// </summary>
        public int Unit { get; set; }
/// <summary>
    /// ProductController API
    /// </summary>
    public class ProductController : ApiController
    {
        /// <summary>
        /// products data
        /// </summary>
        public static List<Product> Products
        {
            get
            {
                return new List<Product>
                {
                    new Product(Guid.NewGuid(), 122, "Product A", 300, 1),
                    new Product(Guid.NewGuid(), 333, "Product B", 400, 10),
                    new Product(Guid.NewGuid(), 444, "Product C", 500, 20),
                    new Product(Guid.NewGuid(), 555, "Product D", 600, 15),
                    new Product(Guid.NewGuid(), 777, "Product E", 700, 5)
                };
            }
        }

        /// <summary>
        ///  get values for products
        /// </summary>
        /// <returns></returns>
        public IEnumerable<Product> Get()
        {
            return Products;
        }

3. Done! Let's browser the API Document

Now, we're done, after build the solution, you should see your xml comment add to the Csharp class at the Swagger API document page.

Conclusion

I think swagger with ASP.NET MVC will provide very powerful API documentation and it is very flexible.

Download Code