Skip to content

5 Troubleshooting and FAQ's

Helder Sepulveda edited this page Jun 2, 2017 · 2 revisions
  1. Swagger-ui showing "Can't read swagger JSON from ..."
  2. Page not found when accessing the UI
  3. Swagger-ui broken by Visual Studio 2013
  4. OWIN Hosted in IIS - Incorrect VirtualPathRoot Handling
  5. How to add vendor extensions
  6. FromUri Query string DataMember names are incorrect
  7. Remove Duplicate Path Parameters
  8. Deploying behind Load Balancer / Reverse Proxies
  9. 500 : {"Message":"An error has occurred."}

Swagger-ui showing "Can't read swagger JSON from"

If you see this message, it means the swagger-ui received an unexpected response when requesting the Swagger document. You can troubleshoot further by navigating directly to the discovery URL included in the error message. This should provide more details.

If the discovery URL returns a 404 Not Found response, it may be due to a full-stop in the version name (e.g. "1.0"). This will cause IIS to treat it as a static file (i.e. with an extension) and bypass the URL Routing Module and therefore, Web API.

To workaround, you can update the version name specified in SwaggerConfig.cs. For example, to "v1", "1-0" etc. Alternatively, you can change the route template being used for the swagger docs (as shown here) so that the version parameter is not at the end of the route.

Page not found when accessing the UI

Swashbuckle serves an embedded version of the swagger-ui through the Web API pipeline. But, most of the URLs contain extensions (.html, .js, .css) and many IIS environments are configured to bypass the managed pipeline for paths containing extensions.

In previous versions of Swashbuckle, this was resolved by adding the following setting to your Web.config:

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

This is no longer neccessary in Swashbuckle 5.0 because it serves the swagger-ui through extensionless URL's.

However, if you're using the SingleApiVersion, MultipleApiVersions or CustomAsset configuration settings you could still get this error. Check to ensure you're not specifying a value that causes a URL with an extension to be referenced in the UI. For example a full-stop in a version number ...

httpConfiguration
    .EnableSwagger(c => c.SingleApiVersion("1.0", "A title for your API"))
    .EnableSwaggerUi();

will result in a discovery URL like this "/swagger/docs/1.0" where the full-stop is treated as a file extension.

Swagger-ui broken by Visual Studio 2013

VS 2013 ships with a new feature - Browser Link - that improves the web development workflow by setting up a channel between the IDE and pages being previewed in a local browser. It does this by dynamically injecting JavaScript into your files.

Although this JavaScript SHOULD have no affect on your production code, it appears to be breaking the swagger-ui.

I hope to find a permanent fix, but in the meantime, you'll need to workaround this issue by disabling the feature in your web.config:

<appSettings>
    <add key="vs:EnableBrowserLink" value="false"/>
</appSettings>

OWIN Hosted in IIS - Incorrect VirtualPathRoot Handling

When you host Web API 2 on top of OWIN/SystemWeb, Swashbuckle cannot correctly resolve VirtualPathRoot by default.

You must either explicitly set VirtualPathRoot in your HttpConfiguration at startup, or perform customization like this to fix automatic discovery:

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

How to add vendor extensions

Swagger 2.0 allows additional meta-data (aka vendor extensions) to be added at various points in the Swagger document. Swashbuckle supports this by including a "vendorExtensions" dictionary with each of the extensible Swagger types. Meta-data can be added to these dictionaries from custom Schema, Operation or Document filters. For example:

public class ApplySchemaVendorExtensions : ISchemaFilter
{
    public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
    {
        schema.vendorExtensions.Add("x-foo", "bar");
    }
}

As per the specification, all extension properties should be prefixed by "x-"

FromUri Query string DataMember names are incorrect

When using FromUri Model Binding, it is possible to override the querystring parameter name's using DataMembers. In this case you can add a custom operation filter to override the name. For example:

public class ComplexTypeOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        if (operation.parameters == null)
            return;

        var parameters = apiDescription.ActionDescriptor.GetParameters();
        foreach (var parameter in parameters)
        {
            foreach (var property in parameter.ParameterType.GetProperties())
            {
                var param = operation.parameters.FirstOrDefault(o => o.name.ToLowerInvariant().Contains(property.Name.ToLowerInvariant()));

                if (param == null) continue;

                var name = GetNameFromAttribute(property);

                if (string.IsNullOrEmpty(name))
                {
                    operation.parameters.Remove(param);
                }
                param.name = GetNameFromAttribute(property);
            }
        }
    }
    
    private static string GetNameFromAttribute(PropertyInfo property)
    {
        var customAttributes = property.GetCustomAttributes(typeof(DataMemberAttribute), true);
        if (customAttributes.Length > 0)
        {
            var attribute = customAttributes[0] as DataMemberAttribute;
            if (attribute != null) return attribute.Name;
        }
        return string.Empty;
    }
}

Remove Duplicate Path Parameters

When using FromUri Model Binding, duplicate items can appear as items can be passed as URI parameters, or querystrings. In this case you can add a custom operation filter to remove the duplicates. For example:

public class ComplexTypeOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
       if (operation.parameters == null)
           return;
       var complexParameters = operation.parameters.Where(x => x.@in == "query" && !string.IsNullOrWhiteSpace(x.name)).ToArray();

       foreach (var parameter in complexParameters)
       {
           if (!parameter.name.Contains('.')) continue;
           var name = parameter.name.Split('.')[1];

           var opParams = operation.parameters.Where(x => x.name == name);
           var parameters = opParams as Parameter[] ?? opParams.ToArray();

           if (parameters.Length > 0)
           {
               operation.parameters.Remove(parameter);
           }
       }
    }
}

Deploying behind Load Balancer / Reverse Proxies

Swashbuckle attempts to populate the Swagger "host" property from HTTP headers that are sent with the request for Swagger JSON. This may cause issues in load balancer / reverse proxy environments, particularly if non-standard headers are used to pass on the outer most host name. You can workaround this by providing your own function for determining your API's root URL based on vendor-specific headers. Checkout issue 705 for some potential implementations.

500 : {"Message":"An error has occurred."}

If, on loading the Swagger UI page, you get an error: 500 : {"Message":"An error has occurred."} http://<url>/swagger/docs/v1 ensure that the XML documentation output settings have been set in the project file in the solution, for both Debug and Release configurations.