.NET Core Web API Data validation with FluentValidation

In this article, we will learn .NET Core Web API Data validation with FluentValidation.

What is Data Validation in Web API?

Data Validation simply tells the rules and validation that we apply to Data.

So, data Validation in Web API means, validating the data that is being sent by the client and if the data is not in the desired format then sending a message to the client about the error.

In order to understand the Data Validation in Web API, let’s create a model class named Product and add 3 properties as shown in below code snippet below.

public class Product
{
    public string ProductCode { get; set; }
    public int Stock { get; set; }
    public string ProductName { get; set; }
}

Now, we will create a ProductController class and add a Post method which accepts Product model as an input parameter.

Before posting the data to the server we need to check if all properties of the model class are in the correct format.

For example – The product Code field should not be blank, Stock must be greater than 0 (zero).

In the below code snippet, we are checking ProductCode and if it is blank or null then send a 400 (Bad Request) message to the client.

// POST api/<ProductController>
[HttpPost]
public IActionResult Post(Product product)
{
    if (string.IsNullOrEmpty(product.ProductCode))
    {
        return BadRequest();
    }

    return Ok();
}

In case ProductCode is blank then the client will receive the below response.

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "Bad Request",
  "status": 400,
  "traceId": "00-3738488015a04444b4f6f4b71938b168-591299b77d6d5344-00"
}

However, the above response doesn’t describe the exact error details.

So, to show the exact error details, we will use ModelState as shown in below code snippet below.

// POST api/<ProductController>
[HttpPost]
public IActionResult Post(Product product)
{
    if (string.IsNullOrEmpty(product.ProductCode))
    {
        ModelState.AddModelError(nameof(product.ProductCode),
            $"{nameof(product.ProductCode)} Can not be blank.");
        return BadRequest(ModelState);
    }

    return Ok();
}

Now, the client will receive the below error message in case ProductCode is blank.

{
  "ProductCode": [
    "ProductCode Can not be null"
  ]
}

What is ModelState?

ModelState is a property available in the instance of a controller class. It is a collection of name and value pairs which are submitted to the server while doing a POST operation. It also contains error messages, if any.

So, in this way, if we have multiple properties to check then we need to write code as shown below.

if (string.IsNullOrEmpty(product.ProductCode))
{
    ModelState.AddModelError(nameof(product.ProductCode),
                    $"{nameof(product.ProductCode)} Can not be null");
    return BadRequest(ModelState);
}

if (string.IsNullOrEmpty(product.ProductName))
{
    ModelState.AddModelError(nameof(product.ProductName),
        $"{nameof(product.ProductName)} Can not be null");
    return BadRequest(ModelState);
}

if (product.Stock <= 0)
{
    ModelState.AddModelError(nameof(product.Stock),
        $"{nameof(product.Stock)} Can not be 0");
    return BadRequest(ModelState);
}

But, this is a little bit lengthy and complex task.

Make it easy with FluentValidation

FluentValidation is a .NET framework-based library which helps to build strong type validation rules. It supports .NET Standard and .NET Core frameworks both.

FluentValidation NuGet Packages

Firstly, we need to install the below packages from the NuGet package manager.

  • FluentValidation
  • FluentValidation.AspNetCore
  • FluentValidation.DependencyInjectionExtensions

Code snippet for FluentValidation

So, to demonstrate this, first, create a class and inherit it from AbstractValidator<T>. Here T is the model class.

For this, we will use the below namespace.

using FluentValidation;
public class ProductValidator : AbstractValidator<Product>
{
    public ProductValidator()
    {
        RuleFor(x => x.ProductCode).NotEmpty();
        RuleFor(x => x.ProductName).NotEmpty();
        RuleFor(x => x.Stock).GreaterThan(0);
    }
}

Create the object of the Validator class and then use the ValidationResult class to fetch the result.

IsValid – Returns a boolean value which says if the validation has succeeded.

Now, we will write the below code in the Action method.

[HttpPost]
public IActionResult Post(Product product)
{
    ProductValidator validationRules = new ProductValidator();
    ValidationResult validationResult = validationRules.Validate(product);
    string message = "";
    if (!validationResult.IsValid)
    {
        foreach (var failure in validationResult.Errors)
        {
            message = message + "Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage;
        }

        return BadRequest(message);
    }

    return Ok();
}

You can return the error message in your way. So, by using FluentValidation we have minimised the code and achieved the validation status with built-in methods and rules.

Conclusion

So, in this article, we explored the data validation in Web API. To demonstrate the concept, I used FluentValidation which is a .NET framework-based library. This library helps us to easily apply validation rules on a member of a model class.

Leave a Comment

RSS
YouTube
YouTube
Instagram