【问题标题】:Validating 2 models with ModelState.IsValid and FluentValidation validator in .NET Core 2在 .NET Core 2 中使用 ModelState.IsValid 和 FluentValidation 验证器验证 2 个模型
【发布时间】:2018-06-07 09:36:46
【问题描述】:

在我的 API 项目中,我有多个端点用于简单的 CRUD 操作。端点使用 FluentValidation 通过将验证器添加到 DI 并使用 ModelState.IsValid 来验证提供的模型。

当只有一个模型作为参数时,ModelState.IsValid 可以正常工作,但是一旦我有多个模型,那么只有第一个得到验证,下面的示例使这个问题更加清晰:

我的UPDATE端点操作需要2个参数(Id和model):

    public async Task<IActionResult> UpdateMedium([CustomizeValidator(RuleSet = ValidationClass.UPDATE)] [FromRoute] long id, [FromBody] Medium model)
    {
        if (!this.ModelState.IsValid)
        {
            return this.BadRequest(this.ModelState);
        }

        if (id != model.MediumID)
        {
            return this.BadRequest();
        }

        // Etc....

    }

this.ModelState.IsValid 现在只验证第一个模型 (Id),而忽略第二个模型。 验证这两个模型的最佳方法是什么?

Id 参数显然很简单,但我还是为它做了一个 FluentValidation 验证器(以防我们将来想为其添加更多验证逻辑):

public class IdValidator : AbstractValidator<long>
{
    public IdValidator()
    {
        RuleFor(r => r).NotEmpty().WithMessage("Id is empty.");
    }
}

此外,Medium 模型验证器如下所示:

    public class MediumValidator : AbstractValidator<Medium>
    {

        public MediumValidator()
        {
            RuleSet(ValidationClass.CREATE, Create);
            RuleSet(ValidationClass.UPDATE, Update);
        }

        private void Create()
        {
            RuleFor(r => r.InsertDateTime).Empty().WithMessage("{PropertyName} is not empty.");
            RuleFor(r => r.InsertUserID).Empty().WithMessage("{PropertyName} is not empty.");
            RuleFor(r => r.SolutionID).Empty().WithMessage("{PropertyName} is not empty.");
            RuleFor(r => r.Name).NotEmpty().WithMessage("{PropertyName} is not filled in.");
            RuleFor(r => r.Name).MaximumLength(100).WithMessage("The length of {PropertyName} must be {MaxLength} characters or fewer. You entered {TotalLength} characters.");
        }

        private void Update()
        {
            RuleFor(r => r.UpdateDateTime).Empty().WithMessage("{PropertyName} is not empty.");
            RuleFor(r => r.UpdateUserID).Empty().WithMessage("{PropertyName} is not empty.");
            RuleFor(r => r.MediumID).NotEmpty().WithMessage("{PropertyName} is empty.");
            RuleFor(r => r.Name).NotEmpty().WithMessage("{PropertyName} is not filled in.");
            RuleFor(r => r.Name).MaximumLength(100).WithMessage("The length of {PropertyName} must be {MaxLength} characters or fewer. You entered {TotalLength} characters.");
        }

    }

也许我应该只使用模型作为参数,然后只需要 ID 字段?

更新

启动时FluentValidation的设置:

services.AddMvc()
            .AddFluentValidation(fv =>
            {
                fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
            });

            // Add fluent validators
            services.AddTransient<IValidator<long>, IdValidator>();
            services.AddTransient<IValidator<Medium>, MediumValidator>();

更新 2:

我正在使用 swagger 测试端点(JSON 输入)。

【问题讨论】:

  • 多个模型?一个动作中不能有多个模型,因为由于 TCP/IP 连接的性质,只能反序列化一个模型(一旦读取,就不能再倒带)。该模型应该工作。 CustomizeValidatorAttribute 是什么? [FromRoute] 和另一个 [FromBody] 本身不应冲突。必须是您的设置或经过流畅验证的内容
  • 奇怪的是,我在主帖中添加了我的 FluentValidation 设置。

标签: asp.net-core fluentvalidation modelstate


【解决方案1】:

现在我已经实施了一种不同的方法。对于 UPDATE 操作,我现在手动将 Medium 模型错误添加到 ModelState

var validator = new MediumValidator();
var result = validator.Validate(model, ruleSet: ValidationClass.UPDATE);
result.AddToModelState(this.ModelState, null);

if (!this.ModelState.IsValid)
{
    return this.BadRequest(this.ModelState);
}

我们随时欢迎更好的解决方案!

【讨论】:

    猜你喜欢
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 2020-04-06
    • 2012-10-23
    • 2018-11-24
    相关资源
    最近更新 更多