How do I configure the status code returned by my ASP.NET Web API service when the request has an unsupported Content-Type?
asp.net-web-api, content-negotiation
Solution
Here is the solution I came up with to this problem.
It's broadly based on the one described here for sending a 406 Not Acceptable status code when there's no acceptable response content type.
public class UnsupportedMediaTypeConnegHandler : DelegatingHandler {
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken) {
var contentType = request.Content.Headers.ContentType;
var formatters = request.GetConfiguration().Formatters;
var hasFormetterForContentType = formatters //
.Any(formatter => formatter.SupportedMediaTypes.Contains(contentType));
if (!hasFormetterForContentType) {
return Task<HttpResponseMessage>.Factory //
.StartNew(() => new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));
}
return base.SendAsync(request, cancellationToken);
}
}
And when setting up your service config:
config.MessageHandlers.Add(new UnsupportedMediaTypeConnegHandler());
Note that this requires that that the char sets match as well. You could loosen this restriction by checking only the `MediaType` property of the header.
Problem
If a request is made to my Web API service that has a `Content-Type` header containing a type not supported by that service, it returns a `500 Internal Server Error` status code with a message similar to the following: ``` {"Message":"An error has occurred.","ExceptionMessage":"No MediaTypeFormatter is available to read an object of type 'MyDto' from content with media type 'application/UnsupportedContentType'.","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger) at System.Web.Http.ModelBinding.FormatterParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) at System.Web.Http.Controllers.HttpActionBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(HttpParameterBinding parameterBinder) at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext() at System.Threading.Tasks.TaskHelpers.IterateImpl(IEnumerator`1 enumerator, CancellationToken cancellationToken)"} ``` I would instead prefer to return a `415 Unsupported Media Type` status code as recommended, e.g, here. How do I configure my service to do this?