How to Create a custom model validation attribute in ASP.NET Core
By FoxLearn 3/7/2025 4:29:10 AM 97
However, sometimes built-in attributes aren’t enough, and you might need to create your own custom validation logic. In this example, I'll demonstrate how to create a custom model validation attribute that ensures a password has a minimum length.
Subclass ValidationAttribute
and Implement Validation Logic
To create a custom validation attribute, you need to subclass ValidationAttribute
, override the IsValid()
method, and write your validation logic. The IsValid()
method takes an object
parameter, so you need to check its type, and then apply the specific validation. In this example, we'll check if the password's length is above a certain threshold.
using System.ComponentModel.DataAnnotations; public class MinPasswordLengthAttribute : ValidationAttribute { private readonly int _minLength; public MinPasswordLengthAttribute(int minLength) { _minLength = minLength; } public override bool IsValid(object value) { if (value is string password && password.Length >= _minLength) { return true; } return false; } }
In this example:
- We define a
MinPasswordLengthAttribute
that accepts a minimum password length through the constructor. - Inside the
IsValid()
method, we check if thevalue
is a string and if its length is greater than or equal to the specified minimum length. If both conditions are true, the validation passes.
When a request is received with a model containing this attribute, the framework will automatically call the IsValid()
method to validate the property value. If validation fails, it will return a 400 Bad Request with an error response.
Customize the Error Message (Optional)
By default, the error message generated will be generic, like "The field <property name> is invalid." You may want to make the error message more descriptive. You can override the FormatErrorMessage()
method to provide a custom message that includes the property name.
using System.ComponentModel.DataAnnotations; public class MinPasswordLengthAttribute : ValidationAttribute { private readonly int _minLength; public MinPasswordLengthAttribute(int minLength) { _minLength = minLength; } public override bool IsValid(object value) { if (value is string password && password.Length >= _minLength) { return true; } return false; } public override string FormatErrorMessage(string name) { return $"{name} must be at least {_minLength} characters long."; } }
In this example:
- We override the
FormatErrorMessage()
method to return a more specific error message. - Now, instead of the generic message, the response will say something like: "Password must be at least 8 characters long."
Using the Attribute
Now, you can apply this custom attribute to a model property.
For example, How to use the MinPasswordLength
attribute on a password field:
public class UserRegistration { public string Username { get; set; } [MinPasswordLength(8)] public string Password { get; set; } }
The Password
property now uses the MinPasswordLength
attribute, which enforces that the password must be at least 8 characters long.
Test the Validation
Let's test this custom validation by sending a request with a short password using Postman.
Request:
POST /users/register { "username": "john_doe", "password": "1234" }
Response:
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "0HMHK72C15DT8:0000000B", "errors": { "Password": [ "Password must be at least 8 characters long." ] } }
In this case, the password is too short (less than 8 characters), so the validation error is triggered, and the response returns a 400 status with a clear error message.
Now, let’s try with a valid password:
Request:
POST /users/register { "username": "john_doe", "password": "StrongPassword123" }
Response:
{ "status": 200, "message": "Registration successful" }
Since the password is now long enough, the validation passes, and the user can proceed with registration.
- The name 'Session' does not exist in the current context
- Implementing Two-Factor Authentication with Google Authenticator in ASP.NET Core
- How to securely reverse-proxy ASP.NET Core
- How to Retrieve Client IP in ASP.NET Core Behind a Reverse Proxy
- Only one parameter per action may be bound from body in ASP.NET Core
- The request matched multiple endpoints in ASP.NET Core
- How to disable ModelStateInvalidFilter in ASP.NET Core
- How to fix LoginPath not working in ASP.NET Core