When CreateResponse<T> runs content negotiation, it uses typeof(T) for the type parameter. This effectively means that it is passing in the return type of the action method on the controller.
CreateReponse should instead use the run time type of the value parameter, which may be a subtype of T.
Suppose you have a class hierarchy with Parent and Child. You have a mediatypeformatter that knows how to write Child. You have a controller action whose return type is Parent and whose implementation is something like "return new Child();".
Using the current implementation, a request with a valid media type for child to the action method will fail with 406, because CreateResponse will pass typeof(Parent) into negotiation, which doesn't have a formatter. If it used the run time type of the result, it would pass in typeof(Child) which would succeed.
I don't see how it is possible in the current implementation to deal with inheritance hierarchies in results where you have custom media type formatters that can only deal with a subset of types.
Comments: My previous comment's workaround was incorrect...you can discard it...Following is one correct workaround example: public HttpResponseMessage Get() { // let's assume we have like this: // class Person, // class Administrator : Person // class Supervisor : Person Person p = GetPersonHelper(); // this could return Supervisor or Administrator instances Type runtimeType = p.GetType(); // Probably you might want to create your own extension to HttpRequestMessage DefaultContentNegotiator negotiator = new DefaultContentNegotiator(); ContentNegotiationResult result = negotiator.Negotiate(runtimeType, this.Request, this.Configuration.Formatters); HttpResponseMessage response = new HttpResponseMessage(); response.Content = new ObjectContent(runtimeType, p, result.Formatter, result.MediaType); return response; }
CreateReponse should instead use the run time type of the value parameter, which may be a subtype of T.
Suppose you have a class hierarchy with Parent and Child. You have a mediatypeformatter that knows how to write Child. You have a controller action whose return type is Parent and whose implementation is something like "return new Child();".
Using the current implementation, a request with a valid media type for child to the action method will fail with 406, because CreateResponse will pass typeof(Parent) into negotiation, which doesn't have a formatter. If it used the run time type of the result, it would pass in typeof(Child) which would succeed.
I don't see how it is possible in the current implementation to deal with inheritance hierarchies in results where you have custom media type formatters that can only deal with a subset of types.
Comments: My previous comment's workaround was incorrect...you can discard it...Following is one correct workaround example: public HttpResponseMessage Get() { // let's assume we have like this: // class Person, // class Administrator : Person // class Supervisor : Person Person p = GetPersonHelper(); // this could return Supervisor or Administrator instances Type runtimeType = p.GetType(); // Probably you might want to create your own extension to HttpRequestMessage DefaultContentNegotiator negotiator = new DefaultContentNegotiator(); ContentNegotiationResult result = negotiator.Negotiate(runtimeType, this.Request, this.Configuration.Formatters); HttpResponseMessage response = new HttpResponseMessage(); response.Content = new ObjectContent(runtimeType, p, result.Formatter, result.MediaType); return response; }