【问题标题】:MVC 3 Razor @Html.ValidationMessageFor not working in partial loaded via jquery.load()MVC 3 Razor @Html.ValidationMessageFor 无法通过 jquery.load() 部分加载
【发布时间】:2011-06-24 09:20:18
【问题描述】:

我在这里整理了一个小例子来复制这个问题。 我有一个强类型的局部视图_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 中的 Required 属性实现验证

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 中的 Required 属性内的验证消息,我们需要修改视图中的这段硬编码的 html。

【问题讨论】:

    标签: validation asp.net-mvc-3 razor partial csh


    【解决方案1】:

    @NickBork 在这里有一个很好的答案。关键是ASP.NET的MVC渲染引擎如果认为没有表单,就不输出验证脚本。给出的示例给出了它购买的 hacks 放入一个表单,然后从中选择 HTML 的内部部分被返回,基本上丢弃了表单的外部包装。

    还有另一种方法可以让你得到你的看法:

    ViewContext.FormContext = new FormContext();
    

    使用此方法,实际上不会有FORM代码输出,但会有验证标记。

    谢谢, 约翰

    【讨论】:

    • 我在局部视图的顶部添加了这一行,它解决了这个问题。最后就这么简单。谢谢一百万。
    • 在某些情况下,添加开发人员指出的行不起作用,例如使用 AJAX 获取部分视图。发生这种情况的原因是 AJAX 调用不会触发验证插件“重新绑定”到页面上的表单,这是不应该的。在这些情况下,有必要调用 $.validator.unobtrusive.parse('#myPartialViewForm');方法。在我的情况下,当用户单击“添加”按钮时,我使用 Fancybox 呈现表单。我的部分观点称为“$.validator.unobtrusive.parse('#wizardForm');”配置部分视图的验证。
    • 这绝对是正确的答案。其他人正在使用 JQuery 和 AJAX(解析和重新绑定)解决一个不同的问题,这也是必需的,但不会单独帮助。问题在于 MVC,并且没有它认为有一个表单包含部分视图中的元素通过 AJAX 返回
    • 仅供参考,您将这行代码添加到部分视图 cshtml 顶部的某处:@{ ViewContext.FormContext = new FormContext(); }
    • 但就我而言,我已经在局部视图中使用 @Html.BeginForm() 并遇到了同样的问题。给定的解决方案也不起作用。
    【解决方案2】:

    除非您的字段包含在 FORM 中,否则不会呈现验证标记(跨度标记、自定义字段属性等)。验证插件本身不适用于表单之外的元素。

    当 ASP.NET 呈现部分视图时,控件不在表单内,因此不会呈现元素。

    当您加载部分内容时,您需要使用 jQuery 选择器解析 HTML。

    在下面的示例中,我在包含行的父视图页面上有一个 TBODY。当我需要添加额外的行时,我会调用一个 View,它有一个表单、表格、tbody 和行集合。

    $.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 选择器来选择使用 AJAX 加载的 View/PartialView 内部的行:

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

    包装器的其余部分只是将 AJAX 视图/PartialView 中的行附加到调用父级tbody:

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

    另外一些注意事项,验证器插件在表单上运行后,如果不重新添加它就不能再次调用它(参见jquery.validate.unobtrusive not working with dynamic injected elements)

    为了解决这个问题,我首先调用以下方法来删除所有验证器:

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

    然后我使用以下内容刷新验证器:

    $.validator.unobtrusive.parse(document);
    

    【讨论】:

      【解决方案3】:

      我不记得在哪里找到了解决方案。原因是因为您正在将 PartialView 加载到已经被 jquery.validator.unobtrusive 库解析的 View 中。你需要重新解析不显眼的库

          function ReparseValidation(){
             jQuery.validator.unobtrusive.parse("#yourcontainer");
          }
      

      【讨论】:

      • 我很害怕,但我已经尝试过了,但它对我不起作用。问题不是重新验证页面,而是 @Html.ValidationMessageFor 不呈现验证消息,即上面示例中的 标记。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 2021-08-13
      • 2011-10-12
      • 2011-05-08
      • 2018-12-19
      • 1970-01-01
      相关资源
      最近更新 更多