Clean Error Handling In .NET

  Рет қаралды 15,634

Amichai Mantinband

Amichai Mantinband

Күн бұрын

Пікірлер: 54
@iantabron
@iantabron 5 ай бұрын
I generally disagree with throwing exceptions in non-exceptional circumstances. However, in this example I more strongly disagree with throwing an exception in a service layer that contains an HTTP response code. You are assuming you will always use your service layer with a web-based API, and tying it to this usage. A service layer should be just that - services. An API layer, such as WebAPI in this case, should have the responsibility of returning the appropriate HTTP response code.
@amantinband
@amantinband 5 ай бұрын
Please note that we’re talking about simple, small to medium applications that are mostly CRUD. I share your opinion for larger, more complex applications. For the smaller apps, personally, I’d choose the higher coupling, higher cohesion approach and refactor if needed
@dimitro.cardellini
@dimitro.cardellini 4 ай бұрын
@@amantinband especially if we are talking about small CRUD application, we should not use http-codes outside of the http-based representation layer
@dimitro.cardellini
@dimitro.cardellini 4 ай бұрын
9:14 Oh! Oh! Oh! Don't do that! ... Don't do that ... Application should be unaware of the representation layer .... So, don't use the http statuses for these ... It is a classic abstraction leacking ... I like your videos! Really like! I'm excited that you mention the Result vs Exception patterns (also known as Error (Code) vs Exception). But, please, don't use the http codes outside of the http-based representation layer.
@dimitro.cardellini
@dimitro.cardellini 4 ай бұрын
The application size is not a criterion to choose between exception throwing and result patterns. If we are talking about small applications, you can choose either one, but not both. If you are writing a large application, you should choose both, but for different reasons. For example, any class from the infrastructure layer should either: - return an error result expressed in domain terms, or - throw an exception expressed in infrastructure terms. The error results pass through all layers with explicit handling. Sometimes, they can cause an exception, indicating an unexpected assumption mismatch (or failed assertion). On the presentation layer the error results must then be translated into messages for the client according to the client interface. Exceptions pass through all layers via automatic propagation and reach the error boundary in the client interface layer. This error boundary is responsible for reporting (logging) the error and sanitizing its content before the error is presented to the client. Using exceptions to model error results leads to unnecessary try ... catch blocks and re-throwing of unhandled exceptions, because typically any method returning an error result could also throw an exception that comes from the underlying layers.
@tchial0
@tchial0 5 ай бұрын
Simple and good analysis of what approach to choose.
@LarryGroot
@LarryGroot 5 ай бұрын
Thank you very much. Maybe Next Video how you would log and which framework you would use.
@amantinband
@amantinband 5 ай бұрын
It’s coming
@krccmsitp2884
@krccmsitp2884 5 ай бұрын
3:37 I concur. In domain-centric, i.e. non-CRUD applications/modules, exceptions don't fit well.
@DerAuskennfuchs
@DerAuskennfuchs 3 ай бұрын
Another idea is to annotate the exception classes with a custom attribute. This could also be evaluated in the GlobalErrorHandler. With this other consumers can ignore the attribute and you don't "clutter" the exception classes with adapter specific values.
@patfre
@patfre 5 ай бұрын
Exception should only ever be used IF AND ONLY IF ITS THE ONLY OPTION. Exceptions are incredibly memory and processing intensive and should be reduced as much as possible so even suggesting to use it just because it’s simpler is one heck of a quick way to make people fail an interview
@amantinband
@amantinband 5 ай бұрын
Sounds like you’ll enjoy this video: Exceptions are evil. This is what I do instead. kzbin.info/www/bejne/aJnMfKx8npagnas
@MrPayTune
@MrPayTune 5 ай бұрын
Sorry if its a silly question but how come did you make a new propperty for the error message, and not use: public class ServiceException(int statusCode, string message): Exception(message: message)?
@pilotboba
@pilotboba 5 ай бұрын
One thing I disagree with is ever returning a 404 on a List (collection) endpoint. I'm not sure why your List asked for a product Id. But a list should return an empty collection if no resources match the predicate.
@amantinband
@amantinband 5 ай бұрын
If it's up to me, I choose 404 for parent resource not found, but both are fine and valid approaches
@pilotboba
@pilotboba 5 ай бұрын
@@amantinband Oh so you are listing some child resources of a product. I guess I could see returning a 404 in the case of the missing product.
@jodainemoore8300
@jodainemoore8300 5 ай бұрын
Great Videos, Please can you do one on Composition and Or with Strategy Pattern, I have been struggling with these for months.
@YopYan
@YopYan 5 ай бұрын
Hello and thank you for this informative video! I have a question regarding the UseGlobalErrorHandling middleware. How can we adapt the exception handling to differentiate the information returned based on whether we are in a development or production environment? Do you have any advice or best practices on this topic? Thank you in advance for your response.
@amantinband
@amantinband 5 ай бұрын
You can register different error handling middleware depending on the environment. For example: if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/error"); }
@saiuan4562
@saiuan4562 5 ай бұрын
Why not just return either the record, or 200 OK with empty list/no record, if it was not found? Is that not okay?
@amantinband
@amantinband 5 ай бұрын
Both approaches are good and valid. Personally, if I get to choose, I return 404 for *parent* resource not found, and 200 ok and empty list for collection not found/empty
@georgebelletty7861
@georgebelletty7861 5 ай бұрын
I do like ErrorOr I use it in all our projects
@petherpettersson6152
@petherpettersson6152 5 ай бұрын
What I can't really buy on the cons of Exceptions is the cost of them, sure, it has some resource cost, but who designs a product to do the bad incorrect stuff all the time? There's supposed to be validation on input on the frontend, the one on backend is just a safeguard, so will have no Exceptions there if the frontend has done it's job, so then the only exceptions coming are the ones where something goes bad during processing?
@amantinband
@amantinband 5 ай бұрын
When using exceptions for flow control, by definition you’re using exceptions for flows that are not exceptional. Depending on the scale and requirements of the app, this can be significant
@DavidSmith-ef4eh
@DavidSmith-ef4eh 5 ай бұрын
How would you translate the error messages on apis with multi language support?
@krccmsitp2884
@krccmsitp2884 5 ай бұрын
How would you do that with exceptions?
@tchial0
@tchial0 5 ай бұрын
I would probably create a service class that returns a message according to the language. And have message templates.
@krccmsitp2884
@krccmsitp2884 5 ай бұрын
@@tchial0 there's no difference in this
@rankarat
@rankarat 5 ай бұрын
Are you also responsible for the client-side development? If so, consider creating a shared project to house a mapping system and resource files. The API will return a code indicating a problem, which will act as a key in the resource file. This approach will facilitate easy management of multiple languages.
@tchial0
@tchial0 5 ай бұрын
@@krccmsitp2884 ​ Let's say (or code, lol): "var errorMessage = cultureService.GetErrorMessageById(errorMessageId, param1, ...)"
@Tony-dp1rl
@Tony-dp1rl 5 ай бұрын
Using exceptions for logic branches that you KNOW how to handle without exceptions, such as by returning a suitable response, is not a good idea. It creates a different user experience in most cases, and it creates far more overhead in terms of error logging, monitoring, unit testing, etc. Nothing worse than a unit test, or functional/integration test, that has to say "did this throw an exception?" .. "yes, test passed" ... just stupid :)
@amantinband
@amantinband 5 ай бұрын
I generally agree and have videos on the channel relaying this exact point. The truth is in the middle. Both approaches have great benefits and drawbacks. I’m demonstrating what I would personally use for a small-medium, mostly CRUD app when looking to get things up and running as fast as possible.
@harrisonwell1719
@harrisonwell1719 5 ай бұрын
I found ErrorOr Adds a lot of unnecessary code
@amantinband
@amantinband 5 ай бұрын
That's the main drawback of being explicit
@parlor3115
@parlor3115 5 ай бұрын
Not really, if you look closely, it's as much code as the exception approach. But I prefer this approach because it's more readable (the return type tells you everything about the method)
@petherpettersson6152
@petherpettersson6152 5 ай бұрын
@@parlor3115 Not really, since in every endpoint you will need to add code to handle if you should return the result, or the error if there is anything. Whilst a global exception handler is just that, global, so you do not have to do anything special for it to work. So requiring 5 to 10 extra rows of code is not as much code as no extra rows. *Edit* And then we have the extra try+catch code on top of that...
@parlor3115
@parlor3115 5 ай бұрын
@peth You only handle at the level you want to access the success data in and you have to handle either the exception (try catch) or the return. Otherwise, you'll just let the return propagate as is. And in case of generic and expected errors (validation, record not found, ...), then you'll return those at the last step (at the action method), where an after middleware is dispatched that will check the response and handle it accordingly just like a global error handler. With this, you'll be right the same amount of code while saving on performance.
@stephenyork7318
@stephenyork7318 Ай бұрын
So is this all t here is to this series? Seems like there's a lot more to cover.
@from.heart4
@from.heart4 3 ай бұрын
Using try catch is out dated way?
@MahmoudSaed98
@MahmoudSaed98 5 ай бұрын
source code please
@amantinband
@amantinband 5 ай бұрын
Hey Mahmoud, the source code is available for patrons and members. The description has all the relevant links
@jimread2354
@jimread2354 5 ай бұрын
That's funny, I completely and fundamentally disagree. IMO, if you have a simple application, you can use return codes, but complex applications with lots of shared code and deep stacks of function calls benefit enormously from Exceptions. Exceptions simplify error handling and code readability MASSIVELY over returning error codes. Exceptions were a response to return codes' lack of scalability because return codes require that EVERY time a function is called, whatever calls it has to have logic to handle the error condition right there. Exceptions allow you to simply pass the error up the chain until something that cares or knows what to do will actually handle it. Further, exception handling is done outside the general flow of logic so someone reading the code can actually understand what is 'supposed' to be happening and there's no chance that anything UP the stack is going to continue executing in a faulty state. On top of that, IMO, it's a TERRIBLE idea to have multiple outputs from a given function. It's bad enough to have the possibility of null or an object, but to then throw in the possibility of a third type to check and unpack the result of every function call? How is that scalable? It's a rat's nest of error handling! That's the beauty of an 'out' parameter is you can have the function return a specific type of result and then use the object if it's valid or else handle the case of it not being valid. The other great power of an Exception is that you can add context as the stack unwinds at the levels where it makes sense. Return codes can only change the context and you might lose vital information about what happened in the error situation. You're basically left with the choice of a user being told that there was a divide by zero error OR that the review didn't get added with no information about WHY. For instance, in a complex application a UI action will likely start a cascade of function calls splitting off into different directions to handle the different subtasks associated with with whatever the user just asked for. An exception deep in the bowels of that can say there was a divide by zero error, but then that can propagate to a failure to generate a star rating value which can then be caught closer to the UI level and told that the review couldn't be added. When you're building the message for the user and the message for the log, you'll have different info you can use to generate useful information in both contexts right at your fingertips without generating multiple log entries that you have to then piece together. IMO, you should throw Exceptions if the code you're in can't handle the current logical situation. For instance, adding a review to a product that doesn't exist. But if the code you're in CAN handle the situation, like perhaps you're adding an item to a list of items that share some property, but nothing has been added with that particular property yet, you should create the list for those items--no need for an exception or return code. Not using exceptions and relying on return codes is going backwards. And returning multiple data types from a function has always been a really bad idea from a readability and usability standpoint. The only real use case for return codes is in headless programs or highly performant libraries; but you better be sure the tradeoff in readability and debuggability is worth it.
@amantinband
@amantinband 5 ай бұрын
Thanks for taking the time to share your thought and experience. My opinion around this topic is shaped from suffering bad implementations of exceptions for flow control in numerous large complex projects within Microsoft. I elaborate my opinion in more detail in this video: kzbin.info/www/bejne/aJnMfKx8npagnas In any case, drawbacks and benefits to both approaches. They can both be implemented well and horrible. Plus, personal taste etc'.
@dimitryselin4225
@dimitryselin4225 5 ай бұрын
@@amantinband I want to add some text to this big comment. In big applications we ussualy work with diffrent nuget-packages, call low-level code of c/c++ dll from c#, send http-queries and so on. Often all this stuff generate exceptions (and some authors of libraries say that exception handling is the normal flow of using their packages). So in that case you need handle both: error codes and standard c# exceptions. These approaches lead to complicated error handling, lots of exception hadling code and of course bugs. And last but not least - your entire architecture will strong link with lib. (I hope you know that authors can change package license, stop maintenance and even do what happened to the package "moq") P.S. This is not about you Amantin))
Global Error Handling in .NET 8 - My Favorite Approach
14:18
Amichai Mantinband
Рет қаралды 15 М.
Stop returning custom error responses from your API. Do this instead.
12:07
Amichai Mantinband
Рет қаралды 86 М.
So Cute 🥰 who is better?
00:15
dednahype
Рет қаралды 19 МЛН
Сестра обхитрила!
00:17
Victoria Portfolio
Рет қаралды 958 М.
Tuna 🍣 ​⁠@patrickzeinali ​⁠@ChefRush
00:48
albert_cancook
Рет қаралды 148 МЛН
Your REST API Errors Are Wrong. Problem Details Will Fix This
16:14
Milan Jovanović
Рет қаралды 12 М.
7 Design Patterns EVERY Developer Should Know
23:09
ForrestKnight
Рет қаралды 196 М.
Top 8 Best Practices for API Design #api #bestpractices #apidevelopment
15:23
SWE with Vivek Bharatha
Рет қаралды 8 М.
Elegant Global Error Handling Using Middleware In ASP.NET Core
13:58
Milan Jovanović
Рет қаралды 91 М.
Stop Using FirstOrDefault in .NET! | Code Cop #021
12:54
Nick Chapsas
Рет қаралды 99 М.
5 deadly Rust anti-patterns to avoid
13:25
Let's Get Rusty
Рет қаралды 38 М.
Getting Started with Dapper in .NET
11:29
Amichai Mantinband
Рет қаралды 14 М.
Brutally honest advice for new .NET Web Developers
7:19
Ed Andersen
Рет қаралды 301 М.
JavaScript Error handling in 9 minutes! ⚠
9:03
Bro Code
Рет қаралды 19 М.
Exceptions are evil. This is what I do instead.
24:41
Amichai Mantinband
Рет қаралды 22 М.