MVC 3 Razor @ Html.ValidationMessage для не работающей частично загруженной через jquery.load () - PullRequest
14 голосов
/ 24 июня 2011

Я собрал небольшой пример, чтобы повторить проблему.У меня строго типизированное частичное представление _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 в представлении.

Ответы [ 3 ]

18 голосов
/ 17 ноября 2011

@ У NickBork отличный ответ. Ключевым моментом является то, что механизм рендеринга MVC ASP.NET не выводит сценарий проверки, если он не считает, что существует форма. Приведенный пример взламывает его, помещая в форму, а затем возвращая выделенный внутренний фрагмент HTML, по существу отбрасывая внешнюю оболочку формы.

Есть еще один способ, чтобы вы могли просто получить представление:

ViewContext.FormContext = new FormContext();

С помощью этого метода на самом деле не будет вывода кода FORM, но будет разметка проверки.

Спасибо, John

17 голосов
/ 18 июля 2011

Валидационная разметка (теги span, атрибуты пользовательских полей и т. Д.) Не отображается, если ваши поля не содержатся в FORM.Сам плагин проверки не работает с элементами вне формы.

Когда ASP.NET отображает ваш частичный вид, элементы управления не находятся внутри формы и, следовательно, не отображают элементы.

Когда вы загружаете частичное содержимое, вам нужно проанализировать HTML-код с помощью селектора jQuery.

В моем примере ниже у меня есть TBODY на родительской странице просмотра, содержащей строки.Когда мне нужно добавить дополнительные строки, я вызываю View, который имеет форму, таблицу, тело и коллекцию строк.

$.ajax({
    type: "POST",
    url: "/controller/action",
    data: ({Your: 'dataHere'}),
    dataType: "html",
    success:
        function(response){
            $('tbody').append($('tbody',$(response)).html());

            //The validation plugin can't bind to the same form twice.
            //We need to remove existing validators
            $('form').removeData("validator");

            //Refresh the validators
            $.validator.unobtrusive.parse(document);
        },
    error:
        function(){
            alert('An error occured while attempting to add the new content');
        }
});

Обратите внимание, что я использую селектор jQuery для выбора строккоторые находятся внутри View / PartialView, загруженного с использованием AJAX:

$('tbody',$(response)).html()

Остальная часть оболочки просто добавляет строки из AJAX View / PartialView к вызывающим родителям tbody:

$('tbody').append($('tbody',$(response)).html());

Несколько других замечаний: после запуска подключаемого модуля валидатора в форме его нельзя вызвать повторно без повторного добавления (см. jquery.validate.unobtrusive, не работающий с динамически внедренными элементами)

Чтобы исправить это, я сначала вызываю следующий метод для удаления всех валидаторов:

$('form').removeData("validator");
$("form").removeData("unobtrusiveValidation");

Затем я обновляю валидаторы, используя следующее:

$.validator.unobtrusive.parse(document);
1 голос
/ 25 июня 2011

Я не могу вспомнить, где я нашел решение.Причина в том, что вы загружаете PartialView в View, который уже был проанализирован библиотекой jquery.validator.unobtrusive.Вам нужно заново разобрать ненавязчивую библиотеку

    function ReparseValidation(){
       jQuery.validator.unobtrusive.parse("#yourcontainer");
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...