Open nagtilaklaxman opened 1 year ago
Do you want to do manual validations of objects? or do you want to know if an object was validated or not? Can you explain more of what you are trying to achieve with this?
I would like to do manual validation and need to have custom state in object having collection of other objects.
On Sat, Oct 1, 2022, 09:41 Sharaf M. Mansour @.***> wrote:
Do you want to do manual validations of objects? or do you want to know if an object was validated or not? Can you explain more of what you are trying to achieve with this?
— Reply to this email directly, view it on GitHub https://github.com/Blazored/FluentValidation/issues/159#issuecomment-1264131687, or unsubscribe https://github.com/notifications/unsubscribe-auth/AD56CNX6QV3S5NICPPUWWMLWA53DBANCNFSM6AAAAAAQZVKNUU . You are receiving this because you authored the thread.Message ID: @.***>
@nagtilaklaxman I think I know how to do such thing. Let me do a tiny repo and show a sample to you, then you tell me if that is what you want or not. Give me like few hours :D
@nagtilaklaxman I did a little test here is what I got so far
using FluentValidation;
using FluentValidation.Results;
namespace StateAndValidation;
public class Person
{
PersonValidator PersonValidator => new();
public string? Name { get; set; }
public int? Age { get; set; }
public string? EmailAddress { get; set; }
public List<ValidationFailure> States => PersonValidator.Validate(this).Errors;
public bool IsValid => PersonValidator.Validate(this).IsValid;
}
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required");
RuleFor(x => x.Name).MaximumLength(50).WithMessage( "Name must be less than 50 characters");
RuleFor(x => x.Name).MinimumLength(5).WithMessage( "Name must be at least 5 characters");
RuleFor(x => x.Age).NotEmpty().WithMessage( "Age is required");
RuleFor(x => x.Age).InclusiveBetween(18, 65).WithMessage( "Age must be between 18 and 65");
RuleFor(x => x.EmailAddress).NotEmpty().WithMessage( "Email address is required");
RuleFor(x => x.EmailAddress).EmailAddress().WithMessage( "Email address is invalid");
}
}
Note here:
public List<ValidationFailure> States => PersonValidator.Validate(this).Errors;
public bool IsValid => PersonValidator.Validate(this).IsValid;
State will have a list of all the Errors just like the ValidationSummary And IsValid will manually validate and check the state of is valid You can then map the States with enums like this
public enum State
{
NameShort, NameLong, AgeInvalid, EmailInvalid, NameNull, EmailNull, AgeNull
}
You can have a Custom State and Validation Components I hope I understood what you need Here is the index.Razor
@page "/"
<EditForm Model="@_person" OnSubmit="@SubmitForm">
<FluentValidationValidator />
<ValidationSummary />
<p>
<label>Name: </label>
<InputText @bind-Value="@_person.Name" />
</p>
<p>
<label>Age: </label>
<InputNumber @bind-Value="@_person.Age" />
</p>
<p>
<label>Email Address: </label>
<InputText @bind-Value="@_person.EmailAddress" />
</p>
<button type="submit">Save</button>
</EditForm>
@if(_person.States is not null){
<ul>
@foreach (var state in _person.States)
{
<li>@state.ErrorMessage</li>
}
</ul>
}
@code {
private Person _person = new();
private void SubmitForm()
=> Console.WriteLine(_person.IsValid);
}
Hello, Thanks for your help but this is not i wanted. Fluent validation has custom state property. I dont have EditForm on page it is just preview page of bulk upload via excel and need to validate all records via fluent validation by manually injecting IValidator of model and call validateAsync to get validation result. You can refer
https://docs.fluentvalidation.net/en/latest/custom-state.html
On Sun, Oct 2, 2022, 05:51 Sharaf M. Mansour @.***> wrote:
@nagtilaklaxman https://github.com/nagtilaklaxman I did a little test here is what I got so far
using FluentValidation;using FluentValidation.Results; namespace StateAndValidation;public class Person { PersonValidator PersonValidator => new(); public string? Name { get; set; } public int? Age { get; set; } public string? EmailAddress { get; set; } public List
States => PersonValidator.Validate(this).Errors; public bool IsValid => PersonValidator.Validate(this).IsValid; }public class PersonValidator : AbstractValidator
{ public PersonValidator() { RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required"); RuleFor(x => x.Name).MaximumLength(50).WithMessage( "Name must be less than 50 characters"); RuleFor(x => x.Name).MinimumLength(5).WithMessage( "Name must be at least 5 characters"); RuleFor(x => x.Age).NotEmpty().WithMessage( "Age is required"); RuleFor(x => x.Age).InclusiveBetween(18, 65).WithMessage( "Age must be between 18 and 65"); RuleFor(x => x.EmailAddress).NotEmpty().WithMessage( "Email address is required"); RuleFor(x => x.EmailAddress).EmailAddress().WithMessage( "Email address is invalid"); }
}
Note here:
public List<ValidationFailure> States => PersonValidator.Validate(this).Errors; public bool IsValid => PersonValidator.Validate(this).IsValid;
State will have a list of all the Errors just like the ValidationSummary And IsValid will manually validate and check the state of is valid You can then map the States with enums like this
public enum State { NameShort, NameLong, AgeInvalid, EmailInvalid, NameNull, EmailNull, AgeNull }
You can have a Custom State and Validation Components I hope I understood what you need Here is the index.Razor
@page "/" <EditForm Model="@_person" @.***">
<ValidationSummary /> <p> <label>Name: </label> <InputText @bind-Value="@_person.Name" /> </p> <p> <label>Age: </label> <InputNumber @bind-Value="@_person.Age" /> </p> <p> <label>Email Address: </label> <InputText @bind-Value="@_person.EmailAddress" /> </p> <button type="submit">Save</button>
@.***(_person.States is not null){
@foreach (var state in _person.States) { ***@***.*** }
@.*** { private Person _person = new();
private void SubmitForm() => Console.WriteLine(_person.IsValid); }
— Reply to this email directly, view it on GitHub https://github.com/Blazored/FluentValidation/issues/159#issuecomment-1264450756, or unsubscribe https://github.com/notifications/unsubscribe-auth/AD56CNWA6WAGIIF7QAZA543WBCB2DANCNFSM6AAAAAAQZVKNUU . You are receiving this because you were mentioned.Message ID: @.***>
@nagtilaklaxman you can do that in your model.
public async ValueTask<bool> IsValidAsync() => (await PersonValidator.ValidateAsync()).IsValid;
You can use that to trigger the manual validation just inject your model instead and call this function in your submission function (upload button) And this will trigger a manual validation.
How I can access custom state and error messages set via fluent validator?
Is It not possible to injectIvalidator<PersonValidator>
?
If you mean adding an interface to the DI container that would require a class that implements Ivalidator<PersonValidator>
But here is my question.
Why do you want to inject an interface when your AbstractValidator can do the same?
You already have the class Called PersonValidator
which already implements the ivalidator
interface here
public abstract class AbstractValidator<T> : IValidator<T>, IEnumerable<IValidationRule>
You can inject and use that class as much as you want to do any custom validation or track the state. It is already there!
Is It possible to inject IValidator and get all custom state of object?