Search code examples
c#serializationasp.net-web-apimediatypeformatter

Custom MediaTypeFormatter (Serializer) for ApiController specific method


I have ApiController in place and one of methods needs have custom serialization.

    public async Task<Session> PostSession([FromBody] Session session)

There is massive Session object that holds everything and consumer does not want do get more than half of it, normally I could just decorate properties with [XmlIgnore()] and be done, however this object is being passed internally across many APIs and removing these would break these mechanisms.

Another solution would be to just replace that object with different one like CastratedSession and return that. I can't do this since same endpoint is being called by existing 3rd party APIs that expect to get Session or they would have to rewrite their stuff (not going to happen).

I then proposed to create a different endpoint that this 3rd party could call - but architect objected and said to do the custom MediaTypeFormatter based on specific content-type value they will set in header, problem is we already are using in this same controller custom MediaTypeFormatter, and the way I understand out of the box one can only set them in configuration per controller

public static void ConfigureApis(HttpConfiguration config)
{
    config.Formatters.Add(new CustomJsonFormatter()); 
    config.Formatters.Add(new CustomXmlFormatter()); 
}

Which sorta paints me into the corner.

How (Can) I setup a custom MediaTypeFormatter per method on ApiController?


Solution

  • figured out a workaround myself

    I inherited and replaced CustomXmlFormatter() with EvenMoreCustomXmlFormatter()

    then in WriteToStreamAsync did this:

      public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
        {
            if (content.Headers.ContentType.MediaType == "text/sessionXml") // this was agreed with 3rd party
            {
                //do my serialization stuff
            }
            else
            {
                return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
            }
        }
    

    hope this saves you some time.