SharpCoder
SharpCoder

Reputation: 19183

ASP.NET Web API - Swagger , create multiple views

I am using Swagger with ASP.NET Web API application. If I visit URL http://localhost:5000/swagger

Swagger list all the controllers and actions defined in these controllers. Lets say I have five controllers and each controller has one action. I want to create multiple views such that when

user says http://localhost:5000/swagger/v1 he gets to see all controllers when user says http://localhost:5000/swagger/v2 he gets to see only one controller when user says http://localhost:5000/swagger/v3 he gets to see only two controller

Basically I am trying to restrict access to controller via swagger. Based on user requirement, I will share specific URL with them.

Is it possible to achieve this with Swagger?

Upvotes: 1

Views: 394

Answers (1)

G.Dimov
G.Dimov

Reputation: 2393

Yes, you can do exactly what you want.

You should do the following steps:

  1. Create a class that inherits from IDocumentFilter and register it in SwaggerConfig.cs as follows c.DocumentFilter<HideSwaggerEndpointsDocumentFilter>();

Example:

public class HideSwaggerEndpointsDocumentFilter : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
    //enter code here
    }
}

This filter is loaded once you load the swagger page. Inside it, you have control over each and every controller action. You can delete some actions based on any criteria decided by you.

  1. Deleting them is a bit tricky, I do it as follows:
foreach (var apiDescription in apiExplorer.ApiDescriptions)
{
    var route = "/" + apiDescription.RelativePath.Substring(0, (apiDescription.RelativePath.IndexOf('?') != -1) ? apiDescription.RelativePath.IndexOf('?') : apiDescription.RelativePath.Length).TrimEnd('/');
    var path = swaggerDoc.paths[route];

    switch (apiDescription.HttpMethod.Method)
    {
        case "DELETE": path.delete = null; break;
        case "GET": path.get = null; break;
        case "HEAD": path.head = null; break;
        case "OPTIONS": path.options = null; break;
        case "PATCH": path.patch = null; break;
        case "POST": path.post = null; break;
        case "PUT": path.put = null; break;
        default: throw new ArgumentOutOfRangeException("Method name not mapped to operation");
    }

    if (path.delete == null && path.get == null &&
        path.head == null && path.options == null &&
        path.patch == null && path.post == null && path.put == null)
    {
        swaggerDoc.paths.Remove(route);
    }
}

Disclaimer:
If you put the above code in your DocumentFilter class it will delete all actions regardless of the given URL.

  1. So we are in the final step, where you basically do your desired logic.

Inside the (foreach (var apiDescription in apiExplorer.ApiDescriptions)) you can play and do your custom logic. You have access to HttpContext.Current, so you can get the current URL.

If you don't want to delete the current action have something like this, before the swaggerDoc.paths.Remove(route);.

bool forDelete = false; // your custom logic when it should be deleted
if (!forDelete)
{
    return;
}

Hope this helps you.

Upvotes: 3

Related Questions