在ASP.NET Core API中使用无效格式验证值

问题描述 投票:1回答:2

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

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

Model的地址如下:

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

物业PublishedAt是必需的,需要在过去。

在调用动作时,我能够预测2种不同的场景:

  1. 发送到操作的数据不包括PublishedAtPublishedAt为NULL。 通过使用DateTime?我可以检查它是否为NULL或过去,以防它被定义。 这有意义吗?
  2. 发送到行动的数据包括无效的PublishedAt日期(2019-20-40)。 在这种情况下,我意识到Model变为null,所以我无法验证它。 我也无法发回友情信息,例如: “发布日期格式无效” 当DateTime格式错误时,如何返回友好消息? 我想避免使用String作为PublishedAt的数据类型。 也许使用自定义Model Binder?
c# asp.net-core asp.net-core-2.2
2个回答
0
投票

你能做的就是把Required属性放在PublishedAt

public class Model 
{ 
    [Required]
    public DateTime? PublishedAt { get; set; }       
}

[ApiController]
public class ValuesController : ControllerBase
{
   public async Task<IActionResult> Create([FromBody]Model model) 
   {
   }
}

如果您的控制器上有ApiController属性,它应该自动响应BadRequest(如果它不存在)。

同样,您可以使用消息添加自己的自定义验证属性。 Asp.Net documentation有一个如何做到这一点的例子。


0
投票

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

尝试使用FluentValidation。你可以详细了解它here。这是一个NuGet包,你可以通过NuGet.org download。安装完成后,您可以在ConfigureServices中注册,如下所示:

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继承的任何公共非抽象类型,并将其注册到容器中。然后,您可以为AbstractValidator定义Model,如下所示

在创建AbstractValidator之前

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

如果你真的想避免将PublishedAt更改为string,你可以通过略微改变规则尝试相同的方法,看看它是否适合你

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语句中指定的消息。

或者您可以手动检查action方法中是否有ModelState.IsValid并使用ModelState返回ObjectResult

© www.soinside.com 2019 - 2024. All rights reserved.