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

本文关键字:验证 不起作用 不显眼 MVC3 调用 Ajax | 更新日期: 2023-09-27 18:05:33

好吧,这里是交易,我已经看到了一些关于这个问题的帖子,但没有一个对我有用。

基本上,我有从部分视图加载的选择下拉菜单,我试图过滤每个后续下拉菜单的内容,基于先前选择的下拉菜单。

如果我只是把对div容器中部分视图的调用,并加载页面,则来自数据注释的验证工作得很好,主要是必需属性

但是,如果我试图通过AJAX加载相同的部分,因为它是在这里设置的,所需的验证不起作用,任何人都可以在此之后发布表单和KABOOM。

我发现人们说,在成功回调中,你需要让客户端验证器重新解析表单,我正在尝试,但它似乎不工作。

我有一个视图,它看起来像这样…

  @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>

局部视图非常简单,它们基本上是这样的…

@model Area51.Models.Workflow.AddReportableItemToBatchActionModel
      <hr />
          <h3>Select the Item to Add</h3>
          @Html.EditorFor(x => x.Item)
          <br />

再次,如果我只是RenderPartial,验证工作得很好,然而,当我试图通过ajax,验证消失了。"Rebinding Validation"警报会触发,但是$.validator. unobtrusiative .parse("#frmAddItem");好像什么也没做。

有谁可以帮助我错过了什么?我将不胜感激。

& lt ;======================= 更新1 =============================>

OK,我尝试添加$.validator. unobtrusiative .parse("#frmAddItem");在文档准备事件的部分视图的底部,它似乎也没有工作,基本上没有改变,我仍然可以提交表单。

我确实在这里找到了一篇文章:http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/提到,当jqvalidation的MVC版本看到表单已经绑定了验证规则时,它会忽略.validator调用。我实现了这位先生使用的脚本扩展,并且现在使用新扩展将验证重新绑定到表单。我可以通过将html附加到表单并调用新的扩展来测试这一点,并且它重新绑定到新的文本框。

然而,这仍然没有完全解决问题。我使用Firebug检查从ajax调用返回的字段上的实际内容,并注意到一些非常奇怪的事情。

当我使用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">

然而,当我对相同的控制器动作进行ajax调用时,它返回给我:

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

我尝试添加脚本标签的部分视图,以及,但它没有解决这个问题。ajax调用会剥离不显眼的验证标记,这其中有什么原因吗?

& lt ;======================= 更新2 =============================>

好的,发生的是,我有一个下拉列表的编辑器模板,它接受一个选择列表并将其转换为html选择。我发现一篇文章提到,为了让数据验证属性写在编辑器模板上,你必须有一个表单上下文。自从Html。RenderPartial是在一个表单中完成的,然后编辑器模板有一个表单上下文来处理。当我只是试图通过ajax调用部分时,没有表单上下文可以使用,而不是抱怨它只是没有写出数据验证属性。在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();
    }
}

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

$.validator.unobtrusive.parse("#frmAddItem");将工作。请注意,它必须在您通过ajax加载的部分中(在部分的表单下面)

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

我添加了我的经验,因为上面的建议对我不起作用。这个解决方案已经并且可能会帮助其他人从搜索引擎定向到这个页面:

添加OnSuccess="$.validator.unobtrusive.parse('YourFormName');"到AjaxOptions

使用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');"  
                                 }
                )

此解决方案发现于:http://blog.janjonas.net/2011-07-24/asp_net-mvc_3-ajax-form-jquery-validate-supporting-unobtrusive-client-side-validation-and-server-side-validation

我写了这个小片段,你可以把它放在你的javascript文件中,它将处理所有的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);
        });
    }
});

另一个选择,相当狡猾,对我来说很有效。只需在ajax调用

返回的部分视图的开头添加以下行
this.ViewContext.FormContext = new FormContext(); 
参考

我只能让它的验证工作在OnComplete而不是OnSuccess:

这是AJAX代码:

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

下面是我的脚本:

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