MVC 3 Razor @ Html.ValidationMessage不能通过jquery.load()部分加载

Rob*_*o D 14 validation csh partial razor asp.net-mvc-3

我在这里放了一个小例子来复制问题.我有一个强类型的局部视图_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>
Run Code Online (Sandbox Code Playgroud)

最初加载并显示在主Index.cshtml中

<div id="divForm">
    @using (Html.BeginForm()) {

        <div id="divName">
            @Html.Partial("_Name")
        </div>
    }
</div>
Run Code Online (Sandbox Code Playgroud)

MyName字段是必需的,验证是通过MyViewModel中的Required属性实现的

namespace ValidationInPartial.ViewModels
{
    public class MyViewModel
    {
        [Required(ErrorMessage = "Please enter a Name.")]
        public string MyName { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

第一次加载页面后,如果单击"创建"按钮,则该字段将清空验证消息"请输入名称".显示在田野旁边,田地本身变成粉红色,这是预期的行为.现在通过单击"重新加载名称"链接,进行ajax调用(jquery.load(...)),重新加载部分,这里是控制器代码:

public PartialViewResult NameReload()
{
    MyViewModel myViewModel = new MyViewModel();
    ViewBag.Message = "Name Reloaded";
    return PartialView("_Name", myViewModel);
}
Run Code Online (Sandbox Code Playgroud)

这次,如果单击"创建"按钮使该字段为空,则验证消息不会出现在该字段旁边,尽管该字段变为粉红色.事实证明,当重新加载部分时,@ 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>
Run Code Online (Sandbox Code Playgroud)

我想知道这是Razor引擎呈现@ Html.ValidationMessageFor的方式中的错误还是jquery的问题?知道为什么会这样吗?

我还读过某个地方,ajax调用丢失了页面的所有脚本,实际上我必须在部分内部保留任何javascript代码,以便可以再次渲染和使用它们.

与此同时,我找到了一种解决方法,即在部分中手动渲染应该由@ Html.ValidationMessageFor呈现的内容,即:

<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="MyName"></span>
Run Code Online (Sandbox Code Playgroud)

但是,这种解决方法意味着如果我们在ViewModel中的Required属性中更改验证类型或仅更改验证消息,我们需要在视图中修改此硬编码的html片段.

Joh*_*ger 18

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

还有另一种方法,您可以获得您的观点:

ViewContext.FormContext = new FormContext();
Run Code Online (Sandbox Code Playgroud)

使用此方法,实际上不会有FORM代码输出,但验证标记将在那里.

谢谢,约翰

  • 有些情况下,添加开发人员注意到的行将无法正常工作,例如使用AJAX获取局部视图.发生这种情况的原因是AJAX调用不会触发validate插件"重新绑定"到页面上的表单,它不应该.在这些情况下,有必要调用$ .validator.unobtrusive.parse('#myPartialViewForm'); 方法.在我的情况下,当用户点击"添加"按钮时,我正在使用Fancybox渲染表单.我的部分视图称为"$ .validator.unobtrusive.parse('#wizardForm');" 配置部分视图的验证. (2认同)

Nic*_*ork 17

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

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

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

在下面的示例中,我在包含行的父视图页面上有一个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');
        }
});
Run Code Online (Sandbox Code Playgroud)

请注意,我正在使用jQuery选择器来选择使用AJAX加载的View/PartialView内部的行:

$('tbody',$(response)).html()
Run Code Online (Sandbox Code Playgroud)

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

$('tbody').append($('tbody',$(response)).html());
Run Code Online (Sandbox Code Playgroud)

在其他注释之后,在表单上运行验证器插件之后,如果不重新添加它就无法再次调用它(请参阅jquery.validate.unobtrusive不使用动态注入元素)

要解决此问题,我首先调用以下方法来删除所有验证器:

$('form').removeData("validator");
$("form").removeData("unobtrusiveValidation");
Run Code Online (Sandbox Code Playgroud)

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

$.validator.unobtrusive.parse(document);
Run Code Online (Sandbox Code Playgroud)