Я собрал здесь небольшой пример, чтобы воспроизвести проблему. У меня есть строго типизированное частичное представление _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 является обязательным, и проверка осуществляется с помощью атрибута Required в 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>
Однако этот обходной путь означает, что если мы изменим тип проверки или просто сообщение проверки внутри обязательного атрибута в ViewModel, нам нужно изменить этот жестко запрограммированный фрагмент html в представлении.