When moving more and more towards JavaScript driven applications there is also a higher need for api´s. These api´s needs to be documented so that everyone in the team is able to consume them. A very good way to document api´s is to use Swagger which is an free available nuget package.
The only thing that could hold this back is that swagger by default is open for everyone but can off course be locked down in different ways. It could also be a case that you want to set roles on which api´s users can see documentation for.
To solve this I have created a custom attribute where you can set which role that is required to reach the documentation for each api.
To use this custom attribute, add following classes your project:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class ShowInSwaggerRoleAttribute : Attribute
{
private string role;
public ShowInSwaggerRoleAttribute(string role = null)
{
this.role = role;
}
public virtual string Role
{
get { return role; }
}
}
public class ShowInSwaggerFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
var filteredApisWithRole = apiExplorer.ApiDescriptions.Where(a => a.GetControllerAndActionAttributes<ShowInSwaggerRoleAttribute>().Any());
var paths = new Dictionary<string, PathItem>(swaggerDoc.paths);
swaggerDoc.paths.Clear();
foreach (var apiDescription in filteredApisWithRole)
{
var swaggerRole = apiDescription.GetControllerAndActionAttributes<ShowInSwaggerRoleAttribute>().FirstOrDefault();
if (swaggerRole != null)
{
if (swaggerRole.Role == null || HttpContext.Current.User.IsInRole(swaggerRole.Role))
{
var route = "/" + apiDescription.RelativePathSansQueryString();
if (paths.Any(p => p.Key == route))
{
var path = paths.FirstOrDefault(p => p.Key == route);
if (!swaggerDoc.paths.Contains(path) && !path.Key.ToLower().StartsWith("/episerver/"))
{
swaggerDoc.paths.Add(path);
}
}
}
}
}
}
}
To install swagger to your application:
Install the nuget package Swashbuckle to your project
Enable creation of XML documentation file in project settings:
Edit SwaggerConfig.cs in the App_Start folder to:
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.DocumentFilter<ShowInSwaggerFilter>();
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
c.UseFullTypeNameInSchemaIds();
c.SingleApiVersion("v1", "ExampleProject");
})
.EnableSwaggerUi(c =>
{
});
}
}
Now you just need to add the custom attribute to your controllers and decorate them with all descriptions that swagger needs, for example:
/// <summary>
/// Test Api
/// </summary>
[ShowInSwaggerRole("Administrators")]
public class TestController : ApiController
{
/// <summary>
/// Test
/// </summary>
/// <group>Test Api</group>
/// <verb>GET</verb>
/// <url>http://localhost:60808/api/testapi/test</url>
/// <response code="200"><see cref="string"/> object retrieved</response>
/// <returns></returns>
[HttpGet]
[Route("Api/Test/Test")]
public string Test()
{
return "test";
}
}
To use Episerver internal login just create a folder in your project on root level named “swagger” and add a web.config into it with following content:
Leave a Reply