The Right Way To Return API Errors in .NET

  Рет қаралды 65,589

Nick Chapsas

Nick Chapsas

Күн бұрын

Пікірлер: 223
@nguyen_tim
@nguyen_tim Ай бұрын
Hey man, I’m not a C# dev but I just wanted to say that you make some really good content, and I really respect your hustle. Keep up the good work!!
@pgoings
@pgoings Ай бұрын
I am a C# dev, and his content is invaluable!
@ClayBrooks1010
@ClayBrooks1010 Ай бұрын
Nick Chapsas alt account confirmed
@GackFinder
@GackFinder Ай бұрын
Correction, this does not adhere to the new RFC 9457. It's the same old RFC 7807 implementation that we've had for years, as can be seen in 7:46.
@WillsAGeek
@WillsAGeek Ай бұрын
Also as of this comment, RFC-9457's status is still 'PROPOSED STANDARD'. So currently 7807 is still the standing standard.
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
RFC 9457 is that type can use a shared registry (most were already doing this), that validation errors has an errors array with description and they tried to be more clear. It's just a continuation of RFC 7807.
@plainandstripes
@plainandstripes Ай бұрын
As always, many thanks Nick! 😊
@a__random__person
@a__random__person Ай бұрын
been doing it this way for 15 years, one thing to add, which may be obvious, but you'll need to handle various kinds of exceptions or add a "severity"property if you want to return different kidns of status codes so that an unexpected exception doesn't get returned as a bad request for example. Though of course, I don't really throw exceptions for validation, which is handled separately,
@adedoyin-emmanuel-adeniyi
@adedoyin-emmanuel-adeniyi Ай бұрын
How about creating an API Response class that has 3 different methods overload. Each of the method overloads takes a code, a message string and then a data object. Then in your controller, you can return the normal BadRequest and then use the Response class in it. Say return BadRequest(new Response(400, "custom validation error")); In a 200 response return Ok(new Response(200, "Something fetched successfully", data)); This was you can use the Response class for 200, 400, 404 and 500 responses, That way your API Response remains concise and consistent.
@vonn9737
@vonn9737 Ай бұрын
If you've separated your application layer from your presentation layer (API), then the validation will likely happen in the application layer, and that will not know anything about HttpResponses. So you're back to the same problem. How does your application layer return an error? Is that via an Exception, or some other tuple/result class. If you're in your controller anyway, you can return whenever you like, using whatever response class you like.
@Dustyy01
@Dustyy01 Ай бұрын
You should use a separate class for each response type and it's okay if they're different or the same. You can repy on the OpenApi schema to know what the response looks like on the client. Error responses should be standardized though for your API, preferably using ProblemDetails
@adedoyin-emmanuel-adeniyi
@adedoyin-emmanuel-adeniyi Ай бұрын
@@Dustyy01 yeah this too.
@shadowkras
@shadowkras Ай бұрын
Wait. Not many videos ago we were complaining about throwing exceptions and how expensive they were. What changed?
@nitrovent
@nitrovent 12 күн бұрын
If the exception really is an exception, i.e. there is something wrong, it is not thrown often and therefore should not have a great impact in most use-cases. What should be avoided is using exceptions for control flow. E.g. if you had a cache that would throw a NotFoundException if you pass a non-existent key and you would wrap that in try-catch and go to the DB in the catch or something like that
@paulguk
@paulguk Ай бұрын
Throwing exceptions for validation errors? Big ugh. We need that code cop guy to review this 😆
@nickchapsas
@nickchapsas Ай бұрын
Like I said, I'm against it 100% but you know how it is. People still use it so I thought I'd show it
@alfredosevero80
@alfredosevero80 Ай бұрын
​Possible new part 2 showing a better way to do it without throwing exception ? Just an idea 💡
@SuperLabeled
@SuperLabeled Ай бұрын
Your operation can't continue because a business rule is not met, how is that not exceptional to so many people?
@Countryen
@Countryen Ай бұрын
​@@SuperLabeledTo most (including me) it's a violation of a defined requirement, not an unexpected exception. It's also easier to test imo.
@promant6458
@promant6458 Ай бұрын
@@SuperLabeled Exceptions should represent an unexpected error. Bad requests are part of normal app behaviour - not at all unexpected, thus not quite "exceptional". At least that's how I see it.
@BernhardMillauer
@BernhardMillauer Ай бұрын
Hey Nick. Please use another capturing phrase for your thumbnails. "People still get this wrong" is just pure clickbait and doesn't help deciding if the high quality content you produce is worth watching. Well, you might argue that the video caption "The Right Way to Return API Errors in .NET" is the second source of information, yet the caption is not shown at the end of a video showing the suggestion for the next video to play. You're better than these clickbaits, aren't you? Thanks for listening.
@Thial92
@Thial92 Ай бұрын
I personally use a custom result object which can either be returned as a success or a failure. When it's a failure I can specify an error code, a message, and an http status code. Then the caller of the method checks if the result is a failure and if yes the caller also returns a failure and passes the original failed result higher. This results in errors bubbling up all the way to the controller where I have the full call stack thanks to the caller attributes which I can now log and I can also convert the result into a DTO which the API will return. It's ultra fast and no exceptions are necessary but it requires you to follow a very specific coding pattern.
@bluecup25
@bluecup25 Ай бұрын
Homie went from "we just launched a brand new course" to "we just launched 23 new courses"
@SpaceTrump
@SpaceTrump Ай бұрын
I wrote this 10 years ago as a middleware... Error handling with exceptions is nice but its the easy way out.
@aliengarden
@aliengarden Ай бұрын
Easy way out sounds good. Is the harder way out better?
@SpaceTrump
@SpaceTrump Ай бұрын
@aliengarden more customizable, and exceptions tend to be memory and flops heavy.
@Ar6yZuK
@Ar6yZuK Ай бұрын
We can throw ProblemException from switch expression without equality checking
@aspirio777
@aspirio777 Ай бұрын
Somebody should send your video to SAP
@patxy01
@patxy01 Ай бұрын
Don't go too fast, they're still busy with s4hana migration
@persehlin4379
@persehlin4379 Ай бұрын
242 / 5 000 Thanks for showing this, including the exception part. Very useful! Although I am personally against exceptions when the problem can be foreseen, it is not always me who decides. If my client's strategy is to use exceptions, then...
@Suv3g00
@Suv3g00 Ай бұрын
What is the standard way to handle standard ProblemDetails on another API side? Like I call your example API via another API with HttpClient because the result can be the expected object or the ProblemDetails. Is there a good and standard way to do this?
@dylan8463
@dylan8463 Ай бұрын
A ProblemDetails response should also set the Content-Type header to "application/problem+json" so you'll know response is a problem details response.
@Suv3g00
@Suv3g00 Ай бұрын
​@@dylan8463 Thank you for the answer. I am more interested in the following part. For example, if I use Refit or just the base HttpClient, what should be the return type? Should it be Result, and should I create the result based on the header?
@dylan8463
@dylan8463 Ай бұрын
@@Suv3g00 Ah sorry I misinterpreted your question. Personally in a Blazor project I made my own EnsureSuccessStatusCode extension method that parses the problem details response and throws a custom problem details exception, when the response is not 2xx. You could do something similar with the Results pattern too.
@mightygingercles6481
@mightygingercles6481 Ай бұрын
Are there worlds that exist where setting a problem type parameter is going to be different from the status code parameter? I know this was a very bare bones example, but I'm just having a hard time not cringing at setting two properties/parameters to what amounts to the same value in different formats (enum vs string). That all being said, this was very eye-opening on a few different fronts and I (don't) look forward refactoring some (all) of our company's apis xD
@barebox5718
@barebox5718 22 күн бұрын
The title and detail are in my case templated, localized strings that contain specific details to this occurrence of the error that is read by a human, while the type is a machine readable type for the error as it relates to my application, docs specify it should be an URI-like thing, like one type here is "employee/update/errors/inactive-department"
@Iingvarka
@Iingvarka Ай бұрын
It's remind me Salesforce where it returns 200 on everything and inside the response you've got 400
@martink.7497
@martink.7497 Ай бұрын
I have a better (dumb) question - how do you use those trace IDs? Everywhere, you can find what they are, what they are used for, and how to add them somewhere, but not how do you use them in debug. Based on that magic number, how do you find where the error occurred in the code?
@vifvrTtb0vmFtbyrM_Q
@vifvrTtb0vmFtbyrM_Q Ай бұрын
TraceId is used to track the flow of requests through multiple services, not for debugging individual application code.
@Kwpolska
@Kwpolska Ай бұрын
They are used to follow the specific request in logs. The exception and stack trace are in your logs, alongside the trace ID.
@martink.7497
@martink.7497 Ай бұрын
@@Kwpolska So, in other words, you still need a log with some meaningful text, to see what happened. In that case, why not to use GUID/UUID? What is so special about TraceID if you need to "pair" it with a log?
@Kwpolska
@Kwpolska Ай бұрын
@@martink.7497 Why invent your own ID if there's already TraceID? Plus, it is passed in HTTP request headers, so that you can correlate requests made from one service to the other.
@jesslilly5079
@jesslilly5079 15 күн бұрын
Thank you! Are there cool ways to consume and deserialize problem details in consuming applications?
@shakeuk
@shakeuk Ай бұрын
If I recall at least ast far back as net7 you would get with if you used standard controllers and the API controller attributes and model state for bad requests and you could return a validation problem manually if you wish (in combination with model state)
@MrYosef92
@MrYosef92 21 күн бұрын
Throwing exception for validation in windows server and iis this is will consider as an error in event viewer and for the application pool which is running your application its contain settings for limited number of error if it’s reached this number the application pool will stop, your approach for handing error is perfect but don’t throw exception for validation.
@paulmdevenney
@paulmdevenney Ай бұрын
cool. How might you pass a domain specific error code as an additional property here? (to avoid leaking internal / api type text messages up to the UI)
@happy_burger
@happy_burger Ай бұрын
The easiest way would probably be to use the Extensions dictionary on the ProblemDetails type and put it there (get the code from your domain exception or whatever you app has for this)
@jcmoore2013
@jcmoore2013 Ай бұрын
You Could set the Detail in problem details. If want more specific then like Nick did at 5:03, you could add a property using Extensions. For Example I add an array of error strings or a dictionary of error code string, description string. I generally just pass the domain error. So using ErrorOr I set the error code and error description, map that to a dictionary
@oussama7132
@oussama7132 Ай бұрын
I use a static class with an enum for error codes like USER_NOT_FOUND then use a (frozen) dictionary for error descriptions, one for each language. this class is in a shared project that the client and server use I'm gonna watch the video and see if there's a better way to do this.
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
If it's used more than once, usually standardize it in a Dto, extend problem details with custom error message/codes set. If UI needs a custom error message, that's on them, they can use status code and title, and ignore the message (did this for e.g. translation stuff). Most of the time your message text is the same in back-end and front-end though, since validation error will just be "Name is required" or something like that.
@mindcore1
@mindcore1 Ай бұрын
@nickchapsas when you add the requestId and traceId to the ProblemDetails, did you accidently flip the keys, or am I missing something?
@JollyGiant19
@JollyGiant19 Ай бұрын
I think he did swap them accidentally
@chadox71
@chadox71 Ай бұрын
I'm really curious to know how you validate a request using functionnal programming and monads
@MartinLiversage
@MartinLiversage Ай бұрын
You need a monadic type with a succes and an error value often called an 'Either' (in C# another popular name is 'Result'). You then build a monadic pipeline where the input is the request and the output the response. First step is typically to transform the request into a valid request. You then continue with more transformations until you have the response. Notice that the success type can change at each transformation. However, the error type is always the same. In this context the error type can be a problem details or something that can be converted into a problem details. The validation method would take the request as the input and return either a valid request or a problem details (wrapped into the monad). Each subsequent transformation takes the succes type of the previous step as the input and produces a new success type for the next step. By the wonders of the bind operator you can then build a succinct data transformation pipeline using monads. At the end of the pipeline you match the value of the monad into perhaps a 200 OK payload or a problem details with varying HTTP status. Notice that validation often consists of many smaller steps that lends itself to be implemented using monads and doing that gives you nicely composable validation rules. Rules like "string is not empty" and "integer is positive" that return an 'Either' can be composed into more complex rules using the bind operator. Unfortunately, you might try this approach together with async methods and run into problems and that's because 'Task' also is a monad. Nested monads can be troublesome but there are ways to deal with that. It just require a bit more work but the end result can still be great.
@artemromanenia6088
@artemromanenia6088 Ай бұрын
@@MartinLiversage What is a bind operator in C#? Is it related to linq's SelectMany? Also, it would be terrific if you can point to a repo that illustrates this approach.
@CarrigansGuitarClub
@CarrigansGuitarClub Ай бұрын
Best place is to use it in your global error API handling middleware class
@szeroki
@szeroki Ай бұрын
Warsaw ❤ hello from Poland 🎉
@dziarskihenk8798
@dziarskihenk8798 Ай бұрын
Poland mentioned, Polska gurom!!!! Jokes aside, keep up great work
@EffektUpInHere
@EffektUpInHere Ай бұрын
Hi Nick, funnily enough, today I got a issue assigned that has is basically "figure out a way to add generic error results to API". How would you go about following this standard, if the API is also a backend for a SPA that needs some kind of errorCode or unique, to translate the real message to a users preferred language?
@alanschmitt9865
@alanschmitt9865 Ай бұрын
I literally just yesterday opened a PR matching this pattern fuck yeah Well I did some things different but still
@mindcore1
@mindcore1 Ай бұрын
Same here, ironically enough
@winchester2581
@winchester2581 Ай бұрын
Returning 200 OK with { errors: [///] } is the OG way
@erynmacdonald
@erynmacdonald Ай бұрын
Go wash your mouth out with SOAP 😊
@T___Brown
@T___Brown Ай бұрын
Agreed otherwise your force the integrator to handle multiple paths and parsing. Auth, validation, errors, and actual result
@dylan8463
@dylan8463 Ай бұрын
eeewww I hate APIs that do this. It's the worse
@T___Brown
@T___Brown Ай бұрын
@@dylan8463 you probably dont handle all the possibilities in the ones you love
@bluecup25
@bluecup25 Ай бұрын
Unironically, yes. This standard basically adds nothing useful.
@davidelliott4203
@davidelliott4203 Ай бұрын
I basically do the same thing but have added an upfront check of the data model so I don't get into the API for basic validation errors through a service behavior. public static class Behaviors { public static void Register(IServiceCollection services) { services.Configure(options => { options.InvalidModelStateResponseFactory = context => { var badRequest = BadRequestProblem.Create(context.ModelState); return new BadRequestObjectResult(badRequest); }; }); } }
@solidid9368
@solidid9368 Ай бұрын
I personally dont like the idea to use exceptions (and throw them) for validation handling and other control flows. Thats not the idea of exceptions and a mis-usage in my point of view.
@huszaristvan8246
@huszaristvan8246 Ай бұрын
God forbid explaining why do you think that and what better alternative you have.
@turcanuioangeorge4750
@turcanuioangeorge4750 Ай бұрын
I wonder how many got trigger when you threw the Exception instead of returning it with a Result.
@dimitrislaliotis504
@dimitrislaliotis504 Ай бұрын
I was looking for something like this in the comments, isn't it bad practice to throw exceptions instead of returning something? Even Nick had mentioned it in an older video that it is.
@vonn9737
@vonn9737 Ай бұрын
@@dimitrislaliotis504 It's opinion, not bad practice.
@dimitrislaliotis504
@dimitrislaliotis504 Ай бұрын
@vonn9737 some say it's performance hit also
@vonn9737
@vonn9737 Ай бұрын
@@dimitrislaliotis504 Yes. I think Nick did a video on it, and found throwing exceptions were about 3 times slower than error handling without exceptions. But that doesn't make it bad practice, it's just a design consideration.
@turcanuioangeorge4750
@turcanuioangeorge4750 Ай бұрын
It comes down to how and where you use it. IF you throw exceptions for everything then yes, it's bad practice. IF you mange most of your error with results and have some corner cases/global handler with exceptions it shouldn't have a big impact.
@8660holm
@8660holm Ай бұрын
Hey man, great video! Went straight in a implemented in my side project - great! But i have one problem.. when using typedresults to generate a openapi spec with swagger, the documentation says nothing about a possible code 401. Is there someway to generate a nice open api spec with the TypedResults.Problem or TypedResults.ValidationProblem?
@patrykklimas4398
@patrykklimas4398 Ай бұрын
Is there any way to add request id to not catched exceptions?
@JtendraShahani
@JtendraShahani 14 күн бұрын
Hello Nick. Really liked the video. Where can I find the source code?
@ablues15
@ablues15 24 күн бұрын
ProblemException should not expose the Message property since it hides the property from the base.
@davidmontilla6466
@davidmontilla6466 Ай бұрын
this is great, follow every video you release, I want to buy the unit test course that you have, I'm having a lot of questions on how to create good unit test and correct way to do it, but not sure if it will help me to understand how to create them will all dependencies or scenarios that methods have, what can you recommend me ?
@ВкидимирПодгубенский
@ВкидимирПодгубенский Ай бұрын
It should be mentioned in REST API course
@nickchapsas
@nickchapsas Ай бұрын
It will on the update
@Vantian58
@Vantian58 Ай бұрын
Hi Nik, how to return exact same format from Model Validation?
@marsking
@marsking Ай бұрын
What are the uses of requestId and traceId?
@lmoelleb
@lmoelleb Ай бұрын
Logging correlation. If you have multiple systems calling each other you can follow the entire flow. Works best if you use something more than just text files for logging, but even in a text file it is better than nothing.
@zimpoooooo
@zimpoooooo Ай бұрын
This seems like a slightly worse version of doing try/catch in your own exception middleware. I really like to see what is going on instead of adding options and services that do their thing in the shadows.
@СергейИванченков-ДляСвоих
@СергейИванченков-ДляСвоих Ай бұрын
Awesome!
@sebastianbusek2087
@sebastianbusek2087 25 күн бұрын
Hey, does anyone have the link for code samples?
@hopkientran2534
@hopkientran2534 Ай бұрын
I have a problem when using rider on windows, that is rider uses too much ram, do you have any way to fix it?
@geraldmaale
@geraldmaale Ай бұрын
It's even more terrible on Linux, especially with the watcher stuff
@hopkientran2534
@hopkientran2534 Ай бұрын
@@geraldmaale that's terrible
@geraldmaale
@geraldmaale Ай бұрын
@hopkientran2534 yh, so I stick with VS Code as my possible (Linux and Windows) until I need some heavy refactoring to do. VS 2022 has also caught up a bit 😊
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
Define too much RAM usage. Is it causing actual out of memory usage issues for other processes? Lots of programs ask for more RAM than they need and will release it when the system requests it, this avoid fragmentation issues and means you get more efficient GC. There's a toggle for "show memory indicator", you can see use vs allocated, e.g. I am using 1.7GB/3.4GB (+1GB for back-end bit on top), you can lower this via "change memory settings", but 4GB is really not much for heap. If you have
@sirus49
@sirus49 Ай бұрын
the right way is always subjective
@sunclausewitz2707
@sunclausewitz2707 Ай бұрын
What if you don't want to help a malicious actor by returning correct response for every request?
@victor1882
@victor1882 Ай бұрын
then you're just hurting whoever is using the API, and they'll hunt and find you
@gileee
@gileee Ай бұрын
Malicious actors aren't deterred by that. Only clients.
@davidyates8154
@davidyates8154 Ай бұрын
If you want to return more detail while developing locally and then restrict it once deployed to your server, you could inject IHostEnvironment and determine your environment and the level of detail you want to return. I would also suggest injecting ILogger and logging the exception so that once deployed, you can find the problem and the larger detail in your logs.
@davidyates8154
@davidyates8154 Ай бұрын
You also conditionally compile it with compiler directives. DEVs build the debug version that gives them more info and server build the prod version without the details.
@francispion2353
@francispion2353 8 күн бұрын
Remember, there's no security in obscurity. Give just enough information in the details to help a client fix the error on his side (or help you debug the error), but not too many to help attackers.
@purdysanchez
@purdysanchez Ай бұрын
It's been a minute since I did a .NET web api, but there's a much simpler way to map exceptions to status codes globally with way less code. I'm not sure why they're adding worse patterns when a better way has been available for 8+ years.
@Crown0815
@Crown0815 Ай бұрын
how is the performance? throwing exceptions is possible not the fastest way to get a response.
@aristondarmayuda1451
@aristondarmayuda1451 Ай бұрын
if the concept of exception still same, exception usually faster but it has cost. exception basically an interrupt, it's order to system/thread pool "stop whatever you are doing, we have problem!". so throw exception for validation, it should faster but it's like saying "all of you, stop what you are doing, this guy send wrong character", it's unnecessary cost to the thread. throwing exception should be critical issue, such attempt access violation, etc.
@MrSchmell
@MrSchmell Ай бұрын
It does not matter. You optimize the happy path, not the other way around. Unless you actually expect to be bombarded with a lot of bad requests. But then the question is: why is that?
@gileee
@gileee Ай бұрын
In my testing I had about 5-20ms to return a Result, same request with exceptions took about 80ms on average and on initial throw it went up to 200ms+... for a simple NotFound response.
@thanzeeljalaldeen
@thanzeeljalaldeen Ай бұрын
should not we be throwing exceptions nick? you always mention in some videos not to throw exceptions but to return a response result. And now you are throwing an exception. i am confused
@mealloc
@mealloc 19 күн бұрын
I’d just use the first approach. The global handling seems to be against the spirit of minimal api. Your error type and error code won’t be statistically validated for you and they won’t be part of your OpenAI spec unless I’m mistaken. The first approach is clearer and objectively better.
@heshamelsheltawy9039
@heshamelsheltawy9039 Ай бұрын
Is this work with controllers
@ablues15
@ablues15 24 күн бұрын
A good reason to not use Result
@Daniel15au
@Daniel15au Ай бұрын
Validation errors should return HTTP 4xx errors, not 5xx. 4xx means an error caused by the client whereas 5xx means an error caused by the server. Invalid input from the client is always considered as an error that was caused by the client.
@teamdroid9834
@teamdroid9834 Ай бұрын
this applies to minimalapis but i wonder if controller based guys als have the same concept behind
@mindcore1
@mindcore1 Ай бұрын
They do... as a matter of fact, the ControllerBase has a PropertyDetailsFactory property which you can use by creating a custom implementation, registering it, and then use the built-in Problem method to invoke it.
Ай бұрын
Exception handler is how Laravel does it as well. But then datadog sees tons of errors en exceptions happenings in code which are just false poisitives :(
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
Datadog should only be handling uncaught exceptions, so stuff like user id doesn't exist on login are common ones and you'd use a key not found exception and should end up being grouped (be it by endpoint or type or both). For us, entire company moved off of datadog as just too expensive for what it is if have entire dev and devops team already to manage open telemetry and grafana dashboards (and can reuse most templates). If you're C#, often hosted on Azure, Azure Insights is also great.
@dangg44
@dangg44 Ай бұрын
Can be done in multi language?
@nickchapsas
@nickchapsas Ай бұрын
Yeah every language should implement it in some way
@deeplerg7913
@deeplerg7913 Ай бұрын
@@nickchapsas I think they meant different human languages, not programming languages
@codewithfrenchy
@codewithfrenchy Ай бұрын
no link for the code this time?
@parsalotfy
@parsalotfy Ай бұрын
Make a video about garnet
@matteobarbieri2989
@matteobarbieri2989 Ай бұрын
With your example you send 400 even if the correct code it's different (e.g. 401/403/409)
@Sergio_Loureiro
@Sergio_Loureiro Ай бұрын
"I identify as a problem".
@promant6458
@promant6458 Ай бұрын
What if my API uses snake case instead of camel case? Should the problem details also be in snake case (which would be against the standard, I guess?), or leave them as camel case, making it a massive inconsistency?
@promant6458
@promant6458 Ай бұрын
Ok, all properties included in the standard use one-word-only names (e.g. 'status' instead of 'status_code'), so I guess they did think about this beforehand!
@vekzdran
@vekzdran Ай бұрын
Hahaha I see what you did, taunting poor commenters with this approach :)))
@davidmata3104
@davidmata3104 25 күн бұрын
@nick You are contradicting yourself. In one video, you mention that exceptions are bad and expensive. Additionally, exceptions and data validations are not the same thing. Treating validations like exceptions is similar to using goto statements which are considered bad practice because they can make code difficult to read, maintain, and reason about by creating uncontrolled jumps in the flow of execution. A better approach is to use a Result type, which allows for explicit handling of success and failure cases without the drawbacks of exceptions or goto statements.
@ruslanfreepoint
@ruslanfreepoint Ай бұрын
Very good content but here is my 20 cents! You should throw exceptions only when you don't handle it in the code logic (something unexpected). Also this can lead to a performance issues as throwing exceptions is expensive process. When you validate you should return the object not throw and exception.
@Iingvarka
@Iingvarka Ай бұрын
Nick why you should use Result pattern for validation errors also Nick throw exception on validation
@oussama7132
@oussama7132 Ай бұрын
http code: 200 response: {success:false, errorCode:401,description:unauthorized}
@winchester2581
@winchester2581 Ай бұрын
This is the coolest way possible
@Sgro81
@Sgro81 Ай бұрын
I've ran in this kind of shit so many times, I'm impressed how much effort is taken to develop this kind of shit
@richard-t7c5o
@richard-t7c5o Ай бұрын
This in fact makes a lot of sense. It is not perse REST but more like RPC. I use it in all my services. When I get a 404, I know that it is infrastructure related, VPN issue, Firewall issue, Company policy, Azure Gateway issue or whathever, but has nothing to do with my service. I use UseCase driven development so my Usecase (like vertical slices) give a Response.success(response object), or Response.error(ERRORS.USER_NOT_FOUND....) which is not aware of infrastructure, so I can use that response to map it to HTTP responses or back to my CLI programm for example.
@Sgro81
@Sgro81 Ай бұрын
@@richard-t7c5o I'm very glad I'm not a consumer of your services then
@WalderFrey
@WalderFrey Ай бұрын
Seems like a long-winded way to return a 400 status code. Who's reading the message - human or machine?
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
Both, you code to check against the status code if error or not, title to map error if custom message, and if not pass the rest back/up the chain through systems and a human can read it at the end to know what the issue is. Just a 400 is going to be annoying, and lots did that because every error response was different, so couldn't easily map it, this solves that.
@LinkingWorlds
@LinkingWorlds Ай бұрын
As always Microsoft try to enforce some habits, i don't like that and this one, too much informations we don't need, a personnal returned envelope object, will be nearer my needs. Of course, you are one partner of Microsoft, they give you you give them.
@kyreehenry9202
@kyreehenry9202 Ай бұрын
Result pattern makes your code tedious, Exceptions works better and infact Microsoft uses a lot on the framework you're coding on
@GeorgeGeorge-u5k
@GeorgeGeorge-u5k Ай бұрын
Sad to see unopinionated devs in 2024 and a mindset of "if you dont use problemdetails,results pattern,clean architecture etc you are bad dev". While CleanArchitecture is something useful the problemdetails is totally useless thing that restricts you how to expose your endpoint results. An API should have its own response contract. Most of the times you will have to expose additional fields in response that this standarized way is just restricting you for no reason. Sad to see blindly follow things and make our life harder.
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
You don't seem to know what Problem details are then. They're just a standardized format so any system can at least read status and title. It's got extension members as part of the spec (rfc7807 3.2 "Extension Members"), usually add extra stuff there like traceId. The new RFC just adds "type" to a common registry schema, which most organizations were already doing to their own registry. I have yet to find a use-case where ProblemDetails or ValidationProblemDetails doesn't cover every use-case easily, all it's done is standardize that we write e.g. detail instead of details, and errors as error array instead of just error and then the other half uses errors in the same system.
@damiank6566
@damiank6566 Ай бұрын
Nice tutorial and to be honest I've done something similar in my project some time ago, but then I've watched one of your videos: kzbin.info/www/bejne/l2LclmybfLl1b5o&ab_channel=NickChapsas which as far as I remember shows some other approach and says that global exception handlers are not the best way, so now I'm a little bit confused. I'm still using the global exception filter and personally I think it's an elegant solution. One one or another, nice video as always ;)
@DusanJovanovicDBJ
@DusanJovanovicDBJ Ай бұрын
Comedy of Errors
@anotherme4638
@anotherme4638 Ай бұрын
If You can return it don't throw it. I always think that If you can use return don't throw exception. I think Exception should only be used for when the system is facing unexpected problem and it unable to handle it nor continue to work properly (db connection for example). Not forget to mention that there are a performance hit when throwing an exception.
@mmuekk
@mmuekk Ай бұрын
Suggestion: In my opinion, dark mode makes videos harder to see
@afonsocarvalho3124
@afonsocarvalho3124 Ай бұрын
I strongly disagree my friend. Dark mode is essencial on the screen age
@Cristian-ek7xy
@Cristian-ek7xy Ай бұрын
@@afonsocarvalho3124 I agree with @mmuekk, dark mode is so much difficult, specially if it is sunny.
@adambickford8720
@adambickford8720 Ай бұрын
I would stop watching if he did light mode since i can't control that on my end in any way
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
At a lower resolution, sometimes, but for most of us as devs we have dark mode and usually better bandwidth, so much prefer not looking at a flashlight.
@MrMattberry1
@MrMattberry1 Ай бұрын
More overcomplicating a simple problem
@SuperLabeled
@SuperLabeled Ай бұрын
Get out of my head Chapsas!
@Sayuri998
@Sayuri998 Ай бұрын
I still fail to understand why people include strings in machine-readable APIs. End users aren't supposed to see these error (heavens forbid you show these errors to the user because they can contain internal details and are non-localized), and you probably want to parse the respond to figure out what's going wrong in the client code anyway, so just dumping the error into the logs is just lazy coding. So why not just return error codes and include relevant context for the error? If we return enums or types for errors in our non-web APIs, and that works just fine, then why can't we do the same for web APIs?
@GeorgeGeorge-u5k
@GeorgeGeorge-u5k Ай бұрын
In case of error you can log the "description" so you don't have to go all the time to some manual with the mapping of codes-description.
@Sayuri998
@Sayuri998 Ай бұрын
@@GeorgeGeorge-u5k A well-named error code (aka string, enum) will tell you all you need without a description. We do it all the time in our code.
@magnusbergh5012
@magnusbergh5012 Ай бұрын
Depends what kind of error codes you return. If you return something like 1337 as error code then you need to document, include as description or have some other method to translate the error code. A named error code "WrongUnit" might be an option. But it is not really an enum but rather an enum name as string. Also the producer might have a lot of error codes which might be changed so logging the error description might be reasonable and not lazy. Anyway I do think it is good to have a unique error code so yuo can translate the error to the user (ithe rin non technical terms or actual translation to user's language)
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
@@Sayuri998 because the overhead is minimal for most systems, dumping the error into logs is the exact right thing to do with enough info that you can understand the entire error when looking at it later as dev, and you want the error descriptive enough that another dev integrating with your system can understand it/what the correct thing to do is (and avoid the support call).
@Sayuri998
@Sayuri998 Ай бұрын
@@Masterrunescapeer Right, but my argument is how is a web api different from directly calling a library method? We don't return error strings in our error objects. If the error code (a string, not a number) is clearly named, the developer will understand what it means. The first time they see it, they probably have to look it up in the documentation, but that's the same for an error string too. (And I would argue that you SHOULD look up errors when you see them.)
@T___Brown
@T___Brown Ай бұрын
I know its a part of the specs but by doing this you now require your users to handle many paths of responses. Its very painful. Just simplify to always return 200
@dimitrislaliotis504
@dimitrislaliotis504 Ай бұрын
Then they will not know what happened or what to do
@T___Brown
@T___Brown Ай бұрын
@dimitrislaliotis504 having a wrapper class of Response with a bool IsSuccess, T Data, and string Message is better imo
@Daniel15au
@Daniel15au Ай бұрын
The client already has to handle many paths - they have to differentiate successful responses from errors. Returning a proper HTTP code makes this easier, as you don't have to parse the response to know whether it's an error or not. This also means that analyzing the error rate is easier, as you can use the web server's logs (which contain the HTTP status code)
@T___Brown
@T___Brown Ай бұрын
@Daniel15au and 404 and why 304 how about 201. Why not just map every conceivable outcome so you can be as rest complaint as possible.
@Masterrunescapeer
@Masterrunescapeer Ай бұрын
Client goes from handling a success message and any number of different error messages to handling just success and problem details. For e.g. front-end can check if not success, check title, if known title (or type with new one) and I want a specific error for that one, or pass through detail or just say error. This avoids the issue of e.g. "error" or "errors" or error being e.g. request param name. RFC9457/7807 both have a JSON object example.
@kyreehenry9202
@kyreehenry9202 Ай бұрын
Result pattern makes your code tedious, Exceptions works better and infact Microsoft uses a lot on the framework you're coding on
Stop Using FirstOrDefault in .NET! | Code Cop #021
12:54
Nick Chapsas
Рет қаралды 97 М.
The New Option and Result Types of C#
15:05
Nick Chapsas
Рет қаралды 82 М.
Арыстанның айқасы, Тәуіржанның шайқасы!
25:51
QosLike / ҚосЛайк / Косылайық
Рет қаралды 700 М.
She made herself an ear of corn from his marmalade candies🌽🌽🌽
00:38
Valja & Maxim Family
Рет қаралды 18 МЛН
We Attempted The Impossible 😱
00:54
Topper Guild
Рет қаралды 56 МЛН
The Right Way To Build Async APIs in ASP.NET Core
20:12
Milan Jovanović
Рет қаралды 22 М.
Your REST API Errors Are Wrong. Problem Details Will Fix This
16:14
Milan Jovanović
Рет қаралды 11 М.
Why Just In Time Coding Is More Effective
7:36
Senior Code Review Buddy
Рет қаралды 4,8 М.
The PROBLEM With Checked Exceptions In Java
10:49
Continuous Delivery
Рет қаралды 9 М.
Using EF Core’s Coolest Feature to Audit in .NET
26:06
Nick Chapsas
Рет қаралды 40 М.
Don't Use Polly in .NET Directly. Use this instead!
14:58
Nick Chapsas
Рет қаралды 74 М.
How To Handle Permissions Like A Senior Dev
36:39
Web Dev Simplified
Рет қаралды 292 М.
They Let the Intern Code...
12:50
Low Level
Рет қаралды 388 М.
What's new in .NET 9 and C# 13
19:21
Filip Ekberg
Рет қаралды 20 М.
Is Functional Programming DEAD Already?
21:07
Continuous Delivery
Рет қаралды 75 М.