Как часть проекта ASP.NET Core MVC 1.0, у меня есть ViewModel с свойством ICollection<>
. Мне нужно проверить, что эта коллекция содержит один или несколько элементов. Мой пользовательский атрибут проверки не выполняется.
В моем экземпляре он содержит несколько прикрепленных файлов из формы multipart/form-data
.
Я украсил свойство в ViewModel с помощью специального атрибута проверки:
[RequiredCollection]
public ICollection<IFormFile> Attachments { get; set; }
Ниже приведен пользовательский класс атрибутов. Он просто проверяет, что коллекция не равна нулю и имеет больше нуля:
public class RequiredCollectionAttribute : ValidationAttribute
{
protected const string DefaultErrorMessageFormatString = "You must provide at least one.";
public RequiredCollectionAttribute() : base(DefaultErrorMessageFormatString) { }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var collection = (ICollection) value;
return collection == null || collection.Count > 0
? ValidationResult.Success
: new ValidationResult(ErrorMessageString);
}
}
И, наконец, в контроллере я гарантирую, что ViewModel в запросе POST
действителен, что должно вызвать проверку:
[HttpPost]
public async Task<IActionResult> Method(MethodViewModel viewModel)
{
if (!ModelState.IsValid)
return View(viewModel);
...
}
Если я нарушаю вызов ModelState.IsValid
, содержимое ModelState.Values
для свойства Attachments
:
Вопрос
- Почему моя точка останова в методе
RequiredCollectionAttribute.IsValid()
никогда не попадает? - Почему
ValidationState
устанавливается вSkipped
для свойстваAttachments
?
-
Изменить 1:
Определение MethodViewModel в соответствии с запросом:
public class MethodViewModel
{
...
[Display(Name = "Attachments")]
[RequiredCollection(ErrorMessage = "You must attached at least one file.")]
public ICollection<IFormFile> Attachments { get; set; }
...
}
-
Изменить 2:
Ниже приведено обрезанное значение actionContext.ModelState
(экспортировано в JSON) по запросу. Это состояние, когда точка останова попадает на запись в глобальный фильтр действий, OnActionExecuting()
:
{
"Count": 19,
"ErrorCount": 0,
"HasReachedMaxErrors": false,
"IsReadOnly": false,
"IsValid": true,
"Keys":
[
"Attachments"
],
"MaxAllowedErrors": 200,
"ValidationState": Valid,
"Values":
[
{
"AttemptedValue": null,
{
},
"RawValue": null,
"ValidationState": Microsoft.AspNet.Mvc.ModelBinding.ModelValidationState.Skipped
}
],
{
[
"Key": "Attachments",
{
"AttemptedValue": null,
"RawValue": null,
"ValidationState": Microsoft.AspNet.Mvc.ModelBinding.ModelValidationState.Skipped
},
"key": "Attachments",
{
"AttemptedValue": null,
"RawValue": null,
"ValidationState": Microsoft.AspNet.Mvc.ModelBinding.ModelValidationState.Skipped
}
]
}
}
-
Изменить 3:
Синтаксис вида бритвы для отображения поля ввода Attachments
.
<form role="form" asp-controller="Controller" asp-action="Method" method="post" enctype="multipart/form-data">
...
<div class="form-group">
<label asp-for="Attachments" class="control-label col-xs-3 col-sm-2"></label>
<div class="col-xs-9 col-sm-10">
<input asp-for="Attachments" class="form-control" multiple required>
<span asp-validation-for="Attachments" class="text-danger"></span>
</div>
</div>
...
</form>