How to make Web API routing ignore parameters when matching

I recently had a scenario where I was using an action filter to pass parameter values into a Web API controller’s parameters.  The problem I ran into is that unless you do some hacky stuff, there isn’t an option to do this OOTB.  By hacky, I mean defaulting values like

[HttpGet]
[Route("")]
public IHttpActionResult Get(string accountNumber = null) { }

That was not something I liked personally.  I wondered if it was possible to create an [Ignore] attribute and use it like you would for [FromBody] or [FromUri] like

public IHttpActionResult Get([Ignore] string accountNumber) { }

Turns out, it’s incredibly easy.

Little bit of background…

In case you don’t know, routing in MVC and Web API is done with best guessing: taking a URL and using the path and query string, try to match to a method and its best overload.  This is done using ValueProviderFactories (here is the query string implementation) that ultimately serialize data into dictionaries whose keys can be used to match to parameter names.  Unfortunately, though it makes sense why, if a parameter doesn’t have a dictionary from a factory to match up against, the method is seen as a non-match and skipped.

The solution

The solution is to create an attribute that just returns an empty factory list.  The parameter is seen as “handled” and nothing gets filled in, allowing matching to occur and filters to fire and everything else as normal.

The attribute class

public class IgnoreAttribute : ModelBinderAttribute
{
    /// <summary>
    /// Gets the value providers that will be fed to the model binder.
    /// </summary>
    /// <param name="configuration">The <see cref="T:System.Web.Http.HttpConfiguration" /> configuration object.</param>
    /// <returns>
    /// A collection of <see cref="T:System.Web.Http.ValueProviders.ValueProviderFactory" /> instances.
    /// </returns>
    public override IEnumerable<ValueProviderFactory> GetValueProviderFactories(HttpConfiguration configuration)
    {
        return new ValueProviderFactory[0];
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: