You have heard about exceptions and definitely confronted exceptions. If every system is healthy then it is of course good sign, however if it is error prone or exception prone then it's a little tough to manage business, and moreover, if the exception carries or brings lots of potential information and is promoted on the end user'sscreen then itdefinitely might be a big problem (exception always varies).
Sometimes it leads to trouble!
If I consider it, there are generally two types of exceptions: First is business exception, and second is system exception. Business exception is when you are not allowed to perform certain actions like invalid user during payment. Card number provided in the system is wrong or invalid at the moment. While a system exception or critical exception is like network failure, and due to this the channel is broken and credentials or sensitive information may be revealed. Connectivity exceptions with database may have sensitive information.
Sometimes it has been noticed that system/application just returns complete StackTrace in response body which doesn’t look good because it may carry confidential information. Rather than making it public we should log it using Log4net(possible utilized tool).
One of the basic examples which may have lots of potential information and may not leak to the end customer until essential, it throws an exception as below:
- [HttpGet]
- public HttpResponseMessageGetEmp(int id)
- {
- if (id % 2 != 0)
- {
- throw new ApplicationException("Error thrown @ Controller level");
-
-
-
-
-
- }
- }
Using Postman is shown below:
WebApi has one of the greaestt features with its release, it is the HttpResponseException class which helps you to add only header information and the status code (HttpStatusCode.NotAcceptable) passed as an argument to the HttpResponseMessage as shown below in sample code segment.
- [HttpGet]
- public HttpResponseMessageGetEmp(int id)
- {
- if (id % 2 != 0)
- {
-
- return newHttpResponseMessage(HttpStatusCode.NotAcceptable) {
- Content = new StringContent("Value sent as parameter doesn't accept criteria !!"),
- ReasonPhrase = "Error"
- };
- } else
- {
- return newHttpResponseMessage(HttpStatusCode.Accepted) {
- Content = new StringContent("Value sent as parameter accepted at controller level !!"),
- ReasonPhrase = "Accepted"
- };
- }
- }
The above code segment is one of the possible ways to handle exceptions at controller level. But you may confront a situation where a programmer would be happy to manage it at a centralized or global place at application level to reduce/mitigate code redundancy.
Here, I found it at HttpPipeLine level using IHttpActionInvoker which is also responsible for invoking controller’s action. The Action Invoker invokes the Controller Action and we can have custom implementation for this also. To achieve this you just need to replace the existing default action invoker; here I’ve just written a code segment to manage exception.
Action Invoker Execution process:
Step1. For this purpose, I’ve added a class Custom_ControllerActionInvoker.cs in solution with name as in the following screenshot,
Step 2: Code to manage exception at ActionInvokerlevel.
- public class Custom_ControllerActionInvoker: ApiControllerActionInvoker
- {
- public override System.Threading.Tasks.Task < System.Net.Http.HttpResponseMessage > InvokeActionAsync(HttpActionContextactionContext, System.Threading.CancellationTokencancellationToken) {
- var objResult = base.InvokeActionAsync(actionContext, cancellationToken);
- if (objResult.Exception != null)
- {
- Debug.WriteLine("Exception thrwon by controller {0} :", actionContext.ControllerContext.Controller);
- returnTask.Run < HttpResponseMessage > (() => newHttpResponseMessage(HttpStatusCode.InternalServerError));
- }
- elseif(objResult.Result.StatusCode == HttpStatusCode.Forbidden)
- {
-
- Debug.WriteLine("Exception thrwon by controller {0} :", actionContext.ControllerContext.Controller);
- returnTask.Run < HttpResponseMessage > (() => newHttpResponseMessage(objResult.Result.StatusCode));
- }
- return objResult;
- }
- }
Step 3: Register an Action Invoker in Global.asax to replace the default execution.
GlobalConfiguration.Configuration.Services.Replace (typeof (IHttpActionInvoker), newCustom_ControllerActionInvoker());
Press F5 and run Web API application. The following window will appear and ensure that Web API is running.
Send the Get request in order to verify the execution cycle as given below. Copy and paste the following Url (http://localhost:57888/api/employees/GetEmp/5) in PostMan tool as depicted in the following screenshot,
Later, It will go to desired controller’s action and return HttpResponseException as shown below:
Output will be as here:
This is how we can manage exception at ActionInvoker level and customize WebApi HttpPipeLine. Please must read wrapping up section below.
One of the best benefits of IHttpActionInvoker which I understood and gathered is that it provides you liberty to store the real runtime type of the response object in the actionContext.Request.Properties["RuntimeReturnType"] = objResult.GetType(); so you may utilize it later. Also you can control exceptions from single place as per the HttpResponse return by specific action. There are few other objects in WebApi Pipeline where you can fit custom exception handling like: ExceptionFilterAttributeandDelegateHanlderMessageHanlder and other is IHttpCustomInvoker.
Read more articles on ASP.NET: