首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >FluentValidation在Blazor中的自定义验证

FluentValidation在Blazor中的自定义验证
EN

Stack Overflow用户
提问于 2020-03-24 14:53:47
回答 1查看 2.2K关注 0票数 2

我正在尝试创建一个自定义的复杂类型验证。我已经创建了一个有三个子类的类型,每个子类都有一个自定义验证器。Validator只是进入默认设置。一个具体的例子是,金额应该允许负数,但不管我的尝试,它只允许>0。任何帮助都是非常感谢的。

Razor Page

代码语言:javascript
运行
复制
<TSValidator />

TSValidator.sc

代码语言:javascript
运行
复制
public class TSValidator : ComponentBase
{
    [CascadingParameter] private EditContext CurrentEditContext { get; set; }

    protected override void OnInitialized()
    {
        if (CurrentEditContext == null)
        {
            throw new InvalidOperationException($"{nameof(TSValidator)} requires a cascading parameter of type {nameof(EditContext)}. For example, you can use {nameof(TSValidator)} inside an {nameof(EditForm)}");
        }

        CurrentEditContext.AddFluentValidation();
    }
}

扩展

代码语言:javascript
运行
复制
    public static EditContext AddFluentValidation(this EditContext editContext)
    {
        if (editContext == null)
        {
            throw new ArgumentNullException(nameof(editContext));
        }

        var messages = new ValidationMessageStore(editContext);

        editContext.OnValidationRequested += (sender, eventArgs) => ValidateModel((EditContext) sender, messages);

        editContext.OnFieldChanged += (sender, eventArgs) =>
            ValidateField(editContext, messages, eventArgs.FieldIdentifier);

        return editContext;
    }

    public static void ValidateModel(EditContext editContext, ValidationMessageStore store)
    {
        var validator = GetValidatorForModel(editContext.Model);
        var validationResults = validator.Validate(editContext.Model);

        store.Clear();
        foreach (var error in validationResults.Errors)
        {
            store.Add(editContext.Field(error.PropertyName), error.ErrorMessage);
        }

        editContext.NotifyValidationStateChanged();
    }

    public static void ValidateField(EditContext editContext, ValidationMessageStore store,
        in FieldIdentifier fieldIdentifier)
    {
        var properties = new[] {fieldIdentifier.FieldName};
        var context = new FluentValidation.ValidationContext(fieldIdentifier.Model, new FluentValidation.Internal.PropertyChain(), new MemberNameValidatorSelector(properties));
        var validator = GetValidatorForModel(fieldIdentifier.Model);
        var validationResults = validator.Validate(context);

        store.Clear();
        store.Add(fieldIdentifier, validationResults.Errors.Select(error => error.ErrorMessage));

        editContext.NotifyValidationStateChanged();
    }

    public static IValidator GetValidatorForModel(object model)
    {
        var abstractValidatorType = typeof(AbstractValidator<>).MakeGenericType(model.GetType());
        var modelValidatorType = Assembly.GetExecutingAssembly().GetTypes()
            .FirstOrDefault(t => t.IsSubclassOf(abstractValidatorType));
        var modelValidatorInstance = (IValidator) Activator.CreateInstance(modelValidatorType);

        return modelValidatorInstance;
    }

父类

代码语言:javascript
运行
复制
public class SubmissionActivity
{
    public Submission Submission { get; set; } = new Submission();
    public List<SalesActivitySubmission> SalesActivitySubmissions { get; set; } = new List<SalesActivitySubmission>();
    public RepActivitySubmission RepActivitySubmission { get; set; } = new RepActivitySubmission();

}

父校验器

代码语言:javascript
运行
复制
public class SubmissionActivityValidator : AbstractValidator<SubmissionActivity>
{
    public SubmissionActivityValidator()
    {
        RuleFor(s => s.RepActivitySubmission).SetValidator(new RepActivitySubmissionValidator());
        RuleForEach(s => s.SalesActivitySubmissions).SetValidator(new SalesActivitySubmissionValidator());
        RuleFor(s => s.Submission).SetValidator(new SubmissionValidator());
    }
}

儿童班

代码语言:javascript
运行
复制
public class Submission
{
    [Key]
    public long SubmissionId { get; set; }
    public DateTime SubmissionDate { get; set; }
    public bool IsActive { get; set; }
    public int PropertyId { get; set; }
    public Property Property { get; set; }
    public DateTime CreatedOn { get; set; }
    public long CreatedBy { get; set; }
    public DateTime ModifiedOn { get; set; }
    public long ModifiedBy { get; set; }
}

public class SalesActivitySubmission
{
    [Key]
    public long SalesActivitySubmissionId { get; set; }
    public long? SubmissionId { get; set; }
    public Submission Submission { get; set; }
    public long? SellerId { get; set; }
    public User Seller { get; set; }
    public int? TicketHierarchyId { get; set; }
    public TicketHierarchy TicketHierarchy { get; set; }
    [Column(TypeName = "money")]
    [Range(-999999999999.99, 999999999999.99, ErrorMessage = "Please enter a positive amount of 999,999,999,999.99 or less.")]
    public decimal? Amount { get; set; }
    [Range(int.MinValue, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? TicketSaleCount { get; set; }
    public DateTime CreatedOn { get; set; }
    public long CreatedBy { get; set; }
    public DateTime ModifiedOn { get; set; }
    public long ModifiedBy { get; set; }
}

public class RepActivitySubmission
{
    [Key]
    public int RepActivitySubmissionId { get; set; }
    public long SellerId { get; set; }
    public User Seller { get; set; }
    public long? SubmissionId { get; set; }
    public Submission Submission { get; set; }

    [Range(int.MinValue, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? CompletedCalls { get; set; }

    [Range(int.MinValue, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? Contacted { get; set; }

    [Range(int.MinValue, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? Pitches { get; set; }

    [Range(int.MinValue, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? Sales { get; set; }

    [Range(int.MinValue, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? Referrals { get; set; }

    [Range(int.MinValue, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? Appointments { get; set; }

    [Range(0, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? HoursWorked { get; set; }

    [Range(0, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? OvertimeHours { get; set; }

    [Range(0, int.MaxValue, ErrorMessage = "Please enter a valid positive number.")]
    public int? PTOHours { get; set; }

    [Column(TypeName = "money")]
    [Range(-999999999999.99, 999999999999.99, ErrorMessage = "Please enter a positive amount of 999,999,999.99 or less.")]
    public decimal? PropExpense { get; set; }
    public DateTime CreatedOn { get; set; }
    public long CreatedBy { get; set; }
    public DateTime ModifiedOn { get; set; }
    public long ModifiedBy { get; set; }
}

子验证器

代码语言:javascript
运行
复制
public class SubmissionValidator : AbstractValidator<Submission>
{
    public SubmissionValidator()
    {
        RuleFor(s => s.SubmissionDate).NotEmpty().NotNull();
    }
}

public class SalesActivitySubmissionValidator : AbstractValidator<SalesActivitySubmission>
{
    public SalesActivitySubmissionValidator()
    {
        RuleFor(s => s.SalesActivitySubmissionId).NotNull().WithMessage("SalesActivitySubmissionId cannot be null");
        RuleFor(s => s.SubmissionId).NotNull().WithMessage("SubmissionId cannot be null.");
        RuleFor(s => s.SellerId).NotNull().WithMessage("SellerId cannot be null");
        RuleFor(s => s.TicketHierarchyId).NotNull().WithMessage("TicketHierarchyId cannot be null.");
        RuleFor(s => s.Amount).InclusiveBetween(0, 999999999999)
            .WithMessage("Amount must be within 0 and 999999999999, inclusively.");
        RuleFor(s => s.TicketSaleCount).GreaterThan(-1).LessThan(int.MaxValue)
            .WithMessage($"TicketSaleCount must be null or between 0 and {int.MaxValue} inclusively.");

    }
}

public class RepActivitySubmissionValidator : AbstractValidator<RepActivitySubmission>
{
    public RepActivitySubmissionValidator()
    {
        RuleFor(r => r.SellerId).NotNull().WithMessage("SellerId cannot be null.");
        RuleFor(r => r.SubmissionId).NotNull().WithMessage("SubmissionId cannot be null.");
        RuleFor(r => r.CompletedCalls).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"CompletedCalls must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.Contacted).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"Contacted must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.Pitches).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"Pitches must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.Sales).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"Sales must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.Referrals).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"Referrals must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.Appointments).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"Appointed must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.HoursWorked).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"HoursWorked must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.OvertimeHours).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"OvertimeHours must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.PTOHours).GreaterThanOrEqualTo(0).LessThanOrEqualTo(int.MaxValue)
            .WithMessage($"PTOHours must be between 0 and {int.MaxValue} inclusively");
        RuleFor(r => r.PropExpense).GreaterThanOrEqualTo(0).LessThan(1000000000000)
            .WithMessage("PropExpense must be between 0 and 999999999999.99.");
    }
}
EN

Stack Overflow用户

回答已采纳

发布于 2020-03-25 23:57:55

它是否与拥有允许负数的范围验证数据属性和不允许负数的流畅验证规则有关?似乎您要使用不同的验证提供程序两次为相同属性指定验证规则,而且每个提供程序指定的规则是不同的。

例如,

的一个具体例子是,金额应该允许负数,但不管我的尝试如何,它只允许>0。

代码语言:javascript
运行
复制
public class SalesActivitySubmission
{
    ...

    [Column(TypeName = "money")]
    [Range(-999999999999.99, 999999999999.99, ErrorMessage = "Please enter a positive amount of 999,999,999,999.99 or less.")]
    public decimal? Amount { get; set; }

    ...
}
代码语言:javascript
运行
复制
public class SalesActivitySubmissionValidator : AbstractValidator<SalesActivitySubmission>
{
    public SalesActivitySubmissionValidator()
    {
        ...

        RuleFor(s => s.Amount).InclusiveBetween(0, 999999999999)
            .WithMessage("Amount must be within 0 and 999999999999, inclusively.");

        ...
    }
}

通常,在使用流利验证时,您不会指定数据属性--如果可能的话,您应该有一个验证的真实来源。

在ASP.NET中,核心流畅验证在其他验证提供者之前执行。在这种情况下,内置提供程序将没有机会测试范围验证数据属性的负数量,因为流利验证已经测试了属性并返回了验证失败。

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60833509

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档