在ASP.NET Core API中验证格式无效的值 [英] Validate values with invalid format in ASP.NET Core API

查看:279
本文介绍了在ASP.NET Core API中验证格式无效的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ASP.NET Core 2.2 API上,我执行以下操作:

On an ASP.NET Core 2.2 API I have the following action:

public async Task<IActionResult> Create([FromBody]Model model) {
}

Model如下:

public class Model { 
  public DateTime? PublishedAt { get; set; }       
}

属性PublishedAt是必需的,并且必须是过去的.

Property PublishedAt is required and needs to be in the past.

调用该动作时,我可以预测2种不同的情况:

When calling the action I am able to predict 2 different scenarios:

  1. 发送到操作的数据不包含PublishedAtPublishedAt为NULL.

通过使用DateTime?,我可以检查它是否为NULL或在过去的情况下(如果已定义).

By using DateTime? I am able to check if it is NULL or in the past in case it is defined.

这有意义吗?

发送到操作的数据包含无效的PublishedAt日期(2019-20-40).

Data sent to action includes an invalid PublishedAt date (2019-20-40).

在这种情况下,我意识到Model为空,所以我无法对其进行验证.

In this case I realised that Model becomes null so I cannot validate it.

我也无法发送回友好消息,例如:

I also cannot send back a friendly message such as:

发布日期格式无效"

当DateTime格式错误时,如何返回友好消息?

我想避免将String用作PublishedAt的数据类型.

I would like to avoid using String as data type for PublishedAt.

也许正在使用自定义的Model Binder?

Maybe using a custom Model Binder?

推荐答案

恕我直言,我喜欢下面的方法,并已广泛使用它而没有任何问题.这种方法的好处是,它可以保持模型清洁并分离关注点.您对Model的验证逻辑是完全独立的.

IMHO, I like the approach below and have used it extensively without any problems. The good thing about this approach is that it keeps your model clean and enables separation of concerns. Your validation logic for the Model is completely independent.

尝试使用FluentValidation.您可以在此处详细了解.这是一个NuGet程序包,您可以通过NuGet.org 下载.安装后,您可以在ConfigureServices中进行注册,如下所示:

Try using FluentValidation. You can read about it here in detail. It's a NuGet package that you can download via NuGet.org. Once installed you can register it in ConfigureServices like below:

1 public void ConfigureServices(IServiceCollection services)
2 {
3    services.AddMvc(setup => {
4      //...mvc setup...
5    }).AddFluentValidation(configuration => configuration
6      .RegisterValidatorsFromAssemblyContaining<Startup>());
7 }

第5行和第6行将自动查找从AbstractValidator继承的任何公共的非抽象类型,并将它们注册到容器中.然后,按如下所示为Model定义AbstractValidator

Line number 5 and 6 will automatically find any public, non-abstract types that inherit from AbstractValidator and register them with the container. You then define your AbstractValidator for Model as below

在创建AbstractValidator

我知道您提到过要避免将PublishedAt类型更改为字符串.但是,我建议您考虑一下.这将使验证参数变得容易,否则,自动模型绑定可能会以不同的格式将其绑定,并且自定义模型绑定比以下代码难一些.

I know you mentioned that you would want to avoid changing the PublishedAt type to string. However, I would suggest you consider it. That will make it easy to validate the parameter, otherwise, automatic model binding may bind it in a different format, and custom model binding is little trickier than the following.

如果您确实要避免将PublishedAt更改为string, 您可以通过稍微更改规则来尝试相同的方法,然后查看 如果适合您

If you really want to avoid changing the PublishedAt to string, you can try the same approach by changing the rules slightly and see if that works for you

public class ModelValidator : AbstractValidator<Model>
{
    public ModelValidator()
    {
        // add a rule that Date must be in the past, shouldn't be empty
        // and in the correct format
        RuleFor(model => model.PublishedAt)
           .Cascade(CascadeMode.StopOnFirstFailure)
           .Must(date => !string.IsNullOrWhiteSpace(date))
               .WithMessage("PublishAt is a required parameter")
           .Must(arg =>
           {
               if (DateTime.TryParseExact(arg.ToString(), new[] { "dd-MMM-yyyy" }, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
               {
                   return date < DateTime.Now;
               }

               return false;
            })
            .When(model => !string.IsNullOrWhiteSpace(model.PublishedAt))
            .WithMessage("Argument PublishAt is invalid. Please specify the date in dd-MMM-yyy and should be in the past");
    }
}

上面的验证器将在模型绑定过程之后执行,如果验证失败,则WithMessage语句会将错误添加到ModelState.由于您具有[ApiController]属性.您的模型将通过验证,并将返回您在WithMessage语句中指定的消息.

The above validator will be executed after the model binding process and if the validation fails, WithMessage statements will add the error to the ModelState. As you have [ApiController] attribute. Your model will be validated and it will return the messages you specified in the WithMessage statements.

或者您可以手动检查action方法内的ModelState.IsValid并返回带有ModelState的ObjectResult.

Or you can manually check if the ModelState.IsValid inside the action method and return the ObjectResult with the ModelState.

这篇关于在ASP.NET Core API中验证格式无效的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆