Error handling strategies in ASP.Net Core APIs

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 this one we'll talk about error handling strategies in our asp.net core applications because I think there are two major strategies in which we can go about handling errors in our asp.in core applications and I want to present them to you now before we get started I want to say one thing this topic about exception handling in general is a very dogmatic topic that kind of like spawns a lot of discussion similar to the discussions around the repository pattern where there are of course Arguments for a pro and cons for each of the approaches that I will present here but what I want to do is actually to walk you through those approaches to try to understand what are the benefits what are the pros what are the cons of each of these approaches of course I will also tell you about what my personal preference is and what I think it works best for my applications but that's for sure not a rule that really everybody should try to accomplish or try to implement in their applications I really just want you to to be informed about the different possibilities and then take your informed decisions whenever you need to take them so that's the whole point of this entire discussion this being said let's get started with this topic about error handling strategies and the first one that's also maybe the most straightforward because it's kind of like in line with what you usually learn during our courses or University or during our first programming years it's to actually well use try catch blocks and throw exceptions and what we have here is a regular API a very very simple one but still layered with the usual layer that we might have in our asp.net core applications and here I have for instance this post controller and I have this get post by ID now here what I would do in this controller in this case is I would do a try and okay if everything's okay then I will return this okay okay but then if I have an exception then I catch the exception and well I log it because usually we want to lock these exceptions and then we rethrow them now what happens afterward we already described in a different video I would have either an exception uh filter or an exception Handler middleware that will kind of like get this exception and generate then an exception or error response for the consumer that made a call to my API but that is say autoscope of this video If you haven't watched the other video about how we can use filters or exception handling middleware to actually treat our exceptions in our API globally then there is a link here in the description of this video also there's a card here somewhere in the corner upright that you might click and you would be able to actually go and watch that specific video now with this approach what happens is that here I also have for instance this post service and in this post service I use the repository of course and as I used the repository in his post service I also will have a try catch block here because the post repository it might throw some errors the errors might come from Entity framework or for from any other orm that we are using or directly from SQL if you are kindling like executing directly code to SQL via a SQL command or something like that now we want to catch this exception and then of course once again maybe log this exception and throw it now the first thing that we have to notice here and here once again the discussions are kind of like heated and I would just really advise you to take everything with the grain of salt try these approaches try to understand how they work and what's actually best for you now the idea is that we might actually want to try and catch the exceptions in every layer of the application because what we want to do is for instance if we get here an SQL exception maybe I want to transform this to a custom exception of my application like I have for instance a I don't know data access exception that I have created and in which I might add different other information that might be useful when we want to log the information like maybe the provider that we use the query that we executed or things similar to that so it is really common uh that we would like to maybe catch these exceptions that we have here from the repository transform them or create a new exception that we will throw afterwards of course the original exception we will paste in or put in as the inner exception for that one as it would be a best practice and that would be the good way to go on the other hand there are there is the other approach here when it comes to throwing these exceptions directly is that okay we don't really need this try and catch block here in the service it's enough theoretically if we have this try catch block here in the controller because this would catch eventually all the exceptions that may come from Downstream from this get post by ID method and that would of course also work and there shouldn't be any problems but in that case you don't really know exactly at which layer your exception was created so pros and cons for each of the approaches then there is the other side that might say okay we don't really want to have try catch blocks in the controller we just have a try catch Block in the service and yeah we do all the caching here and then we throw it and if the exception is thrown and we get okay it started from from this action we don't really care the exception is thrown and it would be handled once again either by the exception filter or by my exception handling middleware so also this approach might be okay now this general idea of throwing exception and basically breaking the application flow has a lot of contenders or people that don't think that this is actually a good idea because first of all or one of the most important things is that exceptions or exception handling comes with a cost in terms of performance and by the way I am preparing a video on how or what exactly the cost of exceptions is from a performance perspective so stay tuned to this channel subscribe to this channel hit the notification Bell to be notified whenever new content comes in so that you are notified when the new video will arrive now the idea is that okay we know that it has these downsides that okay we we might have different problems and here comes the second exception handling strategies that is also my preferred way of working with errors or exceptions in my applications is to actually not throw exceptions at all now you would ask how would this even work now the idea is and we can go here back to this application layer and instead of throwing exception and instead of having my services just okay I I would return a post here no let's think about a little bit more conceptually and what I will return from my service is always not a certain entity or a certain collection of entities but what I would return is a service result meaning what is the result of my service or my service method being executed and the result of course could contain some payloads like if we have some some information that we want to return but it could return for instance or it could include some errors or the message of the error that was encountered during the execution of this method so in order to do this what we do here is we'd add a new class here in my service layer and I would call this class service result lot and this class it would be also a generic class for now it would be a service result of T and we'll see exactly why this team might be important now what we want to return or usually as a bare minimum what we want to have in this concept of a service result and by the way if you are using handlers you can name your class handle result or anything similar to that so you can name this idea of result whatever it fits best for you operation result handle result service result it doesn't really matter conceptually is that you kind of like have always a certain object that is the return type of your service calls or of your handle methods or similar to this now the bare minimum that we would need for this to work is here a property of type bull that is error let's call it is error okay so we have a get set what we need if we have an error I would like to have public string and that might be null uh it would be the message of the error and let's maybe call this property directly error message now if you want for instance together if there are several errors or exceptions that happen during the execution of the method you would also maybe like to catch them all and create maybe a list or a collection of strings that represent the message of each of the error that that was encountered but in this case for Simplicity here we will just leave this with a simple string which would contain the error message and last but not least what we'll have here is we'll have this public T and we'll call this payload and this payload property will contain the result in case everything was successful now of course if we have an error this might be also null so let's have it nullable and here I have a typo so I guess one thing for things to work correctly would be to type them appropriately now that we have this class we can go back to our post service and in this case we can actually do a little bit of stuff here now the try cage block remains because the repository could throw us some exception because the repository might use a connection or something that that we don't really directly uh or that we don't own so and we know that they might actually throw exceptions so what I would have here is for instance Service uh result let's call this result and we can even uh new it up so that would be no problem with that uh and of course here would be if I have a service result it would be a service result of post because this method is supposed to return a post is if everything is successful now what we do here is that when we try and everything is okay we actually don't return this but what we will do here is now in this result dot payload we just set the payload to post repository get post by ID and it would be this what we have on the other line uh geoid Dot new guid and we should be good to go with this one and of course in this case we don't really need this line anymore so we can just have it like this cool so this is the results.payload now if we have an exception during Dick's guest post by ID from the repository we would go into this sketch block and what we do in this sketch block well we will not throw anything anymore but instead what we'll be doing here is go to our result and say that is error is equal to true because I have an error here and also on the result I would say that error message and I would say this is equal to the message from the exception it would be like this and then what I will do in the end I will just return result so I would return my service result of course this would also mean that my method signature would have to return a service result of post it would be something like that and now we should be good to go so now I have totally refactored my service method here then I can go over to the controller and of course in this case I don't really need this try catch block anymore so we can just simply delete everything and here we can say of our result equals postservice dot get by ID and yeah that should be actually it I guess we have to provide here a guid new guid but the idea is that yeah in that case we will just reuse the GID from there so jid dot new guid so it's okay let me go then in the post service because in this case we can just use the post ID that we have so that was a slight mistake from my part sorry for that kind of like this happens sometimes cool so we have then refactored this so let's go back to our controller now we have this result and if the result we can simply say if um result of course we have to even format if correctly so if result Dot is error so in that case I would return maybe let's say a bad request but of course here what we would have but I will come to this just in a few seconds otherwise we'll just return okay and the result dot payload so this is actually what will be returning in this case here I would have to return the bed request of course here you could even return internal server error or things similar to that however the idea is that of course based on the error that you might have you might want to expect this and return different type of results like for instance you could return this bad request but you can return internal server error so you can fully customize what you want to return as an action result if you have an error the idea is that I would even maybe go to the base controller or yeah I would create a base controller and have there in that base controller class a method that I would call something like handle error result and if I would have here result this error I will just call that method that method would look into the error may may try to understand the type of the error that we have in based on the type it might return different results so I guess you get the idea but the whole point of this strategy is that we do not throw any errors if we have exceptions we just catch them we add them or aggregate them to the service result object and then we look into the result object and if it is an error okay we generate something that is specific for that error like a bad result or internal server error but if everything is okay we just return the payload in an OK action result which is actually very very fine now the the pros of this approach is that first of all you don't have to throw a lot of exceptions so from a performance perspective this might be a little bit better but on the other side the flow of the execution of my application is actually not broken by exceptions that might happen occasionally now there is one last thing that I would like to say when you have this or when you go for this approach with the service result or a handle result or operation result or whatever you want to call that you would still need to have those either exception filter or exception handling middleware in play is because the application you don't know might still throw some exceptions at some points that you cannot or that you cannot anticipate directly and in that case we still want to have kind of like this Global layer of handling exceptions and returning an appropriately formatted result to the consumers of our API so going for this approach with the service result doesn't mean that we can actually get rid totally of this exception filter or of the exception handling middleware no we should still keep them but from my point of view and this is what why I prefer this strategy or this approach is that the flow of the application kind of like is maintained and from a performance perspective we don't have to really uh well clutter our application and and create maybe problems or performance problems due to exceptions being thrown all the way throughout all the stack of my application or all the layers of my application and that's why I really 10 tends to have a preference for this strategy instead for the other one where we just throw the exceptions everywhere where we can basically throw them or where it makes sense and of course going back to the service result because you might ask this uh actually when we have this error we can still for instance maybe this is something that I forgot we can still use the logger because we want to lock the exceptions that we have in our application so I would say here log error and still I would log maybe the exception message or the entire exception so this depends on your login strategy and unlocking I have an entire playlist so you can go to that playlist and check out the different type of flowing that we can do here and how logging Works in asp.net core how we can use logging providers with our asp.net core applications everything is covered in that logging playlist and I will leave by the way also a link to the playlist in the description of this video if you are interested cool this being said that that's mostly it if you did enjoy this content don't be shy and feel free to share it with your colleagues with your peers on forms or wherever you think that there might be people interested in this content just feel free to share it and I'm sure that they will appreciate that and if you didn't subscribe to this channel already please hit the Subscribe button and also the notification Bell button so that you get notified whenever we have some new content here on this channel uh 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: 3,540
Rating: undefined out of 5
Keywords: .net core, asp.net, asp.net core, net core
Id: Aho4kris_YI
Channel Id: undefined
Length: 18min 19sec (1099 seconds)
Published: Wed Nov 09 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.