У меня есть собственный атрибут проверки, который я сделал для группы флажков, расположенных внутри ViewComponent. До того, как я переместил его в ViewComponent, ненавязчивое сообщение проверки отлично работало через asp-validation-for, но теперь сообщение там не появляется.
В то же время я собираю ошибки проверки на стороне сервера и передаю их обратно в представление, и это работает так, как ожидалось: поэтому я получаю сообщение об ошибке, которое я сделал через пользовательский атрибут, он просто не показывает сообщение в .
Вот код (я упрощаю его, где могу, дайте мне знать, если вам нужна дополнительная информация. Я извиняюсь, если что-то упустил.):
Контроллер:
public IActionResult Enrollment(EnrollmentViewModel enrollmentVM)
{
return View("~/Enrollment.cshtml", enrollmentVM);
}
public EnrollmentViewModel SetModelListItems(EnrollmentViewModel enrollmentVM)
{
if (enrollmentVM.Preferences == null)
{
var preferencesList = preferences.GetAll().ToList();
enrollmentVM.Preferences = preferences.Select(x => new SelectListItem
{
Text = x.PreferencesName,
Value = x.PreferenceseId.ToString()
}).ToList();
return enrollmentVM;
}
public async Task<IViewComponentResult> InvokeAsync(EnrollmentViewModel enrollmentVM)
{
enrollmentVM = SetModelListItems(enrollmentVM);
return new ViewViewComponentResult()
{
ViewData = new ViewDataDictionary<EnrollmentViewModel>(ViewData, enrollmentVM)
};
Основной вид:
@model EnrollmentViewModel;
@{
Layout = "_Layout.cshtml";
}
<button type="submit" id="EnrollForm" form="EnrollForm">
<span>Save</span>
</button>
<div>
@await Component.InvokeAsync("EnrollClient", new { enrollmentVM = @Model });
</div>
@section Scripts
{
@if (Model.HasErrors)
{
@foreach (string errorMessage in Model.SubmitErrors)
{
<script type="text/javascript">
toastr["error"]("@errorMessage");
</script>
}
}
ВидКомпонент:
@model EnrollmentViewModel
@using (Html.BeginForm("EnrollClient", "Enrollment", FormMethod.Post, new { enctype = "multipart/form-data", id = "EnrollForm" }))
{
<fieldset>
<legend>Preferences (select all that apply)</legend>
@for (var i = 0; i < Model.Preferences.Count(); i++)
{
<div>
<input type="checkbox" asp-for="@Model.Preferences[i].Selected">
<label asp-for="@Model.Preferences[i].Selected">@Model.Races[i].Text</label>
<input type="hidden" asp-for="@Model.Preferences[i].Value" />
<input type="hidden" asp-for="@Model.Preferences[i].Text" />
</div>
}
<span asp-validation-for="Preferences" class="text-danger"></span>
</fieldset>
Почтовый метод:
public IActionResult EnrollClient(EnrollmentViewModel viewModel)
{
try
{
if (!ModelState.IsValid)
{
viewModel = SetModelListItems(viewModel);
viewModel.HasErrors = true;
viewModel.SubmitErrors = ModelState.Values
.SelectMany(state => state.Errors)
.Select(error => error.ErrorMessage);
return View("~/Enrollment.cshtml", viewModel);
}
SaveForm();
}
//....
}
ViewModel с атрибутом:
public class EnrollmentViewModel
{
[ListItemSelected(ErrorMessage = "Please select at least one Preference option.")]
public List<SelectListItem> Preferences { get; set; }
}
public class ListItemSelectedAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
if ((value as List<SelectListItem>).Count(x => x.Selected) == 0)
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
}
Я чувствую, что это много кода, но, надеюсь, большая его часть была необходима, чтобы объяснить мою проблему... Я сильно сократил ее. Скрипты jquery, проверки и ненавязчивые сценарии находятся в файле _Layout.cshtml. Большое спасибо!
ИЗМЕНИТЬ:
Я поставил точку останова в ViewComponent и в файлах Main View, и в обоих случаях на вкладке Locals ViewContext показывает, что ModelState недействителен, а ValidationMessageElement = span! Я думаю, это не то, что должно быть?? Я нашел сообщение, рекомендующее добавить ViewContext.FormContext = new FormContext(); вверху, но с ним или без него элементы FormContext одинаковы.
ModelState
? Там должны быть ошибки проверки, иначе хелпер тега не работает дляasp-validation-for
. Кстати, я немного сомневаюсь, что этоasp-for="@Model.Preferences[i].Selected"
отобразит соответствующее имяSelected
. Не могли бы вы проверить свою веб-страницу (используя инструмент инспектора браузера), чтобы увидеть, каковы фактические имена, сгенерированные для ваших входных данных? Однакоasp-validation-for
выглядит правильно. - person King King   schedule 12.03.2021ViewContext.FormContext = new FormContext();
вверху, но с ним или без него элементы FormContext на вкладке Locals одинаковы. - person Trevor   schedule 12.03.2021ModelState
глубоко в списке ошибок для каждогоModelStateEntry
, ModelState здесь - этоIReadOnlyDictionary<string,ModelStateEntry>
. - person King King   schedule 12.03.2021