Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Per Route Formatter Configuration in Web API

The title more or less says it all. I am trying to configure the JSON MediaTypeFormatter to behave differently per route.

Specifically I have two routes in my WebAPI that are mapped to the same controller. Each route performs the same operation and returns the same data but for reasons of backwards comparability with existing consumers they must format their output slightly differently.

I could put some code in the Controller to determine if the request came in on the legacy route or the new route and change the formatters accordingly.

I could also use an ActionFilter to change the formatters where required.

I was however wondering if there is a way to configure formatters at a per route level because that is the level of abstraction where my API behaves differently. This could either be at the point of Route Configuration or in a Delegate Handler.

Any suggestions?

like image 417
Gavin Osborn Avatar asked Jan 14 '13 04:01

Gavin Osborn


1 Answers

I'm not entirely sure how much different your two JSONs are and what exactly you are doing with them, but if you ask me, I'd do it in the formatter:

public class MyJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
    private IHttpRouteData _route;

    public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, System.Net.Http.Headers.MediaTypeHeaderValue mediaType)
    {
        _route = request.GetRouteData();
        return base.GetPerRequestFormatterInstance(type, request, mediaType);
    }

    public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, HttpContent content, TransportContext transportContext)
    {
        if (_route.Route.RouteTemplate.Contains("legacy"))
        {
            //here set the SerializerSettings for non standard JSON
            //I just added NullValueHandling as an example
            this.SerializerSettings = new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore
                };
        }

        return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
    }
}

You would then replace the default JsonMEdiaTypeFormatter with this one.

    config.Formatters.RemoveAt(0);
    config.Formatters.Insert(0, new MyJsonMediaTypeFormatter());

In Web API you can have DelegatingHandler that only runs on a specific route, but that doesn't really make sense since Formatters collection is global so there is no point in modifying that in runtime even from a route-scoped handler.

like image 116
Filip W Avatar answered Nov 15 '22 06:11

Filip W