I was looking for such a clean and smooth solution for custom error responses for a really long time and finally I found it in your video. Really thank you for this :) Keep working on your channel, you have really useful tips and great knowledge! Subscribers+1 :)
I'm not exactly sure what exactly to you have in mind. But in this factory you write your custom code and can put inthere all the logic you need. When would you need to validate multiple models since you have only 1 request body per request?
On the action context you have access to the HttpContext but also to a property called RoutData (or something very siimilar, I don't recall the exact name). And in this property you'll find the requuest parameters.
The thing I find confusing with validation is that surely the domain model needs to validate itself or be validated when it's created/updated? If that's the case do we need to validate the request or do we validate both the request and the domain model?
As I mentioned in another comment, we tend to confuse validation concerns. At the API level the only validation we NEED to make is the API contract validation. Meaning we need to validate that the incoming JSON bodies are compliant to our DTOs, which are the contract to the API. At this stage, no business rule validation should be performed. Validating business logic is something that you'll do either at the domain level (preferred especially when working with rich domain model) or application level (handler or service that's responsible for the application logic). Imagine going to any public institution 100 years ago. You probably needed to fill in a form. The clerk at the desk was responsible for validating if you filled in the form correctly. But iti didn't perform any validation to define if and how you can send something out. You'd eventually receive a response regarding your request some time afterwards. It's the same for APIs. Validation at API level is just the desk clerk. Validating business rules happens in a different place.
I never tried it with exception filters, but I guess you can implement the ExceptionFIlterAttribute class and make your filter become an attribute. Then you can decorate your actions with the attribute. Works pretty much for most filter types.
Is that code fragments needs to be in every model that needs custom validations? Or we can make a default base implementation an inherit that in our all models?
Obviously in this video I have covered the validation with ModelState. Which for validating API contract I consider preferable to FluenValidation. But, the thing is that you usually have only one single Error contract that contains also error messages. So in most cases you don't have to do anything custom. On the other hand, it's your own factory and you have full control. You can implement whatever logic you want. You can use reflection to peek into types, you can do conditional error returns based on some criteria that you might have as requirements. You have full flexibility here.
Thanks a lot, learnt something new today, would it be possible to do validations for case such as missing required fields and even say if client sent an extra unknown field, return a validation error saying "unknown field" in aspnet core
It's just a first junch at this, but I assume you can do that. As this is your own factory, you can implement a lot of logic in here. In the ActionContext you also have the HttpContext and the RouterData. With this information you can do virtually anything you want. There is however one thing to keep in mind. This factory creates a filder that needs to handle model validation. The model validation itself is done by ModelState. So if you want to do some very deep custom model validation, then you should probably look into implementing your own model binders and custom model validation.
I can't think of a reason why I wouldn't be happy with the default behavior. Maybe if I am porting legacy system that had some behavior that should be preserved to avoid breaking clients. If I had to do that I'd look for the kind of extensibility mechanism that you are showing, I'd expect something like this to be there. I wonder why they didn't do it via DI though, hmm...
@@pilotboba this might be so but the video is labelled "we're all doing model validation wrong!", The video was interesting in learning how to override the default model validation filter should you want to, but he basically recreated what already exists and didn't show how people how to do model validation right (other than avoid manual validation in the controller which I agree with).
I chose this video title because a lot of the model validation and custom response returning is done in controllers, which is totally wrong. Then, very popular is to do it in an action filter. Then you get the problem that I described in this video and most hack around the problem (remove ApiController or override OnResultExecuting instead of OnActionExecuting). Moreover, from a software craft perspective, having validation attributes on controller action is not the cleanest thing. So, a lot of wrong doings around here. And then the solution mentioned in the video that make all these problems go away.
@@Codewrinkles That all said, I think my favorite way so far is to use a Mediatr pipeline with a validation behavior. I'm still building out a few PoC reference applications for our team will follow and am trying other ideas as well, like FastEndpoints which also supports FluentValidation.
I don't agree with that. MediatR pipelines shouldn't validate API contracts. These are two different validation scopes. I think that's a topic I'll do a video soon enough :)
Isn't the whole point of model validation to have a context specific response to incorrect model data? What you did in the end was simply install your own global generic handler instead of the default one.
How about you just place data annotation inside the model that is entry point of the controller and make things much easy ? What is the problem there i keep doing it like that for 5 years and works perfectly.
Never thought we could use this approach with out touching controller...thanks
Well I was quite surprise myself when I found out. I think that's very powerful!
Thanks you and please can you cover unit testing with some real world examples
I'll try
I was looking for such a clean and smooth solution for custom error responses for a really long time and finally I found it in your video. Really thank you for this :) Keep working on your channel, you have really useful tips and great knowledge! Subscribers+1 :)
Wow! The edition has improved million times man! You are a pro now, awesome topic.
Wow, thanks!
Genial, era lo que venia buscado hacer hace tiempo, gracias.
Thanks! Do you prefer to use the same for minimal API? or for this approach do you prefer endpoint filters?
TBH I'm not sure that this works for the minimal API at all. But I'll have to try it out.
What about the scenario where we have multiple models that needs validation? How do we configure that?
I'm not exactly sure what exactly to you have in mind. But in this factory you write your custom code and can put inthere all the logic you need. When would you need to validate multiple models since you have only 1 request body per request?
Does this means we can do away class custom attribute for validation? Whats the impact? Whats the impact on javascript if any?
Thanks for the video.
My question is how do I pull a request params
from ActionContext
On the action context you have access to the HttpContext but also to a property called RoutData (or something very siimilar, I don't recall the exact name). And in this property you'll find the requuest parameters.
The thing I find confusing with validation is that surely the domain model needs to validate itself or be validated when it's created/updated? If that's the case do we need to validate the request or do we validate both the request and the domain model?
As I mentioned in another comment, we tend to confuse validation concerns. At the API level the only validation we NEED to make is the API contract validation. Meaning we need to validate that the incoming JSON bodies are compliant to our DTOs, which are the contract to the API. At this stage, no business rule validation should be performed.
Validating business logic is something that you'll do either at the domain level (preferred especially when working with rich domain model) or application level (handler or service that's responsible for the application logic).
Imagine going to any public institution 100 years ago. You probably needed to fill in a form. The clerk at the desk was responsible for validating if you filled in the form correctly. But iti didn't perform any validation to define if and how you can send something out. You'd eventually receive a response regarding your request some time afterwards.
It's the same for APIs. Validation at API level is just the desk clerk. Validating business rules happens in a different place.
@@Codewrinkles That makes sense. Thank you for the clarification Dan.
How can I configure this per action ? If I want use different logic in each action.
I never tried it with exception filters, but I guess you can implement the ExceptionFIlterAttribute class and make your filter become an attribute. Then you can decorate your actions with the attribute. Works pretty much for most filter types.
Is that code fragments needs to be in every model that needs custom validations? Or we can make a default base implementation an inherit that in our all models?
Obviously in this video I have covered the validation with ModelState. Which for validating API contract I consider preferable to FluenValidation. But, the thing is that you usually have only one single Error contract that contains also error messages. So in most cases you don't have to do anything custom.
On the other hand, it's your own factory and you have full control. You can implement whatever logic you want. You can use reflection to peek into types, you can do conditional error returns based on some criteria that you might have as requirements. You have full flexibility here.
Thanks a lot, learnt something new today, would it be possible to do validations for case such as missing required fields and even say if client sent an extra unknown field, return a validation error saying "unknown field" in aspnet core
It's just a first junch at this, but I assume you can do that. As this is your own factory, you can implement a lot of logic in here. In the ActionContext you also have the HttpContext and the RouterData. With this information you can do virtually anything you want.
There is however one thing to keep in mind. This factory creates a filder that needs to handle model validation. The model validation itself is done by ModelState. So if you want to do some very deep custom model validation, then you should probably look into implementing your own model binders and custom model validation.
I can't think of a reason why I wouldn't be happy with the default behavior. Maybe if I am porting legacy system that had some behavior that should be preserved to avoid breaking clients. If I had to do that I'd look for the kind of extensibility mechanism that you are showing, I'd expect something like this to be there. I wonder why they didn't do it via DI though, hmm...
nice, saved my time lot
Just found out about your channel.. awesome content man.. you have got a sub from me.
Welcome aboard! I'm glad you found me :) More awesome thinks to come!
Also, feel free to share it with your peers or other people that you think might benefit from the content on this channel.
I don't think having a static method in a contract class is a 100% clean approach...
Why are you re-building what comes out of the box? What's wrong with the default modal validation filter? Am I missing something?
In the end he wanted to specify the custom response, which is what the responsefactory allows you to do. It is still using the build in filter now.
@@pilotboba this might be so but the video is labelled "we're all doing model validation wrong!", The video was interesting in learning how to override the default model validation filter should you want to, but he basically recreated what already exists and didn't show how people how to do model validation right (other than avoid manual validation in the controller which I agree with).
I chose this video title because a lot of the model validation and custom response returning is done in controllers, which is totally wrong. Then, very popular is to do it in an action filter. Then you get the problem that I described in this video and most hack around the problem (remove ApiController or override OnResultExecuting instead of OnActionExecuting). Moreover, from a software craft perspective, having validation attributes on controller action is not the cleanest thing. So, a lot of wrong doings around here. And then the solution mentioned in the video that make all these problems go away.
@@Codewrinkles That all said, I think my favorite way so far is to use a Mediatr pipeline with a validation behavior.
I'm still building out a few PoC reference applications for our team will follow and am trying other ideas as well, like FastEndpoints which also supports FluentValidation.
I don't agree with that. MediatR pipelines shouldn't validate API contracts. These are two different validation scopes. I think that's a topic I'll do a video soon enough :)
Fantastic!
Glad you like it!
Isn't the whole point of model validation to have a context specific response to incorrect model data? What you did in the end was simply install your own global generic handler instead of the default one.
How about you just place data annotation inside the model that is entry point of the controller and make things much easy ?
What is the problem there i keep doing it like that for 5 years and works perfectly.
There's a difference between it's just "working" and well engineered. Robert C. Martin always says this: "making things working is just half the job".
What are "Actions"? I mean, I know what a Result is.