loading...

.NET Core API REST POST validation with IValidatableObject

cesarcodes profile image Cesar Codes Updated on ・2 min read

I recently started using the IValidatableObject interface in my .NET Core APIs to encapsulate validation logic. This helps me separate concerns and keep my controllers lean. For example, suppose that we need to write an endpoint that returns all items for a given day…

One option would be to write a GET method that takes in a date and resourceGroup input parameters. This works, but the problem is that the validation logic for the parameters would result in extra code in your controller and ideally, we want our controllers to be as lean as possible.

A better option is to use a POST endpoint that receives a JSON object that corresponds to a C# model that extends the IValidatableObject interface. Suppose your API takes in the following data:

You could create a class in C# that models this data and accept it via an [HttpPost] endpoint. To do this you would create the POCO model of the JSON above and extend the IValidatableObject interface. When you implement this interface, you implement the Validate() method, in which you can build custom validations and return any errors via the List. Generic checks for things like required pieces of data or string length can be performed through annotations as shown below:

So when someone hits your endpoint, if the payload does not match your validations, the consumer of your endpoint will receive a list of errors. There are some nuances in order to get this pattern right, but for the most part, it’s pretty straight forward. You need to play with it for a bit and then you’ll get it.

By taking this approach, we can now accept richer JSON queries through our endpoint and encapsulate the validation logic in the C# query model. This makes the controller look much leaner and our code cleaner.

Bottom line is: leave parameter validation code out of your controller and let the framework handle it by extending IValidatableObject.

Thanks for reading and happy coding!

Posted on by:

cesarcodes profile

Cesar Codes

@cesarcodes

I experiment with code and talk about it.

Discussion

markdown guide
 

Great article ...I have a requirement to implement model validation in .net core API where endpoints are symmetric. Say for endpoints Model A is used as input parameter.Model A contains below properties

class A {
string name,
string email,
string Id,
string age
}

for Post endpoint,email,name,age and Id are required fields but for PUT endpoint only email is required. How I can use DataAnnotation & model state where required fields vary?

 

I think you meant to use the csharp tag (you typo'd). ;)

 

Thanks Jason!!!! Appreciate that!

 

Dot net core doesn't have any package to do that we have to do it from scratch? Weird... Even laravel framework do that for php applications...

 

Hey Miguel, .NET Core has model validation, but this is more for custom things you want to validate manually. How does Laravel handle it?

 

Hi Cesar, Laravel leads with validation in requests, but that also have model validations...

laravel.com/docs/6.x/validation

Cool, yeah it seems that the custom validation works the same way as here:

class Uppercase implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

This is basically the same concept as with dotnet core.

Hum cool, can you send me an example more complete ?

Actually, IAM trying to learn more about dotnet core to start doing microservices...

 

Hey good writeup Cesar. Care to drop an idea how would you inject from DI here? I need the UserManager instance from ASPNET Identity?