In this community post, ErfanBaghdadi seeks advice on best practices for implementing model validation in .NET with FluentValidation, focusing on maintainability and clean code.

Summary

ErfanBaghdadi explains their current approach to model validation in .NET using the FluentValidation library. They have validator classes prepared, but note from the documentation that automatic validation—similar to data annotations—is discouraged in favor of manual validation inside controllers.

Core Questions

  • Why is manual validation preferred over automatic validation with attributes/data annotations in FluentValidation?
  • How can repetitive validation code be avoided for every endpoint?
  • Is it better to use a custom action filter, a base controller class, or extension methods for validation logic?
  • Where to handle business logic checks, such as ensuring usernames are unique—within the controller or the validation layer?
  • What are best practices to ensure clean, maintainable code for validation?

Community Context

  • The author is relatively new to .NET development, asking for best practices and tips to avoid developing bad habits.
  • They are seeking strategies to streamline or centralize validation to reduce boilerplate and improve code consistency.

Key Discussion Points

  • FluentValidation’s manual approach is preferred because it offers clearer separation of concerns and more control compared to attribute-based (automatic) validation.
  • Repetitive validation logic can be abstracted away using custom action filters, base controller classes, or extension methods, each with trade-offs:
    • Custom Action Filter: Centralizes validation logic and applies it to multiple controllers without repetitive code.
    • Base Controller: Allows shared validation utilities but can increase inheritance complexity.
    • Extension Methods: Flexible and reusable, but might scatter logic across codebase.
  • Business rules that rely on state (like checking for existing usernames) are commonly handled either in the controller or included as asynchronous validation rules in FluentValidation.
  • Community advice often emphasizes clean separation between validation concerns and business logic.
  • Maintainability can be achieved by minimizing code repetition, centralizing common validation, and clearly documenting approaches adopted.

Recommendations

  • Use a centralized validation approach (action filter or shared method) that’s easy to test and maintain.
  • Keep validation rules (format, required fields, etc.) in the validator classes; handle business rule checks through injected services in validators if possible.
  • Strive for clear separation of controller logic, validation, and business rules to ensure code remains comprehensible and maintainable as your application grows.

This post appeared first on “Reddit DotNet”. Read the entire article here