I used FluentValidation with Steve Sanderson's implementation https://gist.github.com/SteveSandersonMS/090145d7511c5190f62a409752c60d00#file-fluentvalidator-cs
I then made a few modifications to it.
First I added a new interface based on IValidator.
public interface IMyValidator : IValidator
{
/// <summary>
/// This should be the objects primary key.
/// </summary>
object ObjectId { get; set; }
}
Then I changed the FluentValidator to implement IMyValidator and added a new parameter.
public class FluentValidator<TValidator> : ComponentBase where TValidator: IMyValidator,new()
{
/// <summary>
/// This should be the objects primary key.
/// </summary>
[Parameter] public object ObjectId { get; set; }
... continue with the rest of Steve Sanderson's code
}
For my FluentValidation AbstractValidator I did the following.
public class InvestigatorValidator:AbstractValidator<IAccidentInvestigator>,IMyValidator
{
public object ObjectId { get; set; }
public InvestigatorValidator()
{
RuleFor(user=>user.LogonName).NotEmpty().NotNull().MaximumLength(100);
RuleFor(user=>user.Email).NotEmpty().NotNull().MaximumLength(256);
RuleFor(user=>user.FullName).NotEmpty().NotNull().MaximumLength(100);
RuleFor(user=>user.RadioId).MaximumLength(25);
RuleFor(user=>user.LogonName).MustAsync(async (userName, cancellation)=>
{
var exists = await GetUserNameExists(userName);
return !exists;
}).WithMessage("UserName must be unique.");
RuleFor(user=>user.Email).MustAsync(async (email, cancellation)=>
{
var exists = await GetEmailExists(email);
return !exists;
}).WithMessage("Email must be unique.");
}
private async Task<bool> GetUserNameExists(string userName)
{
if(ObjectId is int badge)
{
await using var db = MyDbContext;
var retVal = await db.AccidentInvestigators.AnyAsync(a=>a.Badge != badge && string.Equals(a.LogonName.ToLower(), userName.ToLower()));
return retVal;
}
return false;
}
private async Task<bool> GetEmailExists(string email)
{
if(ObjectId is int badge)
{
await using var db = DbContext;
var retVal = await db.AccidentInvestigators.AnyAsync(a=>a.Badge != badge && string.Equals(a.Email.ToLower(), email.ToLower()));
return retVal;
}
return false;
}
}
Then in my Razor Component Form I changed the FluentValidator to set the ObjectId.
<EditForm Model="_investigator" OnValidSubmit="Save">
<FluentValidator TValidator="InvestigatorValidator" ObjectId="@_investigator.Badge"/>
... put the rest of your layout here
</EditForm>