Custom ApiExplorer with namespace-based ApiControllers

I am trying to add API documentation to my backend system. By default, ApiExplorer and the help page worked absolutely fine until I introduced the versions to my Api controllers.

To add versions, I created subfolders in the Controllers folder:

  • v1
  • v2
  • v3

and there are versions of Api Controllers based on the version. In order for me to find Api, I need to rewrite DefaultHttpControllerSelector to account for the namespaces provided by any client, and map them to the right controllers:

This broke my default ApiExplorer, and the following property returns ZERO api server descriptions

Configuration.Services.GetApiExplorer().ApiDescriptions 

How can I customize an existing ApiExplorer and help it find Api controllers and not overwrite the entire ApiExplorer implementation. I really just need to show where to find my Api controllers.

Please inform.

+6
source share
3 answers

It turned out that ApiExplorer has nothing to do. Instead, you should change your controller selector based on the namespace:

 NamespaceHttpControllerSelector : DefaultHttpControllerSelector { //... public override IDictionary<string, HttpControllerDescriptor> GetControllerMapping() { var mapping = base.GetControllerMapping(); mapping["User"] = new HttpControllerDescriptor { Configuration = _httpConfig, ControllerName = "User", ControllerType = typeof(UserController) }; //... return mapping; } //... } 

I.e. After that, by default, ApiExplorer will find you as controllers and select all the actions.

+6
source

I will show you how to do it. This code is for training purposes only. Here I am not talking about design and best practices, so feel free to change whatever you want.

Well, you should follow these steps:

1) Create your own ApiExplorer:

 public class MyApiExplorer: ApiExplorer { private readonly string _version; public MyApiExplorer(string version) : base(GlobalConfiguration.Configuration) { _version = version != null ? version.ToUpperInvariant() : "V1"; foreach(var apiDescription in ApiDescriptions) { apiDescription.RelativePath = apiDescription.RelativePath.Replace("{version}", _version); } } public override bool ShouldExploreController(string controllerVariableValue, HttpControllerDescriptor controllerDescriptor, IHttpRoute route) { return controllerDescriptor.ControllerType.FullName.Contains(_version); } 

}

a) In the constructor, the _version will be converted to upperCase (only if it will be passed as lowerCase), but if it is zero, it will take V1 by default. Then change the relative path to show a specific version instead of {version}.

b) ShouldExploreController (in short) decide whether a particular controller will be displayed in the documentation. In this case, we will only show the controllers that the full name of its type contains the selected version.

2) Go to the HelpController class and change the Index method as follows:

 public ActionResult Index(string version) { //... Configuration.Services.Replace(typeof(IApiExplorer), new MyApiExplorer(version)); return View(Configuration.Services.GetApiExplorer().ApiDescriptions); } 

We replace the current ApiExplorer with our own to be returned when calling Configuration.Services.GetApiExplorer ()

Now you can use this ... / help? version = v1 or ... / help? version = v2 or ... / help? version = v3 and you will get specific api controller documentation.

+4
source

I recently ran into a similar problem and solved: 2 LOC:

 public class VersionControllerSelector : IHttpControllerSelector 

to

 public class VersionControllerSelector : DefaultHttpControllerSelector 

... and ...

 public VersionControllerSelector(HttpConfiguration config) 

to

 public VersionControllerSelector(HttpConfiguration config) : base(config) 
+1
source

All Articles