1

Here @GlennBlock mentioned that throwing HttpResponseException immediately stops request execution while returning HttpResponseMessage does not stop request propagation (as I understood it).

The exception is useful to immediately stop processing and exit.

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.

In .NET Web API 2 you can also return IHttpActionResult from ApiController. Does it stop request propagation or it works similar to HttpResponseMessage?

Thank you;)

Community
  • 1
  • 1
Nikolai Samteladze
  • 7,699
  • 6
  • 44
  • 70

1 Answers1

3

I think @GlennBlock is technically wrong here. Throwing an HttpResponseException does not do anything significantly different than returning an HttpResponseMessage.

Here is the pattern used in ASP.NET Web API courtesy of the source code:

try
{
    return await SendAsyncCore(request, cancellationToken);
}
catch (HttpResponseException httpResponseException)
{
    return httpResponseException.Response;
}
catch (Exception exception)
{
    exceptionInfo = ExceptionDispatchInfo.Capture(exception);
}

At this point in the pipeline if you had thrown an HttpResponseException it gets treated the same as if you returned an HttpResponseMessage... it behaves exactly the same.

One thing you will notice is that when debugging with Visual Studio the debugger will break on a thrown HttpResponseException (since the catch is not happening in user code). If it's an expected error that happens commonly in normal operation of your site then this can get really annoying! In this case you probably instead want to return an error code with HttpResponseMessage.

On the other hand, if it's a bizarre error which should theoretically not happen then you want to be alerted by the debugger. You don't want the error to be quietly ignored. You want to know about it so you can theoretically fix it. In this case throwing the HttpResponseException makes more sense.

About the only other difference I can tell is that throwing an HttpResponseException allows you to catch it with an IExceptionFilter. Similar to how you can apply an action filter or an authorization filter to a method or controller, you can apply an exception filter to handle all exceptions. Perhaps you want to log them in your database. It's obviously a lot easier to apply an attribute filter than to have to write a try/catch in every single action method.

In this case throwing an exception actually does more work and takes longer than simply returning a response. But it is one difference.

An IHttpActionResult is used to create an HttpResponseMessage. Think of it as a HttpResponseMessage factory where you can write it once and use it by multiple action methods. In this case you could throw the HttpResponseException from within the IHttpActionResult. It's not any different than doing it directly from the action.

Trevor Elliott
  • 11,292
  • 11
  • 63
  • 102
  • Nice insight about the debugging problem. I think the point in the referenced question was that HttpResponseException immediately stops the request processing while returning HttpResponseMessage does not. – Nikolai Samteladze Nov 08 '13 at 16:55
  • Also, I actually wondered how IHttpActionResult works in comparison with HttpResposeException and HttpResponseMessage. – Nikolai Samteladze Nov 08 '13 at 16:56
  • @NikolaiSamteladze Returning the `HttpResponseMessage` is literally the last thing in the request chain. There is no processing to be stopped here. – Trevor Elliott Nov 08 '13 at 17:09
  • An `IHttpActionResult` is used to create an `HttpResponseMessage`. Think of it as a `HttpResponseMessage` factory where you can write it once and use it by multiple action methods. In this case you could throw the `HttpResponseException` from within the `IHttpActionResult`. It's not any different than doing it directly from the action. – Trevor Elliott Nov 08 '13 at 17:17
  • So, `return Request.CreateResponse(HttpStatusCode.OK)` will immediately stop request processing and non of the controller's code below this statement will be executed, correct? – Nikolai Samteladze Nov 08 '13 at 17:21
  • Right. That's the same with every C# method, not just an ApiController method. Returning from a method stops execution of the method. There's no magic going on here, it's following all the rules of standard C# code which means that `using` disposal and `finally` blocks are still executed regardless of whether an exception is thrown or the method returns. – Trevor Elliott Nov 08 '13 at 17:25
  • Makes sense, I think I misunderstood the point in the question that I linked. Can you please add your comment about IHttpActionResult to your answer and I will accept it. Thank you! – Nikolai Samteladze Nov 08 '13 at 17:31