MVC2 Клиентская Проверка для введенного содержания Ajax

Я выполняю вызов Ajax и добавляю содержание к форме в приложении MVC2. Я должен обновить Клиентские Метаданные Проверки с проверкой для моего нового содержания.

 <script type="text/javascript"> 
//<![CDATA[
if (!window.mvcClientValidationMetadata) { window.mvcClientValidationMetadata = []; }
window.mvcClientValidationMetadata.push({"Fields":[{"
...
</script>

Существует ли способ генерировать эти метаданные для частичного представления?

Заранее спасибо.

5
задан skaffman 21 May 2010 в 15:17
поделиться

5 ответов

Наконец-то заработало.

Ответ прост: не тратьте время на MicrosoftMvcValidation.js. Он генерируется с помощью Script#, что затрудняет его расширение.

Переходите на xVal и jQuery Validation. Ему не нужна форма для генерации метаданных клиентской валидации. Также для загрузки валидации для AJAX-запроса достаточно после создания нового Html вызвать следующее:

lForm.find("#placeholder").empty();                     
lForm.valid();
lForm.find("#placeholder").html(responseHtml);   

Вот и все. Сначала вы удаляете старое содержимое. Затем повторно запускаете валидацию, чтобы избавиться от потенциально устаревших ошибок валидации. Затем добавляете новое содержимое. Работает как чам.

Также jQuery Validation позволяет очень просто включить или отключить проверку для определенного поля (условная проверка).

2
ответ дан 14 December 2019 в 01:03
поделиться

Наконец нашел. После динамической загрузки содержимого вам нужно будет зарегистрировать новую форму.

Поскольку я использую Facebox, я добавил его в код facebox, однако вы можете добавить его где угодно или в обратном вызове, если ваш модальный или другой объект, в который вы загружаете, имеет событие afterLoaded.

Я заключил их в «try / catch» на всякий случай, если я когда-нибудь воспользуюсь фэйсбоксом без проверки.

Просто запустите эти две строки ПОСЛЕ загрузки вашего контента:

try {
        Sys.Application.remove_load(arguments.callee);
        Sys.Mvc.FormContext._Application_Load();
} catch (err) {/* MVC Clientside framework is likely not loaded*/ }
0
ответ дан 14 December 2019 в 01:03
поделиться

Я добился некоторых успехов, но не совсем счастлив.

Проблема №1: Метаданные проверки клиента не создаются, если у вас нет Html.BeginForm () в партиале. Что в моем случае неверно, потому что я не обновляю всю форму, я обновляю ее части.

Решение проблемы №1: Добавьте форму в частичное представление, позвольте MVC сгенерировать метаданные проверки клиента и удалить теги формы с помощью фильтра действий. Назовем это Хак №1 .

public class RemoveFormFilterAttribute : ActionFilterAttribute
{       

    private static readonly MethodInfo SwitchWriterMethod = typeof(HttpResponse).GetMethod("SwitchWriter", BindingFlags.Instance | BindingFlags.NonPublic);

    private TextWriter _OriginalWriter;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _OriginalWriter = (TextWriter)SwitchWriterMethod.Invoke(HttpContext.Current.Response, new object[] {new HtmlTextWriter(new StringWriter())});
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        if (_OriginalWriter != null)
        {
            HtmlTextWriter lTextWriter =(HtmlTextWriter) SwitchWriterMethod.Invoke(HttpContext.Current.Response, new object[] {_OriginalWriter});

            string lOriginalHTML = lTextWriter.InnerWriter.ToString();

            string lNewHTML =  RemoveFormTags(lOriginalHTML);

            filterContext.HttpContext.Response.Write(lNewHTML);
        }
    }

Проблема №2: Первоначальные метаданные проверки клиента для страницы исчезли к тому времени, когда я получил метаданные для нового содержимого.

Решение проблемы №2: Сохраните исходные метаданные (бумажную копию) и обновите их новыми данными, затем вызовите упомянутые вами методы, чтобы сообщить MVC о поступлении новых данных. Назовем это Хак №2.

<script type="text/javascript">

    var pageMvcClientValidationMetadata;

    $(document).ready(function() {

        $("input[name='PaymentTypeName']").change(PaymentTypeChanged);

        //create a back-up of the ValidationMetadata
        pageMvcClientValidationMetadata = JSON.parse(JSON.stringify(window.mvcClientValidationMetadata));
    });

    function PaymentTypeChanged() {

        var selectedPaymentType = $("input[name='PaymentTypeName']:checked").val();

        $.ajax(
            {
                url: 'PersonalData/GetPaymentTypeHtml?&paymentType=' + selectedPaymentType,
                type: "GET",
                cache: false,
                success: GetPaymentTypeHtml_Success
            });
    }

    function GetPaymentTypeHtml_Success(result) {

        $('#divPaymentTypeDetails').html(result);

        UpdateValidationMetaData();
    }

    function UpdateValidationMetaData() {

        //update the ValidationMetadata
        for (i = 0; i < window.mvcClientValidationMetadata[0].Fields.length; i++) {
            pageMvcClientValidationMetadata[0].Fields.push(window.mvcClientValidationMetadata[0].Fields[i]);
        }

        //restore the ValidationMetadata
        window.mvcClientValidationMetadata = JSON.parse(JSON.stringify(pageMvcClientValidationMetadata));

        //Notify the Validation Framework that new Metadata exists
        Sys.Application.remove_load(arguments.callee);          
        Sys.Mvc.FormContext._Application_Load();            
    }

Сейчас. Приветствуются любые улучшения.

Уловка №1: Как я могу сгенерировать метаданные проверки клиента, не имея фактической формы?

Хакер №2: Как я могу добавить к метаданным проверки страницы?

0
ответ дан 14 December 2019 в 01:03
поделиться

Я стучал своим уперся головой в стену в течение нескольких дней и собирался пойти по пути удаления тега формы, но только что заставил его работать немного менее хакерским способом, если вам все еще интересно. Мой сценарий был похож в том, что у меня есть форма с набором элементов для первоначальной проверки, но пользователи могут динамически добавлять новые строки через ajax.

Я разберу его, так что, надеюсь, вам будет легче увидеть, что происходит. Глядя на исходный код MVC, форма и проверка работают примерно так:

Html.BeginForm () выводит открывающий тег формы, затем создает и возвращает новый экземпляр MvcForm, который внешне мало что делает, кроме упростите управление областью формы. Однако он создает новый FormContext и сохраняет его в ViewContext.FormContext. Именно этот FormContext отслеживает проверку клиента.

Последнее, что делает Html.BeginForm (), - это устанавливает свойство FormId нового FormContext, используя идентификатор тега формы. Это необходимо для того, чтобы клиентский сценарий мог согласовывать формы и правила проверки.

Html.EndForm () удаляет MvcForm. Этот метод Dispose выводит закрывающий тег формы, а затем вызывает ViewContext.OutputClientValidation (), который отвечает за вывод javascript. Наконец, он удаляет текущий FormContext и возвращает его родительскому FormContext или null, если его нет.

Итак, чтобы не выводить тег формы, нам нужно каким-то образом убрать часть управления FormContext из конструктора / деструктора MvcForm.

Итак, в моем частичном представлении я сделал следующее:

Вверху я проверяю, имеет ли ViewContext.FormContext значение. Если это так, мы находимся в начальной загрузке, поэтому не нужно возиться. Если нет, это вызов ajax, поэтому я включаю проверку клиента, создаю новый MvcForm напрямую (, а не с BeginForm) - это вызывает создание FormContext - и устанавливаю FormContext.FormId таким же, как и моя родительская страница

В конце просмотра я проверяю, есть ли у меня экземпляр формы, и если да, вызываю ViewContext.OutputClientValidation () и сбрасываю ViewContext.FormContext на null. Я не использую Dispose () для MvcForm, так как это приведет к выводу закрывающего тега, а MvcForm не содержит одноразовых объектов.

Каркас представления выглядит следующим образом:

<%
MvcForm dummyForm = null;
if (this.ViewContext.FormContext == null)
{
    Html.EnableClientValidation();
    dummyForm = new MvcForm(this.ViewContext);
    this.ViewContext.FormContext.FormId = "mainform";
}
%>

// standard partial view markup goes here

<%
if (dummyForm != null)
{
    this.ViewContext.OutputClientValidation();
    this.ViewContext.FormContext = null;
}
%>

Вы можете легко обернуть это в метод расширения

Фил

6
ответ дан 14 December 2019 в 01:03
поделиться

У меня та же проблема, и ее можно решить с помощью файлов Future, а в MicrosoftMvcJQueryValidation.js я изменяю и файла, это:

$(document).ready(function () {
    var allFormOptions = window.mvcClientValidationMetadata;
    if (allFormOptions) {
        while (allFormOptions.length > 0) {
            var thisFormOptions = allFormOptions.pop();
            __MVC_EnableClientValidation(thisFormOptions);
        }
    }
});

для:

function chargeValidation() {
    var allFormOptions = window.mvcClientValidationMetadata;
    if (allFormOptions) {
        while (allFormOptions.length > 0) {
            var thisFormOptions = allFormOptions.pop();
            __MVC_EnableClientValidation(thisFormOptions);
        }
    }
}

и в содержимом после закрытия формы с помощью я вызываю 'chargeValidation ()', это решает для меня проблему, с которой я использую $ .get (action), содержащий проверку формы.

Надеюсь вам помочь!

1
ответ дан 14 December 2019 в 01:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: