Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practice : Ways to handle errors and exception in web api controllers?

Tags:

I am working on a project and have relied heavily on web api for all my client side operations, be it account details update, new details added, modify everything has been done with ASP.NET Web Api and Backbone.js

Current Scene :

In the current scheme of things, I am returning a boolean value from my web api controllers, to indicate whether the operation was successfull or not.

Example :

[ActionName("UpdateAccountDetails")]
public bool PostAccountDetails(SomeModel model)
{
    bool updateStatus = _customService.UpdateAccountDetails(model);
    return updateStatus;
}

so after making an ajax call to this action, I check the response for true/false and display error or success messages.

Problem :

Now what happened was I started getting exceptions in my action, and the action kept returning false, and the error message was shown. But I was not able to find why ?

So I was wondering if there is a standard api response structure which every one follows ?

I had initially come up with this idea to have each web api action to return this class

public class OperationStatus
{
    public bool Result { get; set; } // true/false
    public string Status { get; set; } // success/failure/warning
    public List<string> WarningMessages { get; set; }
    public List<string> ErrorMessages { get; set; }
    public string OtherDetails { get; set; }
}

This change would be a major change and would be time and resource consuming, so I thought its better to have a second/third/fourth opinion on this.

Please put some thoughts on this.

Update :

With some little help from Mark Jones, I have come up with this

[ActionName("UpdateAccountDetails")]
public HttpResponseMessage PostAccountDetails(SomeModel model)
{
    bool updateStatus;
    string errorMessage;
    try{
        updateStatus = _customService.UpdateAccountDetails(model);
        if(updateStatus)
        {
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        return Request.CreateResponse(HttpStatusCode.InternalServerError);
    }
    catch(Exception exception)
    {
        errorMessage = exception.Message;
        return Request.CreateResponse(HttpStatusCode.InternalServerError, errorMessage);
    }

    return updateStatus;
}

Any thought on this ?

like image 656
Yasser Shaikh Avatar asked Dec 19 '12 11:12

Yasser Shaikh


People also ask

What are the different ways in which we can handle run time errors in Web API application code?

Exceptions are the errors that happen at runtime. Exception handling is the technique to handle this runtime error in our application code. If any error is thrown in web API that is caught, it is translated into an HTTP response with status code 500- "Internal Server Error".

How do you handle exceptions at controller level?

Another way to handle controller level exceptions is by overriding the OnException() method in the controller class. This method handles all your unhandled errors with error code 500. It allows you to log an exception and redirect to the specific view. It does not require to enable the <customErrors> config in web.


2 Answers

You should avoid using try/catch in the controller's action.

There are many ways to handle your problem. The simplest and cleanest solution would probably be to use an ActionFilter to handle the exceptions, something along the lines of:

public class ExceptionAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        Debug.WriteLine(context.Exception);

        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
        {
            Content = new StringContent("An error occurred!"),
            ReasonPhrase = "Deadly Exception"
        });
    }
}

Then you can just decorate your action with [ExceptionAttribute]. Of course you can extend that to behave differently for different types of exceptions - business exceptions, data exceptions, IO exceptions and so on, and return different status codes and feedback based on that as well.

I recommend you read an excellent article by Fredrik Normen - "ASP.NET Web API Exception Handling" http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx.

He provides a great overview of exception handling techniques for Web API.

like image 186
Filip W Avatar answered Oct 20 '22 03:10

Filip W


Instead of returning an HttpResponseMessage I would keep the API's the same and just throw an HttpResponseException when you catch an exception. Something like this:

throw new HttpResponseException(
    new HttpResponseMessage(HttpStatusCode.InternalServerError) 
       { ReasonPhrase = errorMessage });

This way you do not change the definition of your API and it will work with your GET actions as well, where you return some object that has to be serialized. If you are using the JQuery ajax method to send the request over then your error handler will catch this and you can retrieve the text message in the errorThrown parameter and handle it accordingly.

like image 37
Kevin Junghans Avatar answered Oct 20 '22 05:10

Kevin Junghans