Problem:
I need to handle web api 2 exceptions and return a rich object with the correct status code (401 for Unauthorized, 404 for ContentNotFound, etc) and some extra information as the content. Moreover, I need the content to look like a serialized Exception
object (have the message
, exceptionMessage
, stackTrace
, ... properties).
Suggested Solutions:
Create custom exception classes and writing a custom exception filter to apply to any controller's action. this custom exception filters handles the exception thrown according to it's type (one of the custom exceptions that I've already defined) and responds accordingly via something like this (filter's code):
context.Response = context.Request.CreateErrorResponse(HttpStatusCode.Unauthorized,
new Exception("my exception")));
wrapping the already written web api 2 *ActionResult
classes ( System.Web.Http.Results.UnauthorizedResult Unauthorized()
, System.Web.Http.Results.OkResult Ok()
, etc ) and adding some custom data to them and use them so that their result get passed to client every time they're called (the problem is in this case my controller's action's return type should be IHttpActionResult
which is not as easily testable and readable as a strongly typed action).
What solution should I choose? Or is there any other way to do what I'm trying to achieve here?
You can customize how Web API handles exceptions by writing an exception filter. An exception filter is executed when a controller method throws any unhandled exception that is not an HttpResponseException exception.
In ASP.NET MVC Web API, we usually have three ways to handle exceptions, HttpResponseException, associated with HttpStatusCode, --- Locally in Try-catch-final. Exception filter, --- in the level of Action, Controller, and Globally.
You can use the CreateErrorResponse extension method in your Web API controller method to return meaningful error codes and error messages. Note that the CreateErrorResponse method creates an HttpError object and then wraps it inside an HttpResponseMessage object.
Or you could use the built-in, out-of-the-box solution: exception filters.
Furthermore, you may be interested on exception handling starting from Web API 2.x.
From what I understand you don't want to handle exceptions thrown by the code, rather create them in your action methods. For the case where exceptions are thrown by other areas in the code (other things you call inside your actions or by other filters, you can either use exception filters or global error handling).
Hence I would go with your second approach (though you don't need to customize the action results much). Your code is actually a lot more easy to unit test with IHttpActionResult, because you can inspect the result type directly. In fact one of the reasons IHttpActionResults where added is to simplify unit testing.
The flow of your code is simpler as you don't need to throw to generate errors, and you can always inspect the content of an ok(returnValue) as you can see below.
[TestMethod]
public void GetProduct_ShouldReturnCorrectProduct()
{
var testProducts = GetTestProducts();
var controller = new SimpleProductController(testProducts);
var result = controller.GetProduct(4) as OkNegotiatedContentResult<Product>;
Assert.IsNotNull(result);
Assert.AreEqual(testProducts[3].Name, result.Content.Name);
}
http://www.asp.net/web-api/overview/testing-and-debugging/unit-testing-with-aspnet-web-api
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With