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

时间:2011-06-24 09:20:19

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

我在这里放了一个小例子来复制问题。 我有一个强类型的局部视图_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片段。

3 个答案:

答案 0 :(得分:18)

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

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

ViewContext.FormContext = new FormContext();

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

谢谢, 约翰

答案 1 :(得分: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');
        }
});

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

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

包装器的其余部分只是将AJAX View / 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);

答案 2 :(得分:1)

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

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