在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种不同的场景:
PublishedAt
或PublishedAt
为NULL。
通过使用DateTime?
我可以检查它是否为NULL或过去,以防它被定义。
这有意义吗?PublishedAt
日期(2019-20-40)。
在这种情况下,我意识到Model
变为null,所以我无法验证它。
我也无法发回友情信息,例如:
“发布日期格式无效”
当DateTime格式错误时,如何返回友好消息?
我想避免使用String作为PublishedAt
的数据类型。
也许使用自定义Model Binder?你能做的就是把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有一个如何做到这一点的例子。
恕我直言,我喜欢下面的方法,并广泛使用它没有任何问题。这种方法的好处在于它可以保持模型的清洁并使关注点分离。
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
。