Elegant Global Error Handling Using Middleware In ASP.NET Core

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
proper error handling is very important when we are building web apis in this video I'm going to show you how I approach air handling in web apis using asp.h core middlewares and by the end of this video you'll be able to introduce Global error handling in your applications as well if you're not familiar with the concept of middlewares in asp.net core don't worry I'm going to briefly explain what they are and then I'm going to show you three approaches to introducing middlewares to your application and I'm also going to discuss which approach I consider to be the best option you can see an example HTTP request pipeline in this image we have our HTTP request at the top over here and as it passes through the request pipeline it goes through three distinct middlewares before producing our response at the end the middleware itself acts as a decorator around the HTTP request allowing us to introduce additional logic before or after executing the request so you can write a piece of code in the middleware that executes before a request execute the request essentially passing it along the request pipeline onto the next middleware and after the request completes you can introduce additional logic before having to return the response from the middleware let's now jump into the code and see how we can actually create middlewares in our application we're starting off in program.cs of our.net6 web application notice that we are calling a few methods here like use https redirection and use authorization what these calls do is they configure the HTTP request pipeline in other words they are introducing firmware specific middlewares that you almost always want to use in your applications so if we want to introduce and middleware for error handling in our application we can do so here and this is going to be the first approach that I'm going to show you you can call the app.use method what this method call does is it adds a middleware to the request pipeline where we are providing the body for the middleware in this function here that we are passing in as the argument also as you can see this method has very nice documentation and it's even pointing us to the preferred version of this method that we are supposed to call so let's go ahead and do that I'm going to define a Lambda method with the context and the next request in the request Pipeline and this is how we can define a simple middleware to make the middleware complete we need to call the next request delegate and pass in the HTTP context as the argument and it's as simple as that what we can do here is introduce logic here before executing the request we can store the execution of this request into a variable there will be a task here allowing us to add additional logic after the execution of the request before completing this middleware and passing the result along through the request pipeline so how can we use this middleware to tackle error handling in our application I'm going to get rid of these comments here and I'm going to make this Lambda method asynchronous because I want to await the execution of the request Handler delegate so I'm actually going to await here we can get rid of the return statement and now that we are awaiting the execution of this request what we can do is add a try catch block and move the execution of our request into the try block what we have achieved now with this middleware is that every request is going to execute inside of our try catch statement and any exception thrown during the request execution and not handled explicitly is going to be cut by our middleware here where we can handle it appropriately and return some meaningful response from the API if you're wondering how you can manipulate the API response here you can do that by accessing the HTTP contact response value by calling context dot response and now you have access to the HTTP response of this request which you can modify in our example we may want to change the body of the response so as not to leak any sensitive information from the exception and we can also change the status code of the response to something that we think is appropriate either in the 400 or the 500 status code range for example whenever we catch an unhandled exception in our middleware we can set the status code to 500 which will match an internal server error we've already tackled how we want to approach air handling but I mentioned that this is only the first approach for how we can introduce middlewares in our web applications so I'm going to get rid of this and I'm going to add a new folder in our web application project I will call this folder middlewares and I'm going to add one class inside which is going to be our Global exception handling middleware the second approach for defining a middleware inside of a class is by following a convention that is set inside of the framework and the convention is you need to define a public asynchronous method that returns a task it needs to have a name of invoke async and it needs to accept an HTTP context argument and one more thing you need is to have a private read-only field which will be the request delegate you can call it next and you need to inject it from The Constructor so this is how you define a middleware by convention and inside of the invo casing method you can just await the request delegate and pass in the HTTP context and this is the complete implementation for how you define a middleware by convention I'm going to repeat it again the convention is you need to have an invoke casing method that accepts an HTTP context and you need to inject a request delegate from The Constructor and execute that request delegate inside of the invo casing method I'm going to add one more field here for the I logger that I'm going to also inject from The Constructor we are going to use this logger instance to log the exception that we are going to handle inside of the invo casing method so I'm going to introduce a try catch block again move the execution of our request delegate into the try block and inside of the catch block I'm going to log the exception that we catch here with a log level of error for example I'm going to pass in the exception and use the exception message as the second argument and now what I want to do is to change the response of the HTTP context I'm going to set the status code to an internal server error I'm going to use the HTTP status code enum and I'm going to set the status code to the internal server error value and since the HTTP response status code is an integer I just need to cast the in and value to an integer and now we are fine so this is a very simple exception handling middleware we execute our request inside of the try block if everything completes then great we just return the response otherwise there is an unhandled exception we first lock the exception and then we change the status code to 500 internal server error now that we have our middleware defined we need to tell our web application to use it we can do that by going back to program.cs and on the web application we need to call the use middleware method and pass in the type of our malware in this case the global exception handling middleware and with calling this method we have introduced our middleware to the request Pipeline and now every request is going to execute inside of our try cache block I'm going to add a breakpoint at the start of our middleware right here and I'm going to start the application and show you our middleware in action so we're here inside of Postman where I have a get request for getting the member from the API the web application is already running and I'm going to send this request as you can see we hit the breakpoint inside of our Global exception handling middleware so let's go ahead and execute our request as you can see there's an intentional exception being from here this is because I'm manually throwing this exception in order to illustrate how our Global error Handler works so if we proceed we just log the error we change the status code from 200 to 500 internal server error and we continue and return our response from the API if we go back to postman you can see that we are indeed getting 500 internal server error response from our API this is pretty much all that we need to do to introduce a global error Handler in our application and if you recall I said I'm going to show you three approaches to configuring middleware in our application the first approach was calling the app.use method and providing a Lambda function that's going to represent our middleware the second approach is what we see here which is the convention based approach where you define an invo casing method accepting an HTTP context and inject the request delegate from the construction which you use to execute the actual request and this approach is a little error prone because you have to actually remember what is the convention that you need to follow luckily we have a third option for defining middlewares and the main benefit of this last option is that it is strongly typed what we need to do is we need to make our class inherit from the I middleware interface which is available in the Microsoft asp.net core HTTP namespace let's go ahead and implement this interface as you can see this interface defines the same invoke method that we have used before which was by convention the main difference here is apart from the HTTP context it also has a request delegate parameter that you need to use to execute the HTTP request I'm going to copy over the implementation that we had in our previous method into the one that implements the imlware interface and get rid of our old method of course we need to make our method asynchronous we also need to replace the request delegate that we have injected from The Constructor with the one that is provided as an argument to this method I'm going to get rid of the value that we are injecting from The Constructor and we are only left with the eye logger that we are injecting from The Constructor so let's see how we can improve the implementation of our Global exception handling middleware apart from setting the status code to internal server error it would be beneficial if we provided some sort of standardized response from our API for example what I can do is create a new problem details instance populates it with some meaningful value serialize this instance into a Json string and write it to the response body so that it is returned from the API let's for example set the status code on the problem details to the same value they were setting above let's also set the type property to for example server error let's also set the title to the same value for whatever reason and let's say in the detail that an internal server error has occurred all right now what we need to do is to serialize our problem details into our Json string we can do that by calling the Json serializer in system text Json calling the serialize method and passing in our problem details this is going to return a Json string that we can now write to the response body to write to the response body you need to call context dot response dot write async method and pass in the Json string that we have just realized of course since this method is async we need to await it and one more thing that we should do here since we are returning a Json response from our API would be to set the content type on the response to application Json so I'm going to do that here this is looking much better now and is very close to something that you can use in a real world application we are still missing one last piece of configuration for our middleware to be configured properly I'm going to go back to program.cs and register our middleware as a service this is because we are implementing the I middleware interface and at runtime our middleware is going to be resolved from the imilware factory and for this to work we need to configure our middleware as a service so I'm going to say add transient and specify our middleware and now everything should work correctly so the two components that you need when you are using the strongly typed eye milware approach is register your middleware as a service and then call use middleware and specify which middleware to use I'm going to run the application again and show you how this is working we are back in Postman and I'm going to send the same HTTP request to our API as before and this one is going to be handled by our new strongly type middleware as you can see we hit the breakpoint inside of our new middleware let's go ahead and execute it this is going to throw an exception we log the exception with the logger we set the HTTP Response Code to internal server we create a new problem details error which we serialized to a Json string we set the response content type to application Json because we are returning Json from our API and our consumer needs to be aware of this and lastly we write the Json string to the HTTP response body it's also very important here that you have to set the content type value before you actually write to the response because if you try to change the content type or anything else on the response after writing to the body it's going to throw one exception as you can see this execute properly and we can return from our API back in prosman we are actually getting our problem details response with the type title status and detail value and as you can see the HTTP status code is unchanged we are still getting back 500 internal server error if you learned something useful in this video consider leaving this video a like for the YouTube algorithm so that we can reach a wider audience and grow this channel together subscribe to my channel so that you don't miss any of my future videos and until next time stay awesome
Info
Channel: Milan Jovanović
Views: 72,901
Rating: undefined out of 5
Keywords: global error handling, global error handling in asp.net core web api, global error handling in asp.net core, global error handling in mvc, global error handling in asp.net mvc, global error handler, global exception handler, global exception handling, error handling api, error handling middleware, global error handler middleware, global error handling middleware, global exception handler c#, global exception handler vs try catch, error handling api c#, web api error handling c#
Id: H3EbflpXVmo
Channel Id: undefined
Length: 13min 58sec (838 seconds)
Published: Tue Oct 18 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.