Search code examples
c#asp.net-web-apihttp-headerscontent-type

Web API unsupported media type when uploading - charset not passed


I'm developing a new web API and currently integrating (re-writing) the legacy API to work with the new one. However I'm having issues with the Excel templates. Every time I try do a POST I get a 415 unsupported media type error.

I have managed to make it work so I know my code is fine the problem is when I use the templates it sets the content type in the header to:

Content-Type: application/xml;

However, if I change the template to send:

Content-Type: application/xml; charset=utf-8

It works as I would expect. The problem is I can't change the templates in production. I have to make my code work with the templates as they are.


Solution

  • The issue here seems to be with the ending ; in the case of Content-Type: application/xml;...Web API relies on System.Net.Http library for getting request headers and this library gives a null for HttpRequestMessage's Content.Headers.ContentType in this case and Web API sees that Content-Length is greater than 0 but no Content-Type header and hence returns a 415 Unsupported Media Type.

    Following a workaround that I have tried and that works (I am using a Owin middleware as this would be a stage where I could modify the raw request header before the System.Net.Http library's parsing takes place...)

    public class FixContentTypeHeader : OwinMiddleware
    {
        public FixContentTypeHeader(OwinMiddleware next) : base(next) { }
    
        public override async Task Invoke(IOwinContext context)
        {
            // Check here as requests can or cannot have Content-Type header
            if(!string.IsNullOrWhiteSpace(context.Request.ContentType))
            {
                MediaTypeHeaderValue contentType;
    
                if(!MediaTypeHeaderValue.TryParse(context.Request.ContentType, out contentType))
                {
                    context.Request.ContentType = context.Request.ContentType.TrimEnd(';');
                }
            }
    
            await Next.Invoke(context);
        }
    }
    

    public void Configuration(IAppBuilder appBuilder)
    {
        appBuilder.Use<FixContentTypeHeader>();