Reputation: 47804
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 ?
Upvotes: 22
Views: 17425
Reputation: 27187
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.
Upvotes: 26
Reputation: 17540
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.
Upvotes: 4