The Right Way To Return API Errors in .NET

Поділитися
Вставка
  • Опубліковано 21 лис 2024

КОМЕНТАРІ • 218

  • @nguyen_tim
    @nguyen_tim 14 днів тому +56

    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 14 днів тому +5

      I am a C# dev, and his content is invaluable!

    • @ClayBrooks1010
      @ClayBrooks1010 12 днів тому

      Nick Chapsas alt account confirmed

  • @Thial92
    @Thial92 5 днів тому

    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.

  • @a__random__person
    @a__random__person 14 днів тому +3

    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,

  • @gppsoftware
    @gppsoftware 12 днів тому +15

    The debate about what constitutes an 'exception' is one that has been argued about on many a fora!
    I am actually with Nick on this, but my observation on this is that the vast majority of developers are being extremely lazy in how they handle errors. 'Exceptions' are situations where software is unable to continue: like run out of disk space, run out of memory, hardware failure, network connection lost, database connection lost etc. Situations where a user has entered incorrect data and software is unable to proceed are NOT exceptions. They ARE DATA ERRORS caused by data not conforming to business rules and should be handled as part of a normal result returning mechanism. The fact that a lot of developers functionally overload the exception handling system (which goes against SOLID) to return both exception and normal data errors is laziness and a failure to identify things that are fundamentally different.
    Myself, I return a standard 'result' object as part of an http response and I adjust the http error code accordingly. This means that the calling application has no need to know whether an exception or general data error was returned: they are both returned as a result with an http error code.

    • @manrikevillalobos6270
      @manrikevillalobos6270 12 днів тому

      Exactly!! I handle expections and data erros in the same way, because they are not the same!

    • @TehGM
      @TehGM 11 днів тому +2

      Semantically? Yes. I can't disagree here.
      However in practice, custom exceptions + handler are safer - as throwing an exception causes code execution to stop unless explicitly handled, which prevents the code from continuing to run in invalid state. On top of that, they result in less boilerplate code - a simple line to throw, and you don't need every caller and their dog to have to worry - you just have a global handler.
      There honestly are benefits to both. I'll pick less boilerplate and less complex code + standardized way to follow the exceptions. I think it's the better way - just wish it had the less amount of performance hit.

    • @iliyan-kulishev
      @iliyan-kulishev 11 днів тому

      Yes. Have domain-http-ignorant result objects, which then you map to HTTP status codes and ProblemDetails.
      Code 200 when you get something successfully, 500 when really an exception, 204 when you mutate state successfully, 409 when validation problem.
      Leave code 400 alone, that's literally for "bad request" - bad url, can't deserialize JSON in request body and so on.

  • @Suv3g00
    @Suv3g00 14 днів тому +6

    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 13 днів тому

      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 13 днів тому

      ​@@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 13 днів тому +1

      @@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.

  • @aspirio777
    @aspirio777 14 днів тому +5

    Somebody should send your video to SAP

    • @patxy01
      @patxy01 10 днів тому

      Don't go too fast, they're still busy with s4hana migration

  • @Ar6yZuK
    @Ar6yZuK 14 днів тому +3

    We can throw ProblemException from switch expression without equality checking

  • @mightygingercles6481
    @mightygingercles6481 14 днів тому +1

    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

  • @persehlin4379
    @persehlin4379 13 днів тому

    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...

  • @mindcore1
    @mindcore1 14 днів тому +2

    @nickchapsas when you add the requestId and traceId to the ProblemDetails, did you accidently flip the keys, or am I missing something?

    • @JollyGiant19
      @JollyGiant19 14 днів тому +2

      I think he did swap them accidentally

  • @davidmontilla6466
    @davidmontilla6466 14 днів тому

    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 ?

  • @BernhardMillauer
    @BernhardMillauer 11 днів тому +3

    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.

  • @plainandstripes
    @plainandstripes 14 днів тому +1

    As always, many thanks Nick! 😊

  • @8660holm
    @8660holm 9 днів тому

    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?

  • @paulmdevenney
    @paulmdevenney 14 днів тому +2

    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 14 днів тому

      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 14 днів тому

      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 14 днів тому

      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 10 днів тому

      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.

  • @ruslanfreepoint
    @ruslanfreepoint 12 днів тому

    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.

  • @shakeuk
    @shakeuk 14 днів тому

    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)

  • @EffektUpInHere
    @EffektUpInHere 14 днів тому +1

    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?

  • @bluecup25
    @bluecup25 14 днів тому +1

    Homie went from "we just launched a brand new course" to "we just launched 23 new courses"

  • @adedoyin-emmanuel-adeniyi
    @adedoyin-emmanuel-adeniyi 14 днів тому +12

    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 14 днів тому

      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 13 днів тому +2

      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 11 днів тому

      @@Dustyy01 yeah this too.

  • @chadox71
    @chadox71 14 днів тому +1

    I'm really curious to know how you validate a request using functionnal programming and monads

    • @MartinLiversage
      @MartinLiversage 12 днів тому +1

      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 11 днів тому

      @@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.

  • @patrykklimas4398
    @patrykklimas4398 5 днів тому

    Is there any way to add request id to not catched exceptions?

  • @davidelliott4203
    @davidelliott4203 14 днів тому +1

    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);
    };
    });
    }
    }

  • @Vantian58
    @Vantian58 14 днів тому

    Hi Nik, how to return exact same format from Model Validation?

  • @shadowkras
    @shadowkras 10 днів тому +1

    Wait. Not many videos ago we were complaining about throwing exceptions and how expensive they were.
    What changed?

  • @ВкидимирПодгубенский

    It should be mentioned in REST API course

  • @SpaceTrump
    @SpaceTrump 14 днів тому +3

    I wrote this 10 years ago as a middleware...
    Error handling with exceptions is nice but its the easy way out.

    • @aliengarden
      @aliengarden 10 днів тому +1

      Easy way out sounds good. Is the harder way out better?

    • @SpaceTrump
      @SpaceTrump 10 днів тому

      @aliengarden more customizable, and exceptions tend to be memory and flops heavy.

  • @marsking
    @marsking 14 днів тому

    What are the uses of requestId and traceId?

    • @lmoelleb
      @lmoelleb 12 днів тому +1

      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.

  • @alanschmitt9865
    @alanschmitt9865 14 днів тому +3

    I literally just yesterday opened a PR matching this pattern fuck yeah
    Well I did some things different but still

    • @mindcore1
      @mindcore1 14 днів тому +1

      Same here, ironically enough

  • @heshamelsheltawy9039
    @heshamelsheltawy9039 14 днів тому

    Is this work with controllers

  • @solidid9368
    @solidid9368 13 днів тому +1

    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 13 днів тому

      God forbid explaining why do you think that and what better alternative you have.

    • @gppsoftware
      @gppsoftware 12 днів тому

      @@huszaristvan8246 The alternative is to use IF-THEN-ELSE and check your return codes, rather than relying on the exception handler to bomb out and catch your code because you haven't coded something that you should!
      Validation handling is checking user data according to rules. If it doesn't match, it is a DATA ERROR that should be handled as part of every-day processing and result responses. It is NOT an exception.

  • @CarrigansGuitarClub
    @CarrigansGuitarClub 14 днів тому +1

    Best place is to use it in your global error API handling middleware class

  • @turcanuioangeorge4750
    @turcanuioangeorge4750 14 днів тому +2

    I wonder how many got trigger when you threw the Exception instead of returning it with a Result.

    • @dimitrislaliotis504
      @dimitrislaliotis504 14 днів тому

      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 13 днів тому

      @@dimitrislaliotis504 It's opinion, not bad practice.

    • @dimitrislaliotis504
      @dimitrislaliotis504 13 днів тому

      @vonn9737 some say it's performance hit also

    • @vonn9737
      @vonn9737 13 днів тому

      @@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.

    • @gppsoftware
      @gppsoftware 12 днів тому +1

      @@dimitrislaliotis504 Throwing exceptions absolutely is a performance hit because the whole execution stack has to be unwound, scopes closed down and stack dumps created.
      We should not be writing code that uses exceptions as a convenient (lazy) way of bombing out of a call stack instead of exiting the call stack gracefully!

  • @szeroki
    @szeroki 13 днів тому

    Warsaw ❤ hello from Poland 🎉

  • @martink.7497
    @martink.7497 13 днів тому +1

    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 11 днів тому

      TraceId is used to track the flow of requests through multiple services, not for debugging individual application code.

    • @Kwpolska
      @Kwpolska 11 днів тому

      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 11 днів тому

      @@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 11 днів тому

      @@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.

  • @Crown0815
    @Crown0815 14 днів тому

    how is the performance? throwing exceptions is possible not the fastest way to get a response.

    • @aristondarmayuda1451
      @aristondarmayuda1451 14 днів тому

      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 14 днів тому +1

      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 14 днів тому +1

      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.

  • @dziarskihenk8798
    @dziarskihenk8798 14 днів тому

    Poland mentioned, Polska gurom!!!!
    Jokes aside, keep up great work

  • @paulguk
    @paulguk 14 днів тому +82

    Throwing exceptions for validation errors? Big ugh. We need that code cop guy to review this 😆

    • @nickchapsas
      @nickchapsas  14 днів тому +27

      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 14 днів тому +43

      ​Possible new part 2 showing a better way to do it without throwing exception ? Just an idea 💡

    • @SuperLabeled
      @SuperLabeled 14 днів тому +9

      Your operation can't continue because a business rule is not met, how is that not exceptional to so many people?

    • @Countryen
      @Countryen 14 днів тому +15

      ​@@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 14 днів тому +28

      @@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.

  • @codewithfrenchy
    @codewithfrenchy 14 днів тому

    no link for the code this time?

  • @hopkientran2534
    @hopkientran2534 14 днів тому

    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 14 днів тому

      It's even more terrible on Linux, especially with the watcher stuff

    • @hopkientran2534
      @hopkientran2534 13 днів тому

      @@geraldmaale that's terrible

    • @geraldmaale
      @geraldmaale 13 днів тому

      @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 10 днів тому +1

      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

  • @dangg44
    @dangg44 14 днів тому

    Can be done in multi language?

    • @nickchapsas
      @nickchapsas  14 днів тому +2

      Yeah every language should implement it in some way

    • @deeplerg7913
      @deeplerg7913 14 днів тому +1

      @@nickchapsas I think they meant different human languages, not programming languages

  • @zimpoooooo
    @zimpoooooo 14 днів тому

    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.

  • @Iingvarka
    @Iingvarka 14 днів тому

    It's remind me Salesforce where it returns 200 on everything and inside the response you've got 400

  • @sirus49
    @sirus49 14 днів тому +1

    the right way is always subjective

  • @parsalotfy
    @parsalotfy 13 днів тому

    Make a video about garnet

  • @GackFinder
    @GackFinder 14 днів тому +7

    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 12 днів тому

      Also as of this comment, RFC-9457's status is still 'PROPOSED STANDARD'. So currently 7807 is still the standing standard.

    • @Masterrunescapeer
      @Masterrunescapeer 10 днів тому

      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.

  • @teamdroid9834
    @teamdroid9834 14 днів тому

    this applies to minimalapis but i wonder if controller based guys als have the same concept behind

    • @mindcore1
      @mindcore1 14 днів тому

      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.

  • @purdysanchez
    @purdysanchez 12 днів тому

    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.

  • @sunclausewitz2707
    @sunclausewitz2707 14 днів тому +2

    What if you don't want to help a malicious actor by returning correct response for every request?

    • @victor1882
      @victor1882 14 днів тому +6

      then you're just hurting whoever is using the API, and they'll hunt and find you

    • @gileee
      @gileee 14 днів тому +2

      Malicious actors aren't deterred by that. Only clients.

    • @davidyates8154
      @davidyates8154 13 днів тому

      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 13 днів тому

      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.

  • @winchester2581
    @winchester2581 14 днів тому +27

    Returning 200 OK with { errors: [///] } is the OG way

    • @erynmacdonald
      @erynmacdonald 14 днів тому

      Go wash your mouth out with SOAP 😊

    • @T___Brown
      @T___Brown 14 днів тому +7

      Agreed otherwise your force the integrator to handle multiple paths and parsing. Auth, validation, errors, and actual result

    • @dylan8463
      @dylan8463 13 днів тому

      eeewww I hate APIs that do this. It's the worse

    • @T___Brown
      @T___Brown 13 днів тому

      @@dylan8463 you probably dont handle all the possibilities in the ones you love

    • @bluecup25
      @bluecup25 13 днів тому +1

      Unironically, yes. This standard basically adds nothing useful.

  •  14 днів тому

    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 10 днів тому

      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.

  • @Sergio_Loureiro
    @Sergio_Loureiro 14 днів тому +1

    "I identify as a problem".

  • @thanzeeljalaldeen
    @thanzeeljalaldeen 12 днів тому

    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

  • @Iingvarka
    @Iingvarka 14 днів тому

    Nick why you should use Result pattern for validation errors also Nick throw exception on validation

  • @vekzdran
    @vekzdran 7 днів тому

    Hahaha I see what you did, taunting poor commenters with this approach :)))

  • @matteobarbieri2989
    @matteobarbieri2989 14 днів тому +2

    With your example you send 400 even if the correct code it's different (e.g. 401/403/409)

  • @promant6458
    @promant6458 14 днів тому

    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 14 днів тому

      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!

  • @Daniel15au
    @Daniel15au 12 днів тому +2

    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.

  • @kyreehenry9202
    @kyreehenry9202 12 днів тому

    Result pattern makes your code tedious,
    Exceptions works better and infact Microsoft uses a lot on the framework you're coding on

  • @BeyondAppearances-0
    @BeyondAppearances-0 12 днів тому

    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.

  • @DusanJovanovicDBJ
    @DusanJovanovicDBJ 14 днів тому

    Comedy of Errors

  • @WalderFrey
    @WalderFrey 14 днів тому

    Seems like a long-winded way to return a 400 status code. Who's reading the message - human or machine?

    • @Masterrunescapeer
      @Masterrunescapeer 10 днів тому

      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.

  • @MrMattberry1
    @MrMattberry1 14 днів тому

    More overcomplicating a simple problem

  • @SuperLabeled
    @SuperLabeled 14 днів тому

    Get out of my head Chapsas!

  • @anotherme4638
    @anotherme4638 11 днів тому

    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.

  • @oussama7132
    @oussama7132 14 днів тому +9

    http code: 200
    response:
    {success:false,
    errorCode:401,description:unauthorized}

    • @winchester2581
      @winchester2581 14 днів тому

      This is the coolest way possible

    • @Sgro81
      @Sgro81 14 днів тому +2

      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 14 днів тому

      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 13 днів тому

      @@richard-t7c5o I'm very glad I'm not a consumer of your services then

  • @damiank6566
    @damiank6566 14 днів тому

    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:
    ua-cam.com/video/a1ye9eGTB98/v-deo.html&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 ;)

  • @GeorgeGeorge-u5k
    @GeorgeGeorge-u5k 13 днів тому +1

    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 10 днів тому

      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.

  • @T___Brown
    @T___Brown 14 днів тому

    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 14 днів тому

      Then they will not know what happened or what to do

    • @T___Brown
      @T___Brown 14 днів тому

      @dimitrislaliotis504 having a wrapper class of Response with a bool IsSuccess, T Data, and string Message is better imo

    • @Daniel15au
      @Daniel15au 12 днів тому +1

      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 12 днів тому

      @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 10 днів тому

      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.

  • @Sayuri998
    @Sayuri998 14 днів тому

    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 13 днів тому +1

      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 13 днів тому

      @@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 11 днів тому

      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 10 днів тому

      @@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 10 днів тому

      @@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.)

  • @mmuekk
    @mmuekk 14 днів тому +4

    Suggestion: In my opinion, dark mode makes videos harder to see

    • @afonsocarvalho3124
      @afonsocarvalho3124 14 днів тому +2

      I strongly disagree my friend. Dark mode is essencial on the screen age

    • @Cristian-ek7xy
      @Cristian-ek7xy 14 днів тому

      @@afonsocarvalho3124 I agree with @mmuekk, dark mode is so much difficult, specially if it is sunny.

    • @adambickford8720
      @adambickford8720 14 днів тому +1

      I would stop watching if he did light mode since i can't control that on my end in any way

    • @Masterrunescapeer
      @Masterrunescapeer 10 днів тому

      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.

  • @kyreehenry9202
    @kyreehenry9202 12 днів тому

    Result pattern makes your code tedious,
    Exceptions works better and infact Microsoft uses a lot on the framework you're coding on