Non-generic HttpResponseMessage and ObjectContent<T> and User types

Topics: ASP.NET Web API
May 18, 2012 at 4:59 PM

A simple and obvious question, yet I cannot find it in the framework.

OK there was the decision to remove generic HttpResponseMessage since its type could not be guaranteed through the pipeline. Which is all cool.

But now, I have this action in the service:

public Foo Get()
{
    return new Foo();     
}

But in a particular condition I want to return an explicit HTTP status code:

public Foo Get()
{
    return new HttpResponseMessage(HttpStatusCode.NotModified); 
    // won't compiled since return type is Foo!
}

The only solution I have found is to define service as

public HttpResponseMessage Get()
{
    return new HttpResponseMessage(HttpStatusCode.NotModified); 
    // or {Content = New ObjectContent<Foo>(...)}
}

Now I can return ObjectContent<Foo> but it forces me to provide an explicit MediaTypeFormatter, which I do not want to.

So what is the trick?

 

 

May 18, 2012 at 5:26 PM
Edited May 18, 2012 at 5:28 PM

Hi,

you have a couple of options. For returning a one-off status code in a method that normally returns a model type you can always throw an HttpResponseException.

If you do change the method return type to HttpResponseMessage then you can use the Request.CreateResponse(statusCode, model) extension method to get a HttpResponseMessage with the right ObjectContent<T>. If you want to create an ObjectContent<T> directly then you would have to run content negotiation yourself to obtain the appropriate MediaTypeFormatter instance (you can do this via the IContentNegotiator interface).

May 18, 2012 at 7:22 PM

Thanks Marcin. Second option is the one I had missed and was looking for. Cheers

May 20, 2012 at 12:19 PM

marcind, We find all this options lacking:

  1. Throwing an HttpResponseException for something that is not really an exception is a logic and efficiency problem.
  2. Declaring a return type of HttpResponseMessage when you really want to return a specific data type AND/OR a status code is a serious flaw in the declaration and syntax of api controller methods, which creates a long, unnecessary, misunderstood, repetitive and "ugly" code.

 

Please reconsider your design, because we found Web API great for our production needs, but these kind of flaws are really upsetting.

Thank you

Thingies Team 

May 20, 2012 at 2:33 PM

Thingies Team,

We can't think of any other alternatives. Either the return code of the action is a strongly typed business object in which case the only way to let the result of the action be something different is to throw an exception; or the response is an HttpResponseMessage in which case you have to set the strongly typed business object yourself using Request.CreateResponse overloads.

Hope this helps.

Henrik

May 20, 2012 at 2:44 PM

What about setting the response status code before returning the strongly typed business object?

Something like

"HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotModified;"

Right now if I do that, the status code still being override with 200 code. 

May 20, 2012 at 9:37 PM

Thanks, but we can't rely on HttpContext.Current as that is very much tied to running inside ASP and won't work when running in other environment such as self host. In Web API we expose HTTP requests and responses in the form of HttpRequestMessage and HttpResponseMessage so the best option for you is to use the ApiController.Request.CreateResponse overloads for creating a response or throw an exception in case you want to return a business object directly.

Henrik

May 20, 2012 at 9:54 PM
Edited May 21, 2012 at 8:50 AM

Ok will consider that.

In the meantime HenrikN , do you propose to rely our production on the beta version or the nightly builds?

and is there a stable version after the Beta?
Because relying on Beta in our production is one thing, but relying on nightly builds that are not stable is quite another thing...

Also is there a recap somewhere of the major differences between the beta and the currently nightly build?


Thank you

May 20, 2012 at 10:57 PM
ozba wrote:

In the meantime do you propose to rely our production on the beta version or the nightly builds?

and is there a stable version after the Beta?
Because relying on Beta in our production is one thing, but relying on nightly builds that are not stable is quite another thing...

Also is there a recap somewhere of the major differences between the beta and the currently nightly build?


Thank you

ozba,

I'm just a consumer of the Web API like you, so I'll give my thoughts on this.

I am in fact going to be using the pre-release versions of the Web API in a production environment.  I currently build from source code as needed and update as needed, including my soon to be production environment.

However...

I am doing this with the knowledge that it is a risk and it is a risk that I am responsible for -- not Microsoft.  Beta is beta,  not "release".  The nightly builds are nightly builds of pre-release software.  Use at your own risk.  If you are relying on pre-release software, it is your responsibility.  If you are not comfortable with that, wait for the release version.  Personally, I'm at a point in our product where I need to make a decision that will set the direction for the next couple of years most likely.  I want our API to be based on MVC 4 / Web API so I'm willing to take the risk.  I feel comfortable enough that if I run into trouble, I'll be able to find a solution -- either in the source code, in the community, or both.

I will say that if you are planning on sticking with MVC 4 / Web API, go with the nightly build.  Too many awesome (but not all backwardly compatible) improvements since Beta and if you plan on switching to the release version when it comes out, you'll have much less refactoring to do.

If you want to keep up with what has changed since Beta, follow the git repository commits; they are usually fairly detailed.  Read the forums.  That's all part of open source and pre-release software.

As to your original question, while the Web API method returning HttpResponseMessage may not feel right, it seems to be a very clean way of allowing various types of data to be returned and still have full flexibility for content negotiation, status code, headers, etc.  I'm sure someone can come up with a slicker way to do it, but the current implementation seems to meet the needs of a robust RESTful Web API quite nicely.

Mike

May 20, 2012 at 11:33 PM

I will second pretty much what Mike said.

With the number of changes since beta, it is pretty pointless to stick to beta.