Showing posts with label Exception Handling. Show all posts
Showing posts with label Exception Handling. Show all posts

Monday, 27 October 2014

6 Ways To Handle The Exceptions In Asp.Net MVC 4

Handling exceptions and presenting them to the user in appropriate way instead of default error message is best approach to tell end user "What to do when it happen?"

I found several ways to handle errors but I'm posting the popular ones.

1. Redirect to Custom Error - Simplest Approach

In try..catch block, if you want to redirect to custom error page on the basis of specific conditions you can use HandleErrorInfo class to do so. Example is

// Define variable of type Exception & HandleErrorInfo Exception exception; HandleErrorInfo errorInfo; // Do something like you filter the Client with Id // And clientPresent is a variable which hold Client data which // is use futher to insert its Customers if (clientPresent != null) { // Add its Customer } else { exception = new Exception("Unable to recognize the Client!"); errorInfo = new HandleErrorInfo(exception, "Home", "Index"); return View("Error", errorInfo); }

In above code, you define the appropriate message, add it to HandleErrorInfo class. HandleErrorInfo class contains three parameters.
  • Exception           : Custom format of message
  • Controller Name  : Where this exception raise
  • Action Name       : Action name contains exception

2. Writing try..catch

A classic approach to catch any exception. You use this inside the controller code and handle the exceptions that may occur. Here the only thing you have to take into account is what is the controller action is returning. Here you have two approaches & choose one to follow. First approach is "If you return a view, when you catch an exception you should redirect to an error page." is define above and second approach is "when you return JSON you should return a JSON with the exception message and handle it on the client side" is define here:

public ActionResult Index() { try { //Do stuff here } catch (Exception e) { //Redirect to an error page Response.Redirect("URL to the errror page"); } return View(); } public JsonResult GetJson() { try { } catch (Exception e) { //Return the exception message as JSON return Json(new { error = e.Message }); } return Json("Return data here"); }

The main disadvantage of this approach is that you have to use it everywhere and you bloat the code.

3. Override OnException method inside the Controller

You can handle all the exceptions inside a controller is by overriding the OnExeception method. With this approach you code only one exception handling routine per

Controller and you don`t bloat the code. Example is:

protected override void OnException(ExceptionContext filterContext) { //If the exeption is already handled we do nothing if (filterContext.ExceptionHandled) { return; } else { //Determine the return type of the action string actionName = filterContext.RouteData.Values["action"].ToString(); Type controllerType = filterContext.Controller.GetType(); var method = controllerType.GetMethod(actionName); var returnType = method.ReturnType; //If the action that generated the exception returns JSON if (returnType.Equals(typeof(JsonResult))) { filterContext.Result = new JsonResult() { Data = "Return data here" }; } //If the action that generated the exception returns a view if (returnType.Equals(typeof(ActionResult)) || (returnType).IsSubclassOf(typeof(ActionResult))) { filterContext.Result = new ViewResult() { ViewName = "URL to the errror page" }; } } //Make sure that we mark the exception as handled filterContext.ExceptionHandled = true; }

But same disadvantage that you have to override the OnExecption method inside every controller it`s not the best approach. You need to react in a different way if your exception throwing action returns a view or returns JSON. Also, you have to make sure that you specify that the exception was handled. Skipping this will throw the exception further.

4. Using the HandleError attribute

You can use HandleError attribute. When you provide this attribute to your controller class or to your action method, when an unhandled exception is encountered MVC will look first for a corresponding view named Error in the controller`s view folder. If it can`t find it there, it will look inside the shared view folder and redirect to that view.

[HandleError] public ActionResult Index() { return View(); }

You can also filter the type of error you want to handle

[HandleError(ExceptionType = typeof(SqlException))] public ActionResult Index() { return View(); }

5. Extending the HandleError attribute

You can code your own logic to handle errors using attributes. All you have to do is to extend the existing HandleErrorAttribute and override the OnException method. All you need to create a custom HandleErrorAttribute using the logic mentioned above.

public class HandleCustomError : System.Web.Mvc.HandleErrorAttribute { public override void OnException(System.Web.Mvc.ExceptionContext filterContext) { //If the exeption is already handled we do nothing if (filterContext.ExceptionHandled) { return; } else { //Determine the return type of the action string actionName = filterContext.RouteData.Values["action"].ToString(); Type controllerType = filterContext.Controller.GetType() ; var method = controllerType.GetMethod(actionName); var returnType = method.ReturnType; //If the action that generated the exception returns JSON if (returnType.Equals(typeof(JsonResult))) { filterContext.Result = new JsonResult() { Data = "Return data here" }; } //If the action that generated the exception returns a view //Thank you Sumesh for the comment if (returnType.Equals(typeof(ActionResult)) || (returnType).IsSubclassOf(typeof(ActionResult))) { filterContext.Result = new ViewResult { ViewName = "URL to the errror page" }; } } //Make sure that we mark the exception as handled filterContext.ExceptionHandled = true; } }

You use this custom implementation like this

[HandleCustomError] public ActionResult Index() { return View(); }

6. Handle all errors inside Global.asax

This method uses a global error handling that captures all exceptions into a single point. The only problem is to determine if we have to return a view or some JSON in case of AJAX request. Included in the snippet below there is a method that uses reflection to do all this.

public class MvcApplication : System.Web.HttpApplication { void Application_Error(object sender, EventArgs e) { //We clear the response Response.Clear(); //We check if we have an AJAX request and return JSON in this case if (IsAjaxRequest()) { Response.Write("Your JSON here"); } else { //We don`t have an AJAX request, redirect to an error page Response.Redirect("Your error page URL here"); } //We clear the error Server.ClearError(); } //This method checks if we have an AJAX request or not private bool IsAjaxRequest() { //The easy way bool isAjaxRequest = (Request["X-Requested-With"] == "XMLHttpRequest") || ((Request.Headers != null) && (Request.Headers["X-Requested-With"] == "XMLHttpRequest")); //If we are not sure that we have an AJAX request or that we have to return JSON //we fall back to Reflection if (!isAjaxRequest) { try { //The controller and action string controllerName = Request.RequestContext. RouteData.Values["controller"].ToString(); string actionName = Request.RequestContext. RouteData.Values["action"].ToString(); //We create a controller instance DefaultControllerFactory controllerFactory = new DefaultControllerFactory(); Controller controller = controllerFactory.CreateController( Request.RequestContext, controllerName) as Controller; //We get the controller actions ReflectedControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType()); ActionDescriptor[] controllerActions = controllerDescriptor.GetCanonicalActions(); //We search for our action foreach (ReflectedActionDescriptor actionDescriptor in controllerActions) { if (actionDescriptor.ActionName.ToUpper().Equals(actionName.ToUpper())) { //If the action returns JsonResult then we have an AJAX request if (actionDescriptor.MethodInfo.ReturnType .Equals(typeof(JsonResult))) return true; } } } catch { } } return isAjaxRequest; } //snip }

Monday, 11 August 2014

Spring MVC REST Exception Handling Best Practices (Part 1)



If you’re already using Spring to build your application, and you need to serve a ReST API,Spring MVC can be a good choice to write your REST endpoints.
However, representing errors or problems cleanly in a RESTful way may not be immediately obvious since Spring MVC is so often referenced for building user interfaces. Because there is no direct UI concept in REST APIs, how then do you use Spring MVC to represent errors or problems in a clean and intuitive way?
This article is Part 1 of a 2 part series. In this article, we’ll cover RESTful error reporting best practice conventions. Part 2 will show how to implement them with Spring MVC in a complete example web application.

RESTful Error Design

If an error occurs, RESTful practices expect that we set an HTTP status code in the response to generally classify why the request failed. It is considered best practice by most REST API designers to re-use the status codes in the HTTP specification whenever possible, since so many existing HTTP clients understand most of these error conditions already and re-use encourages consistent behavior, which is always good for development.
However, there are only 24 commonly referenced HTTP status codes that are used for representing errors; there are 18 4xx codes representing client errors and 6 5xx codes representing server errors (there are other codes defined in specifications like WebDav, but they are not ubiquitous). A problem here is that these 24 are really general purpose codes - they likely don’t describe everything there is to know about a particular problem.
To best help your REST API customers, you ideally want to give them as much information as possible to help them diagnose and hopefully fix the problem. The name of the game is simplicity: the easier it is for them to use your REST API, the more likely it is they will adopt your service.

REST Error Representation

Because the status code is probably not enough, what else then can we provide to assist our end users whenever they encounter errors? An obvious item is human readable error message, to be easily read by developers. But there is even more information that we can add to provide a truly intuitive and helpful error representation.
The folks at Apigee have put together a nice blog article about RESTful error representations (and some great videos too) worth checking out. We want to do something similar.
Here is an example of what we consider a ‘best practice’ REST error response body representation to show relevant error data (the example is JSON, but XML would be fine too depending on what your API serves):
{
    "status": 404,
    "code": 40483,
    "message": "Oops! It looks like that file does not exist.",
    "developerMessage": "File resource for path /uploads/foobar.txt does not exist.  Please wait 10 minutes until the upload batch completes before checking again.",
    "moreInfo": "http://www.mycompany.com/errors/40483"
}
We’ll describe the properties next.

status

The status property is merely the same HTTP status code (integer) in the response header. This is a convenience mechanism: by including the status code in the body, any REST client that processes the error has one and only one place to look to fully understand the error: the error representation itself.  There is no need to check header values or other locations to understand the message.

code

The code property is an error code specific to your particular REST API. It is usually something that conveys information very specific to your problem domain.
This is convenient because of the limitation of having only 24 widely known general purpose HTTP error codes. By using your own codes, you can convey much more specific and richer reasons as to why something failed. Again, the more information that the API client can receive, the better.
In the example above, the code property has a value of 40483. While the general purpose“status”: 404 indicates that the requested resource was not found, perhaps there is an application-specific code of 40483 that indicates not only that the resource wasn’t found, but it wasn’t found due to the fact that it wasn’t yet uploaded to the server.
Granted, this particular ‘uploaded file’ example is somewhat contrived, but the key point here is that your API can convey a much richer set of error information if you leverage your own codes.
TIP:  If your application does not have a specific error code for a particular error, it can be a good idea to default the code value to be the same as the status value. This ensures that the client always sees a code value and does not need to perform ‘does this property exist?’ logic. This is cleaner/easier for API consumers, and that’s a good thing for adoption.

message

The message property is a nice human readable error message that can potentially beshown directly to an application end user (not a developer).  It should be friendly and easy to understand and convey a concise reason as to why the error occurred.  It should probaby not contain technical information.  Technical information should be in thedeveloperMessage property instead (covered next).
Why is this useful?
If you have a REST API consumer (e.g. your customer), and that consumer wishes to relay the message value directly to the end user, they can do so.  This allows API consumers to write user interfaces and support their own end-users very quickly without much work on their end.  The more things you do to save them time and keep them happy using your API, the better.

developerMessage

The developerMessage property conveys any and all technical information that a developer calling your REST API might find useful.  This is where you might include exception messages, stack traces, or anything else that you think will help a developer.

moreInfo

The moreInfo property specifies a URL that anyone seeing the error message can click (or copy and paste) in a browser.  The target web page should describe the error condition fully, as well as potential solutions to help them resolve the error condition.  
This is probably THE most important property of all because the target web page can be freely formatted to represent whatever information you wish.  You could have links to your support department, ‘get help now’ chat dialogs, or whatever else you think might be useful.  Show the developers love, and they’ll continue using your API.
Twilio for example has a great Error and Warning Dictionary that shows this concept in action.  Learn it, love it, replicate it.  Again, as much information as is possible is desired.  Supply whatever you might think is necessary to help your API consumers/customers and keep them happy.

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...