Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restricting auto Help Page contents when using Attribute Routing in Web API 2

I'm currently implementing a Web API using Web API 2's attribute routing (http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2). I am also using the Help Pages module in order to automatically generate documentation from XML comments (http://www.asp.net/web-api/overview/creating-web-apis/creating-api-help-pages).

For this API I am providing support for optional return format extensions, so that every API method has a pair of routes defined on it like so:

[HttpGet]
[Route("Path/Foo")]
[Route("Path/Foo.{ext}")]
public HttpResponseMessage DoFoo()
{
    // Some API function.
}

This allows a user to hit any of these and get a result:

www.example.com/api/Controller/Path/Foo 
www.example.com/api/Controller/Path/Foo.json
www.example.com/api/Controller/Path/Foo.xml

My issue is that when Help Pages uses MapHttpAttributeRoutes() to generate documentation, it is picking up both routes for each method. So right now I see help for:

api/Controller/Foo
api/Controller/Foo.{ext}

But I want to only see:

api/Controller/Foo.{ext}

I would prefer to hide the non-extension route on each method, so that every method only shows a single Help Page entry.

Has anyone else tried something similar? Is there a work around that I am missing?

like image 514
jmsb Avatar asked Jan 13 '23 01:01

jmsb


1 Answers

My question would be is that, would consumers of your api figure out easily that the {ext} is optional?...personally, I would prefer the default behavior...but anyways following are some workarounds that I can think of:

  1. A quick and dirty workaround. Split the DoFoo into 2 actions like DoFoo() and DoFooWithExt maybe. Notice that I am using an attribute called ApiExplorerSettings, which is for HelpPage purposes. Example below:

    [HttpGet]
    [Route("Path/Foo")]
    [ApiExplorerSettings(IgnoreApi=true)]
    public HttpResponseMessage DoFoo()
    {
        return DoFooHelper();
    }
    
    [HttpGet]
    [Route("Path/Foo.{ext}")]
    public HttpResponseMessage DoFooWithExt()
    {
        return DoFooHelper();
    }
    
    private HttpResponseMessage DoFooHelper()
    {
        //do something
    }
    
  2. Create a custom ApiExplorer (which HelpPage feature uses internally) and check for specific routes like the following and can decide whether to show the action or not for that particular route.

    // update the config with this custom implementation
    config.Services.Replace(typeof(IApiExplorer), new CustomApiExplorer(config));
    
    public class CustomApiExplorer : ApiExplorer
    {
        public CustomApiExplorer(HttpConfiguration config) : base(config)
        {
    
        }
    
        public override bool ShouldExploreAction(string actionVariableValue, HttpActionDescriptor actionDescriptor, IHttpRoute route)
        {
            if (route.RouteTemplate.EndsWith("Path/Foo", StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
    
            return base.ShouldExploreAction(actionVariableValue, actionDescriptor, route);
        }
    }
    
  3. Get list of all ApiDescription from the default ApiExplorer and then filter out the descriptions which you do not like. Example: Configuration.Services.GetApiExplorer().ApiDescriptions.Where((apiDesc) => !apiDesc.RelativePath.EndsWith("Path/Foo", StringComparison.OrdinalIgnoreCase))

like image 64
Kiran Avatar answered Jan 31 '23 10:01

Kiran