Exception Handling in ASP.NET Core – Middleware vs Filters – What's Best?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there and welcome back to the code wrinkles channel for a brand new video in which we'll talk about global exception handling in an asp.net core API and as you might already know there are actually two ways in which we could handle exceptions globally in asp.net core one way is to use a global exception handling middleware that kind of like would uh help us with the exception handling and then we could also have an exception filter and I have created already a video about filters on asp.net core and I will leave the link to this video in the description of this one if you have time out or if you want or if you are curious about filters in general you should definitely check that out and the question that I always get is what would be the best way to actually go about exception handing or Global exception handling in asp.net core should we use a middleware or should we use a filter for that and as I always say actually or in most cases in programming the answer is it depends it depends what you want to achieve therefore in this video I would like to go through both of the approaches and actually look like look a little bit at what's actually the real difference between them and try to understand the pros and cons for each of of the strategies or what we have at our disposal for instance if we handle it in middleware what we have at our disposal if we handle it in a filter so we want to take a practical look at this and understand exactly then what would be some scenarios in which you might want to do it in a filter or scenarios in which you might want to do it in the middleware so let's get first started I have here a very very simple API but as I always like to do I have structured it in a layered way in this case we have a domain layer here it's a weather forecast just like the regular template and we have then data access layer in which we actually have this repository that returns us the weather forecast in this X -layer the services and the forecast service that we kind of like use for this purpose and then of course we have this API and in this API I have controllers and the controllers what I'm doing here is actually I am just throwing an exception and as I mentioned here I'm throwing it just for fun so that we can have something to discuss about in this video but before we get really started let's see first of all the behavior and what we get for instance if we run this application right now and if we make a request here and let me bring this to the other window so that you can also see it let me make a get let me try it out execute and what you see here is we get kind of like the entire error here with the stack Trace with everything and this is of course not very very good to do so instead what we usually want to achieve in apis is that we want to have an error contract that we return whenever we might encounter some errors so if you go and check out documentation of I don't know very popular apis like the Spotify API or something similar you will always see that when a certain resource for a certain request for a resource has an error you got you get actually a very specific error response that has the same structure no matter what request you send the payload data might differ exactly depending on the resource that you have created but the structure of of the error response is actually always the same and that's because apis as also the name implies are contracts our program are programming interfaces so when we Define what we return consumers actually rely on that information so for instance I have here a contract like whenever I want to return an error I just want to have here a status code and I want to have a message but I don't want to have the stack trace of course you can enlarge this type of error contract providing also maybe time stamps on when the or when the error exactly occurred maybe providing some information about the resource that was requested so that's really up to you to decide exactly what your business or what your use case is and what information you would like to display actually in your errors as long as they are consistent and you get the same structured error messages no matter what resource actually do you request or the client's request and it's clearly in in our case at least so far that was actually not possible so in order to achieve this and make sure that we always return a certain error response with the same structure and of course in Json format because our API here is uh responding in Json so we have to stick to this even if we are returning errors we have a set two different strategies or two different possibilities so first of all we can use a middleware and if we look into this I have here created a custom middleware or exception handling purposes now in this middleware there's really nothing very very specific going on the only thing is that we wrap this away dot next in this try catch and here we have the sketch exception and here what we actually do we set the appropriate response headers because we want to return an error and then we create this body and we write this to the body and we have an override of the two string for our error response so that it returns a Json serialized string when we call the tostring method so that's actually everything that we do but of course you can get fancier with this API because here you can catch different type of exceptions like your very own domain or application specific exceptions you can catch them here and maybe write different messages uh in the message part of the error depending on what type of error do you have so you can get really fancy with this but if you want to have a video only on exception handling middleware because there are a lot or there are some caveats or things that might need to be discussed in more depth just let me or leave me a comment here to this video and if I see that there is really interest for a video dedicated only to exception handing middleware then I will certainly create one but for now I guess we should be good to go and if we go in the program.cs class where is it where is it here it is of course and I have commented out this app use exception middleware that's what I was using previously now if we run the application we'll see that hopefully of course our response will be much different in this time so let's let's just wait to run this it shouldn't really take long of course here it is so let me bring it as usual to the other screen but maybe we don't really need to enlarge this let's say this cat try it out execute and we should be able to see the response and voila here in this case we have a very nice Json formatted response that contains exactly the error response model that we have defined in our contracts and we are okay with this so we can close this application right now and everything seems to be fine cool now uh this was the the way that we have used with this exception handling middleware now let me first of all walk you through this other part with the filter but in order to use the filter we will actually have to add something here in the configuration because I already have an exception filter and I will show you this exception filter just in a few seconds and I would like to add my exceptional filter globally so this is why in the Splinter Services add controllers here we can take in a configuration object and here we can say a configuration filters add and I want to add my exception filter to this and what this means from a filter perspective is that right now this filter is applied globally so for each request no matter to which resources this filter will be applied and if we have an exception then this filter should handle the exception now let's take a look into this filter and we see here this filter we just have to implement this I exception filter there and here in this own exception we actually do something similar to what we have done in our middleware but here in this case we just create this error message and then we set the result with a Json result of error and the status code 500 because that's what we actually want to return and in fact we have set here uh things a little bit differently than than in the middleware and actually that's one of the explanations on why or what's the difference between a filter or a global exception filter or a global exception handling middleware but let's first of all run the application and ensure that we have actually the exact same result and then we'll go a little bit deeper into analyzing uh how these two different strategies or possibilities to handle exception actually work so we have this weather forecast let's click here on this cat we want to try it out and we execute it and we get the same thing here so we got the same error message uh like previously but right now we are using this exception filter and not the middleware cool now let's see what's actually different between an exception handling middleware and a filter and to do that I would like to come back actually to this white wardrobe or Blackboard representation that we have used in the previous video in which we talked generally about what filters are in asp.net core because this would actually also give you a first-hand idea on why actually the exception handling middleware or how exactly the exception and middleware and the filters are differently and if we take a look here what we have in this upper part that's actually the middleware pipeline and usually you would place an exception handing middleware as the first middleware here in the pipeline because that would be also the last through which the response would go through so if we have an error we can just handle that so the exception uh if you try to think visually the exception handling middleware would be actually here now if we use a filter we have to go deeper down the pipeline and we said that when we talk about filters after the routing middleware uh we get into the action execution Pipeline and the exception filter as you can see here is part of this action execution Pipeline and it happens right after the action filter so you see that actually from this spot actually where we have the exception handling middleware till this spot there are quite a different things that still can happen and we are conceptually in two different parts of the request processing so here for the middleware we are in the middleware request Pipeline and here we are in the action execution pipeline cool now what does this actually mean for us from a practical perspective now from a practical perspective it actually means that if we go to the middleware where is middleware this is the middleware cool so if we go to the Middle where traditionally if we are in a middle where we have access to this HTTP context and this means that we can do whatever we want right now with this HTTP context now of course there might be some caveats about this but I said this is something maybe for a different video now the idea is that here what we can do is basically only stuff that we can do on an HTTP context of course we could add some uh of our custom logic to I don't know maybe log the exceptions do whatever we want with them but in the end when we generate a response we can just set Properties or headers or values to the HTTP context and in processing that uh well exception we can only rely on information that we have actually in the HTTP context we can't really rely on any other type of information so this is what we have in the HTTP context okay cool now let's go to the filter the filter as we have seen is part of the execution of the action execution Pipeline and this means that here there are or there is a different set of things or Properties or information or state call it whatever you want that we have access to for instance uh let me just go uh here down a little bit okay let's also stop the application from running it doesn't really help and you see that we have here this x exception contact that's injected uh in this kind of like method by asp.net core so we don't have to care about it now if we look a little bit at the context we see that here we have a lot of additional information that maybe we don't have in the HP context so first of all we have access to the exception itself so we can have here access to really everything that's related to the exception the data the message The Source the inner exception if we have one a stack trace a Target site and every everything basically that's that's the exception itself it's the exception class so that's one thing that we have access to then from this exception context we also have access to the iaction result so this is for instance where we can set the iaction result and that's in fact what we are doing right at the end where we set the result with a Json result and we specify the body so we have access to this result which is very very important but then for instance we have this exception handled which is kind of like a flag if the exception is handled or not but then we have for instance also access to the different filter information so do you do we have other filters down the pipeline so there might be some information from the from other filters that you might want to check while processing this exception then you have for instance this action descriptor and if we look in this uh action descriptor that's actually quite nice and that's uh one very important thing that uh I think it might be well definitely a plus to use a global exception handling in filters because here for instance you have access to the entire action that that was actually triggered you have uh access to all the parameters uh of the action the properties the constraints uh the display name that's not not maybe important but filter descriptors then routed value so the the values actually uh that were part of this route so there are really a lot of things that you have here on this action descriptor that you actually might want to use uh when you handle your exception maybe when you are customizing the message that you want to return to your consumers and of course we have also access to the HTTP context so if we want actually to use or get some information or set some information maybe in the HP context we can do that but then we have also the model state so we have also information about the model State and maybe the exception was thrown because the model state was not valid or that there there are problems in the model state so that's really a vital part of information that might be important when processing or when creating your exception message but then we also have route data and in route data for instance you can have here for instance different routers that you can check to see exactly okay what happened you can you can clear that so you have information about the routing that occurred actually uh when um when this exception was thrown you have here access to this different type of values where you can get the keys for each route data you can you have a key end of value so you see the keys you see the values you have really access to everything that was concerning or that asp.net cortex actually created but in order for us to be able to execute that action and all this type of information uh or case here maybe I just delete it a little bit too long so all this type of information you actually don't have access to in the middleware so if you go in the middleware uh we'll see that yeah we just have the access to the HTTP context and information about hey what did we can get from the context so let's see here context for instance uh context and uh yeah we have the connection the features really everything that we have on the HTTP context like if the user is authenticated but as we see we still have access to the HTTP context also in the filter so all this data can we can gather also or we can use also in the filter but the action execution data we cannot actually use here in our uh Global exception handling middleware so this is actually the main uh difference uh on handling things or handling exception globally in a middleware compared to handling exception globally in a filter and here what I can tell you is that there is not really a best way or a perfect way to do it it kind of like depends on what you need to achieve my personal preference is though to actually use an exception filter for Global exception handling because I have access to a lot more information than in a regular exception handling middleware so that's actually the main point why I would like to do that now of course there might be also some different exception handling strategies that by the way if you actually are interested in this topic and would like a video on exception handling strategies in layered asp.net core applications also just leave a comment and let me know and if there is enough interest that will certainly do a video on on that one because there are some very important or some some night things things or strategies to consider or at least to to have a thought about whenever we actually want to create a new application okay cool but mostly that's what I wanted to show you in this video and well this is what I wanted to actually tell you and my personal preference but as very often happens in programming there is really no definite answer if uh you should do this in a middleware or if you should do this in the filter the main or the important thing is that you are aware of the differences that we have when doing it in a middleware and when doing it in in a filter because when you know this type of differences when you have to kind of like take a decision you can take an informed decision and you can take and you can say hey I would like to use this uh I would like to use a middleware as a global exception handling strategy and that's perfectly perfectly fine as long as you are aware that hey uh maybe there are there is some more information on the action execution context but I don't really care about this information when I am generating my errors and I want for instance my my exception handling to be as close as possible to the entry point in the application or to the exit point of the application when we think about the response uh so you can definitely choose that and it's okay but also you can say hey I would like me I think I it might be useful to have access also to all the action executing context information so in that case I would like maybe to use filters or a global exception filter for Global exception handling and it's also perfectly fine there's no problem with that it's being said thank you very very much for watching if you enjoyed this video and you think it might be useful uh don't be shy and share it with your colleagues with your peers I don't know maybe through emails social networks forums wherever you think that there might be people that might be interested that find this information useful uh share it and I would totally appreciate that and of course if you didn't subscribe to the code request Channel please do subscribe hit hitting the Subscribe button but also using the notification Bell to be all always informed when we post some new content here well and last but not least of course if you have anything that you want to add or questions that you have to ask also don't be shy and hit the comment section and leave your comments and I would be more than happy to get a discussion going this being said once again thank you very much for watching and until the next time I wish you the very best
Info
Channel: Codewrinkles
Views: 19,358
Rating: undefined out of 5
Keywords: asp.net core, dot net 7, filters in asp.net core, middleware in asp.net core, net core
Id: jrkuJulrFok
Channel Id: undefined
Length: 20min 33sec (1233 seconds)
Published: Sun Nov 06 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.