Я собрал здесь небольшой пример, чтобы воспроизвести проблему. У меня есть строго типизированное частичное представление _Name.cshtml:
@model ValidationInPartial.ViewModels.MyViewModel
<h2>@ViewBag.Message</h2>
<fieldset>
<legend>Name</legend>
<div class="editor-label">
@Html.LabelFor(model => model.MyName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.MyName)
@Html.ValidationMessageFor(model => model.MyName)
</div>
<a href="#" id="reload">Reload Name</a>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<script type="text/javascript">
$(document).ready(function () {
$("#reload").click(function () {
$("#divName").load("Home/NameReload");
});
});
</script>
который изначально загружается и отображается внутри основного Index.cshtml
<div id="divForm">
@using (Html.BeginForm()) {
<div id="divName">
@Html.Partial("_Name")
</div>
}
</div>
Поле MyName требуется, а проверка выполняется с помощью атрибута Обязательный в MyViewModel
namespace ValidationInPartial.ViewModels
{
public class MyViewModel
{
[Required(ErrorMessage = "Please enter a Name.")]
public string MyName { get; set; }
}
}
После того, как страница будет загружена в первый раз, если вы нажмете кнопку "Создать", оставив поле пустым, появится сообщение "Пожалуйста, введите имя". показывает рядом с полем, и само поле становится розовым, что является ожидаемым поведением. Теперь, щелкнув ссылку "Обновить имя", которая делает вызов ajax (jquery.load(...)), частичная перезагрузка, вот код контроллера:
public PartialViewResult NameReload()
{
MyViewModel myViewModel = new MyViewModel();
ViewBag.Message = "Name Reloaded";
return PartialView("_Name", myViewModel);
}
На этот раз, если вы нажмете кнопку "Создать", оставив поле пустым, сообщение подтверждения не появится рядом с полем, хотя поле становится розовым. Оказывается, при перезагрузке частичного @Html.ValidationMessageFor не отображает сообщение проверки как первый раз.
Вот файлы jquery, которые я использую
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
Интересно, является ли это ошибкой в том, как движок Razor отображает @Html.ValidationMessageFor или это проблема с jquery? Любая идея, почему это происходит?
Я также где-то читал, что вызов ajax теряет все скрипты для страницы, на самом деле мне нужно сохранить код javascript внутри частичного, чтобы они могли быть отображены и использованы снова.
В то же время я нашел обходное решение, которое нужно вручную отобразить в частичном, что должно было отображаться с помощью @Html.ValidationMessageFor, который:
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="MyName"></span>
Однако это обходное решение означает, что, если мы изменим тип проверки или просто сообщение проверки внутри атрибута Required в ViewModel, нам нужно изменить этот жесткий код html в представлении.