1

I'm trying to write a custom validation class for an ASP.NET Core web app I'm developing. I've found various examples of how to write custom client-side validation, such as this and this. These are all clear and make sense to me. However, my problem is that my model is defined within a .NET Standard library that other projects share. I cannot access the base classes I need to create the custom validation class from within this library.

Basically, I need to ensure that model.PropertyA is never greater than model.PropertyB. I'm aware that I could write some JavaScript that accomplishes this, but I'd prefer to utilize the existing ASP.NET Core validation techniques if possible.

I'd prefer to avoid any 3rd party dependencies to accomplish this, if possible.

RichardJones
  • 149
  • 1
  • 10

2 Answers2

1

hy, Better to avoid Validation against Data Annotation because you don't have access to them in all cases , like the case you are describing; One powerful package exist "FluentValidation " you can create a model class and validate against properties sample:

public class Person {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public int Age { get; set; }
}

full documentation : https://docs.fluentvalidation.net/en/latest/aspnet.html

and then you add a validator for your commands like the following sample :

   public class CreatePersonCommandValidator : 
        AbstractValidator<CreatePersonCommand>
{
    ....

    public CreateTodoListCommandValidator(IApplicationDbContext context)
    {
        _context = context;

        RuleFor(v => v.Name)
            .NotEmpty().WithMessage("Name is required.")
            .MaximumLength(200).WithMessage("Name must not exceed 200 characters.");
             
        }...
      ....
     ..
  • Thanks for the answer. Unfortunately, as a general rule, I try and avoid 3rd party dependencies wherever possible. I think the best solution for me might be to just do it manually in JavaScript, unless there's another solution available. I'll upvote your answer regardless. – RichardJones Feb 11 '21 at 21:10
0

You could build a class extends the class from libraries. And extends IValidatableObject to implement Validation.

Base class is from librarie.

   public class Base
    {
        public int PropertyA { get; set; }
        public int PropertyB { get; set; }
    }

MyClass is build for validation.

public class MyClass : Base, IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (PropertyA > PropertyB)
        {
            yield return new ValidationResult(
                $"model.PropertyA {PropertyA} can't  greater than model.PropertyB ." );
        }
    }
}

Test codes:

[HttpPost]
public IActionResult Add([FromBody]MyClass myClass)
{
    if (ModelState.IsValid)
    {
        RedirectToAction("Index");
    }
    return View();
}

Test result:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>

enter image description here

Michael Wang
  • 3,782
  • 1
  • 5
  • 15
  • So, what if I want to validate against other properties as well, but I don't need custom validation for them? Since the validation lives in the new MyClass, using your example above, how would I add a simple [Required] attribute to a less complicated property where I only care if it's not empty? – RichardJones Feb 26 '21 at 15:10
  • Did you mean other properties from `Base` entity? Sorry for my poor understanding, I'm confused with the discription above. And I suggest you could update the question or post new thread to discuss it. – Michael Wang Mar 02 '21 at 08:20
  • 1
    I apologize for the miscommunication. I see looking at your example with fresh eyes that I would just add more logic to the Validate() method to account for this. – RichardJones Mar 03 '21 at 19:32