在创建不显示错误消息的部分视图的集合上使用FluentValidation

时间:2015-05-07 15:06:54

标签: javascript asp.net-mvc validation asp.net-mvc-4 fluentvalidation

我们目前在MVC项目中使用FluentValidation。我们需要能够创建一个动态视图,用户可以在其中添加或删除项目。这是使用partialviews完成的。



                <div id="LocationsContainer">
                    @foreach (var location in Model.Locations)
                    {
                        Html.RenderPartial("_Location", location);
                    }
                    @Html.ValidationMessageFor(m => m.Locations)
                    <br />
                </div>
&#13;
&#13;
&#13;

在局部视图中,我只有几个字段。

&#13;
&#13;
        ...
        <div class="float-box">
            <div class="label">
                @Html.LabelFor(m => m.PropertyAddress)
            </div>
            @Html.TextBoxFor(m => m.PropertyAddress)
            <br />
            @Html.ValidationMessageFor(m => m.PropertyAddress)
        </div>
        <div class="float-box">
            <div class="label">
                @Html.LabelFor(m => m.ApartmentNo)
            </div>
            @Html.TextBoxFor(m => m.ApartmentNo)
            <br />
            @Html.ValidationMessageFor(m => m.ApartmentNo)
        </div>
        ...
&#13;
&#13;
&#13;

在我的验证器中,我通过调用SetCollectionValidator

为Model.Locations(创建部分视图)设置验证器

&#13;
&#13;
RuleFor(vm => vm.Locations).SetCollectionValidator(new ServiceAddressViewModelValidator());
&#13;
&#13;
&#13;

在我调用ModelState.IsValid的控制器中,它似乎正在工作/验证。根据我的验证规则,我可以看到错误在我的局部视图中被捕获。我只是无法显示错误消息。在我的验证结果中,我可以看到错误消息,但没有应用于UI。我在这里做错了吗?我甚至尝试使用具有流畅验证的数据注释来处理除部分视图之外的其他事情,并且我得到了奇怪的行为。当fluentvalidation显示错误消息时,出现这种方法,然后数据注释错误消息没有显示,并且当显示数据注释错误消息时,它仅适用于第一部分视图。如果我有多个,那么它就不适用于其他视图。任何想法我怎么能让这个工作? (使用流畅的验证或数据注释)?

1 个答案:

答案 0 :(得分:1)

只有在实例化类时,才会验证类的属性。如果根本没有发布该类的数据,则modelbinder将不会实例化它。您的问题在于,当您发布数据时,您的表单字段名称不正确,因此模型绑定器不知道如何处理它们并丢弃信息。因此,您的集合项永远不会被实例化,并且永远不会运行验证。要解决您的问题,您需要使用for而不是foreach

@for (var i = 0; i < Model.Locations.Count(); i++)
{
    Html.RenderPartial("_Location", Model.Locations[i]);
}

或者,由于您所做的只是渲染部分,如果使用编辑器模板,您实际上可以采取捷径。首先创建视图Views\Shared\EditorTemplates\Location.cshtml。在该视图中,将当前部分视图的内容放在您用于位置的内容中。然后,您在主视图中需要的只是:

@Html.EditorFor(m => m.Locations)

Razor会看到你有Location类的编辑器模板(模板名称应该与类名匹配。如果它不是Location,请重命名模板以匹配。)和因为你有一个集合,它将为集合中的每个项目渲染该模板。