If we find the source code for class System.Net.HttpHttpRequestMessageExtensions at method with this signature, because there are several overloads:
public static HttpResponseMessage CreateResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value, HttpConfiguration configuration)We found the things related to content negotiation and checking for proper values from configuration, but at the end there's something like this:
return new HttpResponseMessage { Content = new ObjectContent<T>(value, result.Formatter, mediaType), StatusCode = statusCode, RequestMessage = request };and the key point is that if the typeof(T) is not equal to value.GetType() then the ObjectContent throws the exception because of the mismatching of types and that occurs when for example we declare the method with return type Person and for some reason we return either a Worker object or Student object (where both inherit from Person)
The first solution was to extract the important sentences from this source code and create my own extension for CreateResponse and using the ObjectContent non generic version, but later I decided to group this code in a Filter, in this case an Action filter, and it will be executed after each action is executed, the goal is to transform the any object return type action to a properly configured HttpResponseMessage. Here's the code.
public class HttpResponseFilter : ActionFilterAttribute { public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { var request = actionExecutedContext.Request; var response = actionExecutedContext.Response; if (response.Content != null && !response.Content.IsHttpResponseMessageContent() && response.Content is ObjectContent) { var objContent = response.Content as ObjectContent; var value = objContent.Value; var result = request.CreateResponse(System.Net.HttpStatusCode.OK); if (value != null) { var config = request.GetConfiguration(); var negociator = config.Services.GetContentNegotiator(); var nresult = negociator.Negotiate(value.GetType(), request, config.Formatters); result.Content = new ObjectContent(value.GetType(), value, nresult.Formatter); } actionExecutedContext.Response = result; } } }
Finally, we need to register the filter in application startup, i.e. in the file out of the box WebApiConfig.cs by adding this line:
config.Filters.Add(new HttpResponseFilter());Hope it helps you to improve your code, the source can be downloaded here.
No comments:
Post a Comment