When it comes to Validating Models, arenât we all leaning toward Data Annotations? There are quite a lot of serious issues with this approach for a scalable system. There is a library, Fluent Validations that can turn up the validation game to a whole new level, giving you total control.
In this article, we will talk about Fluent Validation and its implementation in ASP.NET Core Applications. We will discuss the preferred alternative to Data Annotations and implement it in an ASP.Net core API. The source code will be provided at the end of the article.
The Problem
Data Validation is extremely vital for any Application. The GO-TO Approach for Model validation in any .NET Application is Data Annotations, where you have to declare attributes over the property of models. Worked with it before?
It is fine for beginners. But once you start learning clean code, or begin to understand the SOLID principles of application design, you would just never be happy with Data Annotations as you were before. It is clearly not a good approach to combine your models and validation logic.
With the implementation of Data Annotations in .NET Classes, the problem is that there will be a lot of duplication lines of code throughout your application. What if the Developer Model class is to be used in another application/method where these Attribute validation changes? What if you need to validate a model that you donât have access to? Unit testing can get messy as well. You will definitely end up building multiple model classes which will no longer be maintainable in the longer run. So, whatâs the solution?
Introducing Fluent Validation - The Solution
Fluent Validation is a free-to-use .NET validation library that helps you make your validations clean, easy to create, and maintain. It even works on external models that you donât have access to, with ease. With this library, you can separate the model classes from the validation logic as it is supposed to be. It doesnât make your Model classes ugly like Data Annotations do. Also, better control of validation is something that makes the developers prefer Fluent Validation.
Fluent validations uses lamba expressions to build validation rules.
For small systems, I would recommend just using Data Annotations, because theyâre so easy to set up. For larger, more complex systems, I would recommend separating the validation concern using validator objects with Fluent Validation.
Implementing Fluent Validation in ASP.NET Core Applications
For this simple demonstration, letâs work on an ASP.NET Core 3.1 API Project that does nothing other than just validation with Fluent Validation. I will be using Postman to test and receive the validation messages and Visual Studio 2019 Community as my IDE ( the best for C# development)
Getting Started
Here is what the project structure would look like.
We will have 2 Projects in our Solution. One for the actual ASP.NET Core API, and the other one will be to mimic a Library that will have a model class to which we DO NOT have access. Letâs get started.
Installing FluentValidation.AspNetCore
Begin by installing this awesome library into your WebApi project via the Package Manage Console.
Install-Package FluentValidation.AspNetCore
Configuring FluentValidation
We will have to add Fluent Validation to our application. Navigate to Startup.cs and modify as follows.
Line #4 Add the Fluent Validation.
Line #6 Registers all the Custom Validations that are going to build. Note that, we will place our Validators within the API Project for this demonstration.
Line #7 It is possible to use both Fluent Validation and Data Annotation at a time. Letâs only support Fluent Validation for now.
Developer Model
A simple Developer class with basic properties.
Developer Controller
Create a new Controller at Controllers/DeveloperController.cs
Literally an ultra-slim Controller. Here we will just send a response OK if the passed model is valid.
Remember we spoke about validators while registering the services at Startup.cs?
Whatâs a Custom Fluent Validator?
In order to apply custom validation rules to properties of a model class/object. we will have to build custom validators. These Abstract Validators are of type T, where T will be your concerned class.
Creating the First Validator
Since we have made the Developer Model, letâs create a validator with 1 or 2 rules, just to get started.
Line #1 , the name of the class is DeveloperValidator, whose base class is AbstractValidator<T>
, where T is of type Developer.
Line #3 Constructor
Line #4 Our First Rules for the Property FirstName. Here it is mentioned that it should not be empty.
Testing with Postman
Run your API and open up Postman and POST a Developer model to the endpoint we built just now, ../api/developer
.
All good, we get an OK message. Now, remove the FirstName and leave it blank.Send a POST request.
Congrats. you built your own Validator. Quite simple and powerful, yeah? Letâs look into the response.
Itâs a 400 Bad Request Error Code which makes sense. Line #6 gives an array of errors. In our case, just 1 error and 1 property. Letâs make more errors and more rules, yeah? :D
Adding a Custom Message to Errors.
Itâs highly practical to show custom validation based on the property. Itâs quite simple with Fluent Validation. Go to the DeveloperValidator.cs
and modify our existing rule.
Use
{PropertyName}
to get the corresponding Property Name. These are placeholder variables of Fluent Validation Library. Read more about them here.
Letâs check it with POSTMAN.
Done, you have now learned how to display custom validation messages for properties.
Validating the String Length
I am really not sure if people have names with 2 letters. But letâs say, our system has a specific rule to only accepts name that is more than 2 characters. Also, our database says not more than 25 letters, please. With Fluent Validation, it is easy to notify the user upfront to use a first name that is within this range. Get the requirement? Letâs implement it then.
We get multiple validation error messages now. Pretty Sweet! But from a practical point of view, do you really need to show these 2 errors? Like, they are almost meaning the same. So how do we avoid showing 2 validation errors?
Stop on First Failure
Like I mentioned above, there can be scenarios where you actually need not run multiple validation rules for a property even if it fails at the first rule.
Line #2 means that when the validator hits its first error for the corresponding property, it stops. Now run the API and switch to Postman.
Cool, now letâs add a single character to the first name and try. Remember we set the minimum length of the first name to 2?
Working as we excepted.
Integrating Custom Functions
As an example, Theoretically, you could pass a number as the first name and the API would just say âCool, thatâs fineâ. Letâs see how to build a validation rule with Fluent Validation for such a scenario.
First create a simple helper method that would take in our firstname property and return a boolean based on its content. We will place this method in our DeveloperValidator class itself.
Now, letâs add this requirement to the rule and wire it up with our helper method.
Line #5 suggests that the property with return a true when passed to our helper. Letâs run the application and go to Postman.
So, that is taken care of as well.
Adding a new Rule
Now that we have added a rule for Validating First Names, letâs build one Last Name as well. I will just copy the rule of FirstName and Replace the property name.
Letâs run our application and check with Postman.
We see that now we have multiple properties being validated.
Email Validation
Since we are accepting emails in our endpoint, letâs validate that as well. Email Validation is something that comes out of the box with Fluent Validation.
I will try to enter an invalid email address and post it via Postman.
As Simple as that. There are quite a bunch of built-in validators included in the Fluent Validation library. Check them out here.
Manual Validation
There can be a case where you need to validate an object manually within your application using FLuent Validation. Letâs try to replicate such a use case. We will build a response model in Models/ResponseModel.cs which will return a list of error messages from within our code.
As you can see, it has a boolean property and a list of Error Messages. We will create another simple class like Developer.cs. Letâs name is Tester.cs
I will add a Simple Validator for the Tester Model at Validators/TesterValidator.cs.
Now letâs build a controller named Controllers/TesterController.cs
Line #4 creates a new instance of our Validator.
Line #5 a new list of strings - Errors.
Line #6-7 a dummy tester object having obvious validation errors.
Line #11 here we validate the dummy object,
Run the Application and switch to Postman.
There you have it. This is how you implement manual validation with Fluent Validation Library in ASP.NET Core Applications. You could have your own variants of course.
Summary
I hope you have understood this simple-to-follow guide about Fluent Validation. I am sure you will be switching to this powerful library from today onwards! These guys have some great documentation as well. Check it out too! What are your opinions about this library? Some devs still prefer Data Annotations over this. What about you? Let me know in the comments below.
If you found this article helpful,
Frequently Asked Questions
Is Fluent Validation Better than Data Annotations?
For small systems, I would recommend just using Data Annotations, because theyâre so easy to set up. For larger, more complex systems, I would recommend separating the validation concern using validator objects with Fluent Validation.