BrandGhost

Handle ANY Exception On Routes - ASP NET Core Middleware

How is it that ASP NET Core servers don't crash when there's an unhandled exception on a route thanks to a web request? Surely... they don't have a big try/catch block behind the scenes?! Surprise -- they do. Fortunately for you, we can leverage middleware to hook into that and handle exceptions that bubble up from routes in our own way! In this video, I'll walk through my own use case for wanting to have error-handling middleware and how you can incorporate such a thing in your own ASP NET Core applications.
View Transcript
why is it that when we throw exceptions on asp.net cor rout that it doesn't crash the entire web server how is that possible hi my name is Nick centino and I'm a principal software engineering manager at Microsoft in this video we're going to talk more about exception handling try catches and middleware that we can have an asp.net core so why is it that the server does not crash when we have an exception on a route in asp.net core and that's simply because it would be bad design if the entire server came down because one web request came in and it couldn't be handled properly but what if you wanted to do more with that what if you wanted more control when there were exceptions thrown on your routes and you wanted to be able to do something with that information in this video we're going to walk through error handling middleware in asp.net core and check out what we can do with that if you find this kind of content interested remember to subscribe to the channel and check out that pin comment for my courses on dome train with that said let's jump over to visual studio and check out some middleware on my screen I have the basic weather application that we get set up in Visual Studio when we go create a new asp.net corap but I've gone ahead and started modifying it a little bit for this demonstration what I want to do is set up some of the default Json options and this is just to clean up some of the responses that we're going to be working with so I just wanted to mention it very briefly but I'm going to make sure that when we're writing null values out in Json as responses that we're not going to write those values out to the caller that way we don't have Json properties that are basically the property name set to null we're just going to Omit those completely and then something else I'm doing here and this is going to be a bit of the theme in the example that I'm walking through today is that if we're debugging or we're sort of in this safe environment we may want to make this more readable so in debug mode I'm saying hey I'm going to be a human consuming this information I want to write it indented I don't I don't care if that's like extra you know space or size in the payload I want to be able to read it so I do want it to be indented but you know if you concerned about having more performance or having the smallest amount of payload possible you probably don't want to have to go right IND dented because it's not going to offer any value to the machine that's processing it this is just a little bit of a addition that we're adding on to this example but what we're going to do is walk through a very simple scenario to start with where we have the weather forecast route I've hacked this to Pieces so it's no longer returning a weather forecast we're going to start by returning a value seeing what comes back and then start throwing some exceptions on this route to see what we can do quite simply if I go return this new object from the route we should be able to see a Json response it has value set to 1 2 3 and then something else is not going to show up because it's null that's thanks to the Json options so if I go run this it's not going to be too exciting but this is just the Baseline that we have to work with you can see it's exactly as I said value set to 123 and we don't have that other property now if we go throw an exception on this rout so let's say that we have throw new invalid operation exception something like this right we can put a little message in here that says oh no if we go run this now what should happen is that we see this information come back on the web request but it should not crash the entire server so if I go do this you can see it's loading the page and visual studio already is hitting this exception so if I press F5 this will continue on we get this page coming back right but you'll notice if you look at the top of my screen Visual Studio is still running and that means if I go to this route again we hit the exception again right this is n too exciting or uh you know it's not really that interesting but the point that I'm trying to show you here is that the whole server did not crash and that's a very good thing in this case if you're reflecting on times where people are saying hey you know try catches you can't just have a big try catch around stuff in this particular case there's a really big TR catch behind the scenes making sure that your route is not going to bring down your whole server and to kind of prove a little bit of that I'm throwing an invalid operation exception but if I throw say a new uh file not found exception right totally random example right so we don't have this one anymore we have this one instead again there's not a big list of try catch that has all of the possible exceptions that could be thrown here the server still running if I press F5 it hits this again before we move on this is just a quick reminder that I do have a course on C refactoring available on dome train refactoring is one of the most critical skills that you can learn as a software engineer and this helps you continue to build build upon applications that already exist making sure that they can scale and have extensibility I walk you through a bunch of various techniques and give you some examples that we walk through together to see how we can apply these techniques to refactor the code check out the pin comment and the links in the description to get this course now back to the video the reason that I was putting this video together is that in my own personal development I wanted to make sure that my web request that I was writing had a very consistent way to handle error responses and that means that instead of having that error page that comes up I don't want to have to deal with that because a lot of the time when I'm debugging I'm not seeing the stuff in the browser I'm writing client side code that's calling my web server and I'm getting a Json response back and I want to have debug information so what we're going to do now is introduce the error handling middleware and then we can see how we can format some of that data so in my particular case I have debug information available to me and then I'm going to elaborate on why you may not always want to do that because it is a bit of a security risk so to start things off we're going to add this use exception Handler call onto our app so we can have that right at the beginning here use exception Handler and then we say uh this value coming in here is an i application Builder that's what the value of x is and then we say x run and then we need to give it an error Handler all that I've done is to find an error Handler method below if we have a look at the error Handler method we can see that it needs to meet this particular delegate syntax here so it is going to be a synchronous so needs to return a task we can give it a name that we want to have and then it takes in an HTTP context what I do from there so this is the very basic thing that you need to do but from there because I want to work with the exception information I have to ask the context for the list of features and then I try to get the IE exception Handler path feature this is going to be the feature that tells us what exception was thrown when our route was hit so I pull that error right off of the exception feature here on line 50 and then from there we can do anything we want with it right so from this point on in the video this is where I'm telling you this is how you set it up but you can decide what you want to go do with this information what I'm going to do in my particular case is look at structuring different return values based on the exception types that we have however you may want to do other things in your case I'm going to walk through the rest of this method so you can see how it works we'll run it and then I'll explain why this is helpful compared to trying to do something else across all of your different routes and your application the next part that we see here at the end of this method is that I'm setting a response status code here so I'm setting it to 400 and then I'm writing back a new Json object here so I'm sort of intercepting what we're able to return back to the caller and I made this new API response object type here you can see that I'm passing in a null and then a new piece of information on the end of this which is just going to be an object with a message so to see what that looks like if I go to here we can see that there's a data and error uh parameter that get past into this record and then it has a success property as well this is a perfect scenario for a Nate package called one of because we don't have discriminated unions inside of C but the way that this would work is that we go to return a value and either you get something that has data or you get something that has error so I can't easily go enforce the data and error only being set there's ways that you could always kind of manipulate this and it's a bit clunky to work with the way that I would personally want to do this is use something like one of maybe in the future we'll get this kind of language feature in C but I'm going to gloss over that for now because doing this in this particular way especially with the Json serialization options we saw at the beginning it means that if I don't set one of these we're only going to see the other in the response it does mean that I could go mess this up and I could go put something else right here I could go put a new object of some type so there's nothing stopping me from coding this right now I could go change the API to that uh new type and we could make that en Force but I'm just going to like I said skim over that so we can see how this all works again in your own development you may want to go clean this type of thing up more but my goal is to have a more uniform response type that I can send back especially in the error case so we have this API response object this is going to get written back as Json and now if we go run this we can go see that we'll have a different result that comes back in the browser so we get our exception being thrown when I press f 5 you can see that we get this all broken out so there is an error which is what we would expect in this case it has a message that we can format and then the success property is set to false you don't see the other data or payload property here there's nothing else to look at and the reason that I wanted to be able to do something like this in my own development is again because I'm writing a client API call to hit the server and when a Json response comes back I want to make sure I can understand what the heck is going on and you might say well Nick you can't really tell that from this message and that's exactly right this is a very generic one so before I go into the more specific one I wanted to explain to you the challenge that you end up having if you try to go do this handling not in middleware what I mean by that is if we go take this weather forecast example what I'm going to do is introduce this other code that is going to be for validation and this is a more typical thing I would say that I find that I'm writing so I want to go do some validation you might be using something like fluent validator to go write really easy to understand validation logic and then return that information back to the user what I'm doing here is I'm throwing a brand new type of exception that I've written we'll see this more in a moment but the challenge that I was talking about is that instead of doing this kind of thing and saying well I'm going to go throw this exception remember we're going to pretend that middleware is not there what you would need to be able to do is instead of throwing the exception you would need to do something like wrap this whole thing up in that API response so you'd have to go return new API response and then you would give it the information so we don't have data and then we would have to go pass in this error object how were we supposed to format this right it's inconsistent I should have mentioned too that this object type I probably want to have a more concrete type rather than just object but maybe you want to go do something like this now we have this weird situation that I'm about to demonstrate to you that if we go copy and paste this right so we have another route it's not weather forecast it's do something else now if I have validation errors that I want to send back I need to make sure that I'm formatting this in the exact same way this is a very contrived example because I'm not actually doing the validation properly you can see I'm just saying missing ID for X I'm kind of simulating this Behavior but if you keep having other routes and you keep having other types of validation logic and validation exceptions and you want to return stuff in a consistent way now you keep spreading this logic out further and further and further across your application and it starts to become very messy so the error handling middleware is a great way to work around this I'm going to go ahead and remove this one again and we're going to go back to this basic example here and I'm going to go back to throwing this exception as well so we will throw a new exception here I'm going to throw this exception once again and this way we can go back to having the middleware and seeing how we can handle this consistently what I'm able to do in the middleware is ADD special handling so I can check the error type that's coming in and if it's a validation exception I can go do something more specifically here usually when I'm starting out in my applications my setup like this might start looking something exactly like you see here where I'm doing specific type checking however this is not something that I like to propagate as my application grows this is an example of where I like to do something that is plug-in style and that way I can keep adding different handlers for different exception types and I don't have this big if else I basically have a collection I can walk through to see who can handle this but in this very simple application that would be Overkill we're just going to check the type and we can see that I'm going to do the response status code again is 400 but in this particular case I'm going to write out a more specific error type I do have another ify bug here so if we're thinking through how I might want to be working with this in my own application if I'm calling this from my own client in my devel vment mode I might want to get the stack Trace passed back I might want to know the exception type this is extra information that I might want but we would not want to do this in production the reason that you would not want to do this in production is because if you're passing back stack Trace information or other information that might be a little bit private and now you have people on the outside of your development team that are able to see some of these details that might give them more information about how they can circumvent what's going on in your server if people people really want to get in they'll find ways in but this is just kind of helping them if you're giving them extra information in this case I'm using an if def for if debug but there is a development mode in ASP onet core there's lots of other ways that you can do this type of thing with configurations flighting anything you want I'm just showing you one super quick dirty example here the other thing to mention is our validation exception could be built out more robustly to have information about what validation problems occur and that way instead of just having a really generic message here we could go list out all of the things on the request that came in and what was not valid about that that way we could go right out a ton more detail in this case we're going to go back and check out the route it's going to check if the request is valid or not and if we go step into this down here it's going to return true for valid I'm going to say that it's always false this is where you would have your fluent validation code I'm kind of cheating here if we go run this though it should go throw this validation exception and then what we should have happened is that it's going to go into this error Handler and specifically this part here on line 48 and Beyond so we should get a more detailed error response coming back there's the exception being thrown and as you can see it's kind of spread across my screen here but we do get this API response object coming back error is still set we do have this message populated here this is the exception message specifically so like I said if we built out more uh of a robust validation exception we could go add in extra properties here because it's in debug mode we get these extra two properties populated we get the exception type and we get the stack trace and you might want to add in other details that would help you in debugging again this is important for me in my development because I'm not seeing this directly in a browser I'm seeing this in an HTTP client making a request to a server to get an API response back and I wanted to have extra information like this because that error page that we saw at the beginning is not going to help me in my particular case now to go round out the rest of this video I just want to touch on a couple more points because I did live stream putting this video together and I wanted to make sure that I touched on some things that came up because I think they're important because people were expressing their opinions about them the first thing that I want to mention is that this thing that I'm doing where I'm making this API response type we scroll down a little bit more this thing right here could be very well handled by one of which is a nougat package so I do recommend that if you're trying to build out something like this one of really helps and that way you don't have this weird situation where you're passing in a null and the other type or flipping them around or having to come up with your own version of one of in my own development I do have my own version of that that I've kind of customized my liking but this is going to try to give you that behavior of having one or another type we don't really have that in C sharp as a first class thing in the language the other thing that I wanted to mention is that you'll notice if I go back to the route here I'm not returning that consistently I want my API response in the error situation which is handled by that middleware to return that API response object but I'm kind of cheating and I'm not doing that here so in a future video and a live stream that I will put together I'm going to see how we can go right middleware that's going to take any object that we return back from here and make sure that it's passed back is an API response type so if you're interested in seeing that when it's ready you can go ahead and check that out here thanks and I'll see you next time

Frequently Asked Questions

Why doesn't the entire ASP.NET Core server crash when an exception is thrown on a route?

The server doesn't crash because it's designed to handle exceptions gracefully. If one web request encounters an issue, it shouldn't bring down the entire server. Instead, there's a built-in mechanism that catches these exceptions and allows the server to continue running.

What is error handling middleware in ASP.NET Core, and how can it be used?

Error handling middleware is a way to manage exceptions that occur in your application. By implementing this middleware, I can intercept exceptions thrown on routes and format the response in a consistent manner. This allows me to return structured error information to the client instead of a generic error page.

Why is it important to format error responses consistently in an API?

Consistent error formatting is crucial because it helps clients understand the nature of the error without confusion. When I'm developing client-side code that interacts with my API, having a uniform response structure allows me to handle errors more effectively and ensures that I can provide meaningful feedback to users.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload