问题描述
在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:
-
发送到操作的数据不包含
PublishedAt
或PublishedAt
为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?
推荐答案
尝试使用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
更改为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中验证格式无效的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!