ИМХО, мне нравится подход, приведенный ниже, и он широко используется без проблем. Преимущество этого подхода в том, что он поддерживает вашу модель в чистоте и позволяет разделить проблемы. Ваша логика проверки для Model
полностью независима.
Попробуйте использовать FluentValidation
. Вы можете прочитать об этом здесь подробно. Это пакет NuGet, который вы можете скачать через NuGet.org. После установки вы можете зарегистрировать его в 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
на 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
.
Или вы можете вручную проверить, находится ли ModelState.IsValid
внутри метода действия, и вернуть ObjectResult
с ModelState.