Saturday, May 26, 2012

Two ways to work with HTTP responses in ApiController, HttpResponseMessage and HttpResponseException

Two ways to work with HTTP responses in ApiController, HttpResponseMessage and HttpResponseException:
ASP.NET Web API provides two different ways to work with manipulating HTTP response messages from within your API Controller action.
  • Throw an HttpResonseException – This exception allows you to pass in an HttpResponseMessage / set status and headers. Web API will then immediately return the response.
  • Return an HttpResponseMessage – You can simply return an HttpResponseMessage from your action.
So which  should you use when? Are they both identical? Cuong Le recently asked this question on StackOverflow.
The simple answer is no they are not the same.
The main difference between the two is this. The exception is useful to immediately stop processing and exit. For example assume I have the following code

    public class CustomerController : ApiController {
      private ICustomerContext repo;
      public CustomerController(ICustomerContext repo) {
        this.repo = repo;
      }
      
      public Customer Get(int id) {
        var customer = repo.Customers.SingleOrDefault(c=>c.CustomerID == id);
        if (customer == null) {
          throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
        }
        return customer;
      }
    }


If this code runs and I pass an id that is not present, it will immediately stop processing and return a status code of 404.
If instead I return HttpResponseMessage, the request will happily continue the rest of it’s processing and return a 404. The main difference being end the request or not.
As Darrel said, the exception is useful in cases where in some cases I want processing to continue (as in when customer is found) and in others I don’t.
The place where you might want to return HttpResponseMessage directly is in an HTTP POST to return a status code of 201 and set the location header. In that case I do want processing to continue. That would would do with this code.*

    public class CustomerController : ApiController {
      private ICustomerContext repo;
      public CustomerController(ICustomerContext repo) {
        this.repo = repo;
      }
      
      public HttpResponseMessage Post(Customer customer) {
        repo.Add(customer);
        repo.SaveChanges();
        var response = Request.CreateResponse(HttpStatusCode.Created, customer);
        response.Headers.Location = new Uri(Request.RequestUri, string.format("customer/{0}", customer.id));
        return response;
      }
    }


*note: If you are using the beta bits you would create a new HttpResponseMessage<Customer>. I am using the later bits however which require you to use the CreateResponse extension method off of the Request.
Above, I am creating a response which sets the status code to 201, passes in the customer, and then sets the location header.
The response is then returned and the request continues processing.
Hope this helps clarify the difference.


DIGITAL JUICE

No comments:

Post a Comment

Thank's!