简体   繁体   English

在 Ajax 调用之后,MVC3 不显眼的验证不起作用

[英]MVC3 Unobtrusive Validation Not Working after Ajax Call

Ok, here is the deal, I have seen a few posts on SO relating to this issue, but nothing is working for me.好的,这是交易,我在 SO 上看到了一些与此问题相关的帖子,但没有什么对我有用。

Basically, I have select drop downs that are being loaded from partial views, I am trying to filter contents of each subsequent drop down, based on the previously selected drop down.基本上,我有从部分视图加载的 select 下拉列表,我正在尝试根据先前选择的下拉列表过滤每个后续下拉列表的内容。

If I just put the call to the partial view in the div containers, and load the page, the validation from data annotations works fine, primarily Required attribute .如果我只是将调用放在 div 容器中的局部视图并加载页面,则数据注释的验证工作正常,主要是 Required 属性

However, if I try to load the same partial via AJAX as it is setup here, the Required validation does not work, anyone can post the form after that and KABOOM.但是,如果我尝试通过 AJAX 加载相同的部分,因为它是在此处设置的,则必需的验证不起作用,任何人都可以在此之后发布表单和 KABOOM。

I have found people saying that in the Success callback you need to have the client side validator reparse the form, and I am trying that, but it doesn't seem to be working.我发现有人说,在 Success 回调中,您需要让客户端验证器重新解析表单,我正在尝试,但它似乎不起作用。

I have a view which looks like this...我有一个看起来像这样的视图......

  @model Area51.Models.Workflow.AddReportableItemToBatchActionModel
@{
    ViewBag.Title = "Add Reportable Item to Batch";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<script type="text/javascript">

    $(function () {
        var fadeDelay = 150;

        $(".jqDatePicker").datepicker({
            dateFormat: 'm/d/yy',
            onSelect: function (date) {
                $("#categoryContainer").show(fadeDelay);
            }
        });

        $('#Category').change(function () {
            RetrieveItemsForCategory();
            $("#itemContainer").show(100);
        });

        $('#Item').live('change', function () {
            RenderPartialForUOMByItem();           
        });



        function RetrieveItemsForCategory() {

            var category = $("#Category :selected").val();

            $.ajax({
                type: "POST",

                url: '@Url.Action("RenderPartialForLocationItemsByCategory","BatchWorkflow")',

                data: 'category=' + category,

                success: function (result) {
                    $("#itemContainer").html(result.toString());
                    $("#itemContainer").show(100);
                    RebindValidation();
                },

                error: function (req, status, error) {
                    alert("Sorry! Could not request items for your selection at this time.");
                }

            });


        }


        function RenderPartialForUOMByItem() {

            var item = $("#Item :selected").val();

            $.ajax({
                type: "POST",

                url: '@Url.Action("RenderPartialForUOMByItem","BatchWorkflow")',

                data: "item=" + item,

                success: function (result) {
                    $("#quantityContainer").html(result.toString());
                    $("#quantityContainer").show(100);
                    RebindValidation();
                },

                error: function (req, status, error) {
                    alert("Sorry! Could not request items for your selection at this time.");
                }

            });
        }

        function RebindValidation() {
            alert("Rebinding Validation");
            $.validator.unobtrusive.parse("#frmAddItem");
        }

    });      // End OnLoad Event
</script>

<h3 class="pageHeader">Batch : @Model.BatchName</h3>

<div align="center">

@{Html.BeginForm("AddItemToBatch", "BatchWorkflow", null, FormMethod.Post, new { id = "frmAddItem" });}

    @Html.ValidationSummary(true)

    <fieldset style="width:60%">
        <legend>Add an Item to the Batch</legend>     

     <div>       
          <h3>Select Date Item was Added</h3>
          @Html.EditorFor(x => x.EventDate,null)
          <br />
      </div>

      <div id="categoryContainer" style="display:none"> 
        <hr />
          <h3>Select an Inventory Category</h3>
          @Html.EditorFor(x => x.Category,null)
          <br />
      </div>

      <div id="itemContainer" style="display:none"> 
        @*   @{Html.RenderAction("RenderPartialForLocationItemsByCategory", "BatchWorkflow", new { category = Model.Category });}*@
      </div>


      <div id="quantityContainer" style="display:none"> 
        @*  @{Html.RenderAction("RenderPartialForUOMByItem", "BatchWorkflow", new { item = Model.Item });}*@
      </div>

      <div id="reportingDataContainer" style="display:none"> 
        <hr />
          <h3>What quantity of the batch was affected by this addition?</h3>
          @Html.EditorFor(x => x.ConsumedWineQuantity) (Gallons)
        <br />
        <hr />
          <h3>What was the increase in Batch Volume as a result of this addition?</h3>
          @Html.EditorFor(x => x.ProducedWineQuantity) (Gallons)
      </div>

        <div style="display:block">
        <div></div>        
            <span><button type="button" id="btnCancel" class="linkButton" value="Cancel" onclick="location.href='@Url.Action("Home","Home",null)';">Cancel</button></span>  
            <span><button type="submit" id="btnSubmit" class="linkButton" value="Add">Add Item</button></span>
        </div>


    </fieldset>
        @{ Html.EndForm(); }
</div>

The Partial Views are very simple, they basically look like this...部分视图非常简单,它们基本上看起来像这样......

@model Area51.Models.Workflow.AddReportableItemToBatchActionModel

      <hr />
          <h3>Select the Item to Add</h3>
          @Html.EditorFor(x => x.Item)
          <br />

Again, if I just RenderPartial, the validation works fine, however when I try to do it via ajax, the validation goes away.同样,如果我只是 RenderPartial,验证工作正常,但是当我尝试通过 ajax 进行验证时,验证就会消失。 The "Rebinding Validation" alert fires, but the $.validator.unobtrusive.parse("#frmAddItem"); “重新绑定验证”警报触发,但 $.validator.unobtrusive.parse("#frmAddItem"); doesn't seem to be doing a thing.似乎没有做任何事情。

Can anyone help with what I am missing?任何人都可以帮助我缺少什么吗? It would be greatly appreciated.这将不胜感激。

<======================= UPDATE 1 =============================> <========================更新1 ======================= =====>

OK, I tried adding the $.validator.unobtrusive.parse("#frmAddItem");好的,我尝试添加 $.validator.unobtrusive.parse("#frmAddItem"); at the bottom of the the partial view in a document ready event and it didn't seem to work either, basically nothing changed, I could still submit the form.在文档就绪事件的部分视图的底部,它似乎也不起作用,基本上没有任何改变,我仍然可以提交表单。

I did find a post here: http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/ that mentioned that when the MVC version of the jqvalidation sees a form already has validation rules bound to it, it just ignores the.validator call.我确实在这里找到了一个帖子: http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/提到当jqvalidation的MVC版本已经看到一个表单时绑定到它的验证规则,它只是忽略 .validator 调用。 I implemented the script extension that this gentleman used, and the validation is now rebinding to the form using the new extension.我实现了这位先生使用的脚本扩展,现在验证正在使用新的扩展重新绑定到表单。 I can test this by appending html to the form and calling the new extension, and it is rebinding to the new text box.我可以通过将 html 附加到表单并调用新扩展来测试它,它重新绑定到新文本框。

However, this still has not completely fixed the issue.但是,这仍然没有完全解决问题。 I used Firebug to check out the actual content on the fields coming back from the ajax call, and noticed something very strange.我使用 Firebug 检查了从 ajax 调用返回的字段的实际内容,并注意到一些非常奇怪的事情。

When I use the RenderPartial to call the action, it writes out the following select:当我使用 RenderPartial 调用操作时,它会写出以下 select:

<select id="Item" name="Item" data-val-required="The Item field is required." data-val-number="The field Item must be a number." data-val="true">

However, when I make the ajax call to the same exact controller action, it gives me this back:但是,当我对相同的 controller 操作进行 ajax 调用时,它给了我这个:

<select id="Item" name="Item">

I tried adding the script tags to the partial view as well, but it didn't fix the issue.我也尝试将脚本标签添加到局部视图,但它没有解决问题。 Is there some reason why the ajax call would be stripping the unobtrusive validation tags? ajax 调用会剥离不显眼的验证标签是否有某些原因?

<======================= UPDATE 2 =============================> <======================= 更新2 ======================== =====>

Ok, so what was happening, is I had an editor template for the drop down that took a select list and converted it to an html select.好的,所以发生了什么,我有一个下拉编辑器模板,它采用 select 列表并将其转换为 html select。 I found a post that mentioned that in order to get data validation attributes to write out on an editor template, you have to have a form context.我发现一篇文章提到,为了在编辑器模板上写出数据验证属性,你必须有一个表单上下文。 Since the Html.RenderPartial was being done within a form, then the editor template had a form context to work with.由于 Html.RenderPartial 是在表单中完成的,因此编辑器模板具有可以使用的表单上下文。 When I was just trying to call the partial via ajax, there was no form context to work with, and instead of complaining it just didn't write out the data validation attributes.当我试图通过 ajax 调用部分时,没有可以使用的表单上下文,而不是抱怨它只是没有写出数据验证属性。 Adding a new Form Context in the editor template for the SelectListDropDown fixed the issue.在 SelectListDropDown 的编辑器模板中添加新的表单上下文解决了这个问题。

@{ // fix to stop stupid crappy brad wilson mvc3 code from stripping the jq data valdiation attributes
    if (ViewContext.FormContext == null)
    {
        ViewContext.FormContext = new FormContext();
    }
}

$.validator.unobtrusive.parse("#frmAddItem"); will work.将工作。 Do note that it must be in the partial that you load through ajax (below the form in the partial)请注意,它必须在您通过 ajax 加载的部分中(在部分中的表格下方)

<form id="frmAddItem" method="POST" action="...">
    <!-- all the items -->
</form>
<script type="text/javascript">
    $.validator.unobtrusive.parse("#frmAddItem");
</script>

I'm adding my experience as the above recommendations did not work for me.我正在添加我的经验,因为上述建议对我不起作用。 This solution did and may help others that get directed to this page from a search engine:此解决方案确实并且可能会帮助从搜索引擎定向到此页面的其他人:

Add OnSuccess="$.validator.unobtrusive.parse('YourFormName');"添加OnSuccess="$.validator.unobtrusive.parse('YourFormName');" to you AjaxOptions给你 AjaxOptions

An example using Ajax.ActionLink:使用 Ajax.ActionLink 的示例:

@Ajax.ActionLink("This is a test to get unobtrusive javascript working",
                 "Name_of_your_controller_action",
                 new AjaxOptions { HttpMethod = "POST", 
                                   InsertionMode = InsertionMode.Replace, 
                                   UpdateTargetId = "UserDiv", 
                                   OnSuccess="$.validator.unobtrusive.parse('UserDetailsForm');"  
                                 }
                )

This solution was found at: http://blog.janjonas.net/2011-07-24/asp_net-mvc_3-ajax-form-jquery-validate-supporting-unobtrusive-client-side-validation-and-server-side-validation此解决方案位于: http://blog.janjonas.net/2011-07-24/asp_net-mvc_3-ajax-form-jquery-validate-supporting-unobtrusive-client-side-validation-and-server-side-验证

I wrote this little snippet that will you can place in your javascript file and it will handle all your forms that are ajax loaded.我写了这个小片段,你可以把它放在你的 javascript 文件中,它将处理你所有的 forms 加载的 ajax。

//enable unobtrusive validation for ajax loaded forms
$(document).ajaxSuccess(function (event, xhr, settings) {
    //process only if html was returned
    if ($.inArray('html', settings.dataTypes) >= 0) {
        //will parse the element with given id for unobtrusive validation
        function parseUnobtrusive(elementId) {
            if (elementId) {
                $.validator.unobtrusive.parse('#' + elementId);
            }
        }

        //get the form objects that were loaded.  Search within divs
        //in case the form is the root element in the string
        var forms = $('form', '<div>' + xhr.responseText + '</div>');

        //process each form retrieved by the ajax call
        $(forms).each(function () {
            //get the form id and trigger the parsing.
            //timout necessary for first time form loads to settle in
            var formId = this.id;
            setTimeout(function () { parseUnobtrusive(formId); }, 100);
        });
    }
});

Another option, rather trick, which worked for me.另一种选择,相当技巧,对我有用。 Just add following line in the beginning of the partial view which is being returned by ajax call只需在 ajax 调用返回的部分视图的开头添加以下行

this.ViewContext.FormContext = new FormContext(); 

Reference 参考

I could only get it the validation to work inside of OnComplete instead of OnSuccess :我只能让它在OnComplete而不是OnSuccess内部工作的验证:

Here's the AJAX Code:这是 AJAX 代码:

@using (Ajax.BeginForm("Index", null, 
                       new AjaxOptions { OnSuccess = "onSuccess", 
                                         OnComplete = "onComplete"}, 
                       new { id = "mainForm" }))

And here's my script:这是我的脚本:

function onComplete(result) {
    $.validator.unobtrusive.parse("#mainForm");
    alert("Complete");
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM