.NET Core API - Advanced Model Validations
.NET Core API - Advanced Model Validations

Advanced Model Validation For .NET Core Web APIs

In last article, we have seen what a model binding is and how validation attributes can be used with models to enable model validations.

.NET provides validation attributes for almost all basic validations. But in real world applications, sometimes you may come across some situation, where built-in attributes would not be sufficient. In this article, we are going to look at what are options in those cases.

Custom Attributes

First option is to create custom validation attribute. ValidationAttribute is an abstract class and it is used as base class for all the built-in validation attributes.

If a custom validation attribute is required, create a new class which extends ValidationAttribute. Next, override the abstract method – IsValid – to implement custom validation logic.

To better understand how the custom implementation should be, let’s take an example.

Let’s say, the minimum salary requirements for people less than 30 is $50 per hour and minimum salary requirement for people greater than 30 years is $200. So this validation is supposed to read date of birth. But this validation is supposed to be placed on HourlySalary property of model.

This validation can be implemented using the custom validation attribute as shown in below code.

IValidatableObject

Another option to apply custom validations is to implement interface – IValidatableObject – in model class. This interface provides a method – Validate – which can be implemented in the class.

Same validation from custom attributes section can be implemented using IValidatableObject as shown in below code.

Below code shows a validation for date of birth. People with age more than 65 years cannot be accepted by system (as they are supposed to be retired by then).

Code

Below code shows both custom validation attribute and IValidatableObject implemented for Employee model. Full working example can be downloaded from my GitHub repository.

Which one is better ?

Short answer – It really depends !

When a custom validation attribute is created, the logic of validation is outside the class. So it can be reused easily by just placing attribute on any model property.

When IValidatableObject is implemented in model, the validation logic is inside the model. So reusing is not possible – or – if not possible completely, then it is difficult at least.

So, which one should be used ? Various aspects can be checked to decide which option can be best suitable for the scenario. Those aspects may include reusability, ease of implementation or maintainability of the solution.

  • If there are chances of reusing the validation logic, then I would prefer validation attributes.
  • Some may always use IValidatableObject because it keeps the validation logic inside the model it is being used for.
  • Also, sometimes, ease of implementation can also be another driving factor.

When in doubt, I would personally prefer creating a custom validation attribute.

Do you share different opinions ? Let me know your thoughts.

Leave a ReplyCancel reply

This Post Has 8 Comments

  1. shriramkardile
    shriramkardile

    Hi Manoj, very useful and easy to understand article !

    There is also one way of FluentValidation, which I had tried in .net web api. (Something like this – https://www.tutlane.com/tutorial/aspnet-mvc/fluent-validation-in-aspnet-mvc-with-example)

    I believe it is also available in .net core as well.
    But do you know if IValidatableObject way has any benefits over FluentValidation way?
    I think IValidatableObject is easier to implement and understand though.

    1. Manoj Choudhari
      Manoj Choudhari

      There is no single best option. We will have to understand pros and cons of every approach and then decide which one should be used for a project.

      Generally, models (including validations ) should be part of contract. If the contract between caller and API is modified, generally it is a big thing and hence in many projects attribute-based approach or IValidatableObject approach might just be fine.

      If the model and validations are supposed to be varying independent of one another, then FluentValidation might be a good choice as it helps keeping validations in a separate class.

  2. shriramkardile
    shriramkardile

    Also one more follow up doubt on earlier reply – when we are using IValidatableObject on a particular dto, it will get applied to every action in which we have used that dto as input parameter, right?
    Or is there any way to control to apply validation in certain web api, but skip validation on certain other web apis (for the same dto as input parameter).

    1. Manoj Choudhari
      Manoj Choudhari

      I am not able to guess situations in which this would be required. Ideally, I would prefer creating models specific to endpoint. It might appear that the code is getting duplicated, but DRY principle should be applied to the logic not the POCO classes. Also, having separate models help in many other aspects (like versioning).
      If single model is still preferable for multiple endpoints, then additional property can be introduced to model to identify if validation is required or not. This new property can be checked in Validate method to skip validation conditionally.

  3. Aifaz

    Which one is best for custom validation on client side rendering when using jquery unobstrutitive validations?

    1. Manoj Choudhari
      Manoj Choudhari

      I have mostly used web APIs so I am not much familiar with unobstrusive validations using jquery. But as far as I have read, I think it works well with attribute approach.

  4. xaniff
    Whit

    How might one go about implementing asynchronous validation? Let’s say I want to not only verify that a value is a valid email address (per the [EmailAddress] attribute), but I also want to perform a check that the email address isn’t currently in use in my system, requiring an async call out to my database to look for the presence of an existing match.

    Thank you!

    1. Manoj Choudhari
      Manoj Choudhari

      This is interesting question. In my opinion, model validation in API mainly handles validation of requests incoming to the web server. I think there is no support for async validation. Maybe you can check documentation for more details. Also, in my opinion, generally it may not be good idea to mix the data layer constraints with the validations that are performed at API layer.