Exception Handling In .NET Core

Exception handling is a hot topic that is practically required for all real developement applications.
 
When we are going to develop any application in dotnet core it provides a very good concept, that is, middleware makes exeception handling very easy.
 
If we add this line of code in the pipeline under the configure method in startup.cs class and run the application then simply we get the error status code:
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
  2. {  
  3.    app.Run(context => { throw new Exception("error"); });  
  4. }  
as shown in image below,
 
This kind of error is not sufficient for any developer. Developers want some user friendly and propery readable message type of error.
 
In this case dotnet core provides inbulit middleware to get some user-friendly error.
 
Let's see it with an example.
 
In this case we need to Install Microsoft.AspNetCore.Diagnostics Package.
 
There are two ways to install this nuget packege
  1. Using Packge Manager
  2. Using Visual studio search option.
I am using Using Visual Studio search option as attached image.
 
 
Then after that I add the following code:
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env) {  
  2.     if (env.IsDevelopment() || env.IsStaging()) {  
  3.         app.UseDeveloperExceptionPage();  
  4.     }  
  5.     app.Run(context => {  
  6.         throw new Exception("error");  
  7.     });  
  8. }   
After running this application I am able to see an errror as shown in the image below.
 
 
In this article I will try to explain various easy ways to handle exceptions:
  1. Try Catch block
  2. In Built middleware
  3. Custom Middleware
  4. Exception Filter
Try Catch Block
 
It is one of the easiest ways to handle errors in any controller action method:
 
Let's see it with an example
  1. [Route("api/[controller]")]  
  2. [ApiController]  
  3. public class TestController: ControllerBase {  
  4.     // GET: api/Test    
  5.     [HttpGet]  
  6.     public IActionResult Get() {  
  7.         try {  
  8.             var empList = new List < string > ();  
  9.             empList = null;  
  10.             var countItem = empList.Count();  
  11.             return Ok(empList);  
  12.         } catch (Exception ex) {  
  13.             return StatusCode(HttpContext.Response.StatusCode, "Internal server error");  
  14.         }  
  15.     }  
  16. }   
When you run this application you will get this error:
 
Internal server error
 
So this kind of exception is working as expected, but we cannot use this code in any other controller action method. 
 
As we know when we develop any application then the main concern is that we should utilize greater code re-usablity.
 
In-built middleware
 
As above we have seen in-built middleware in the  UseDeveloperExceptionPage that is used to show exceptions in detail.
 
UseExceptionHandler is also an in-built middleware that we can use to handle exceptions.
 
In this case we will create some of our custom classes as show below:
  1. public class CustomError {  
  2.     public int StatusCode {  
  3.         get;  
  4.         set;  
  5.     }  
  6.     public string Message {  
  7.         get;  
  8.         set;  
  9.     }  
  10.     public override string ToString() {  
  11.         return JsonConvert.SerializeObject(this);  
  12.     }  
  13. }   
We will use this class in newly created static class and its extension method.
  1. public static class CustomExcepExceptionExtensions {  
  2.     public static void CustomExceptionHandler(this IApplicationBuilder app, ILogger < CustomExcepExceptionExtensions > logger) {  
  3.         app.UseExceptionHandler(appError => {  
  4.             appError.Run(async context => {  
  5.                 context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;  
  6.                 context.Response.ContentType = "application/json";  
  7.                 var contextFeature = context.Features.Get < IExceptionHandlerFeature > ();  
  8.                 if (contextFeature != null) {  
  9.                     logger.LogError($ "Null exception logged: {contextFeature.Error}");  
  10.                     await context.Response.WriteAsync(new CustomError() {  
  11.                         StatusCode = context.Response.StatusCode,  
  12.                             Message = "Internal Server Error."  
  13.                     }.ToString());  
  14.                 }  
  15.             });  
  16.         });  
  17.     }  
  18. }  
In this class we have created an extension method for UseExceptionHandler which we need to register in configure method.
 
As shown below:
  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger logger) {  
  2.     if (env.IsDevelopment()) {  
  3.         app.UseDeveloperExceptionPage();  
  4.     }  
  5.     app.CustomExceptionHandler(logger);  
  6. }   
Custom Middleware
 
It is one of the best ways to do exception handling.
 
So for that let's create custom middleware.
  1. public class CustomExceptionMiddleware {  
  2.     private readonly RequestDelegate _next;  
  3.     private readonly ILogger < CustomExceptionMiddleware > _logger;  
  4.     public CustomExceptionMiddleware(RequestDelegate next, ILogger < CustomExceptionMiddleware > logger) {  
  5.         _logger = logger;  
  6.         _next = next;  
  7.     }  
  8.     public async Task InvokeAsync(HttpContext httpContext) {  
  9.         try {  
  10.             await _next(httpContext);  
  11.         } catch (Exception ex) {  
  12.             _logger.LogError($ "Exception occur: {ex}");  
  13.             await HandleExceptionAsync(httpContext, ex);  
  14.         }  
  15.     }  
  16.     private Task HandleExceptionAsync(HttpContext context, Exception exception) {  
  17.         context.Response.ContentType = "application/json";  
  18.         context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;  
  19.         return context.Response.WriteAsync(new CustomError() {  
  20.             StatusCode = context.Response.StatusCode,  
  21.                 Message = "custom middleware error."  
  22.         }.ToString());  
  23.     }  
  24. }   
Register this custom middleware in configure method.
  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {  
  2.     if (env.IsDevelopment()) {  
  3.         app.UseDeveloperExceptionPage();  
  4.     }  
  5.     app.ConfigureCustomExceptionMiddleware();  
  6. }   
Now the code part is completed. Let's run our application and hit the URL as shown in the below image.
 
 
We are getting an error as expected.
 
If you have any issue, please download the attached code and run it.
 
I hope this will help you to handle exceptions in dotnet core.
 
Thank you for taking your valuable time to read the full article.