Asp.net mvc 2 为什么';t ValidationMessage是否在此实例中显示我的验证消息?

Asp.net mvc 2 为什么';t ValidationMessage是否在此实例中显示我的验证消息?,asp.net-mvc-2,validation,partial-views,Asp.net Mvc 2,Validation,Partial Views,我有一个视图模型,它包含一个类的5个实例作为子属性。这些子特性使用局部视图渲染,如下所示: <%Html.RenderPartial("_EntryItemForm", Model.EntryItem1, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem1" } }); %> <%Html.RenderPar

我有一个视图模型,它包含一个类的5个实例作为子属性。这些子特性使用局部视图渲染,如下所示:

<%Html.RenderPartial("_EntryItemForm", Model.EntryItem1, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem1" } }); %>        
<%Html.RenderPartial("_EntryItemForm", Model.EntryItem2, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem2" } }); %>
<%Html.RenderPartial("_EntryItemForm", Model.EntryItem3, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem3" } }); %>
<%Html.RenderPartial("_EntryItemForm", Model.EntryItem4, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem4" } }); %>
<%Html.RenderPartial("_EntryItemForm", Model.EntryItem5, new ViewDataDictionary { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem5" } }); %>

在局部视图中,我有以下内容(仅显示一个字段):

x.ItemName)%%>
x、 ItemName)%%>
x、 ItemName)%%>
标签和文本框都使用正确的ID、名称等进行渲染,默认的模型绑定器可以完美地处理所有内容

不幸的是,即使ModelState包含ItemName字段的错误,ValidationMessage也不会出现。如果向父视图添加ValidationSummary,则会显示错误。通常我只会使用ValidationSummary并继续,但我正在进行的设计需要内联验证消息


有人知道这是为什么吗?

可能元数据中包含验证错误的字段的名称与
文本框为
助手生成的字段名称不匹配。使用编辑器模板怎么样?这样,您就不需要为前缀、设置模板信息、验证问题等烦恼了

所以您可以定义(
~/Views/Shared/EditorTemplates/TypeOfEntryItem.ascx
):


x、 ItemName)%%>
x、 ItemName)%%>
x、 ItemName)%%>
主要观点是:

<% using (Html.BeginForm()) { %>
    <%= Html.EditorFor(x => x.EntryItem1) %>
    <%= Html.EditorFor(x => x.EntryItem2) %>
    <%= Html.EditorFor(x => x.EntryItem3) %>
    <%= Html.EditorFor(x => x.EntryItem4) %>
    <%= Html.EditorFor(x => x.EntryItem5) %>

    <input type="submit" value="OK" />
<% } %>

x、 EntryItem1)%%>
x、 EntryItem2)%>
x、 EntryItem3)%>
x、 入口项4)%>
x、 入口项目5)%>
如果您不想麻烦在模型上创建5个属性,这甚至可以用于集合。您可以有一个简单的属性:

public IEnumerable<TypeOfEntryItem> EntryItems { get; set; }
public IEnumerable EntryItems{get;set;}
然后:

<% using (Html.BeginForm()) { %>
    <%= Html.EditorFor(x => x.EntryItems) %>
    <input type="submit" value="OK" />
<% } %>

x、 入口项)%>
这将为集合中的每个项目呈现编辑器模板,当然还要生成正确的ID、名称等

关于IEnumerable的最后一个问题,请查看上面的文章,以获得一个不错的解决方法。另外,我希望有人能回答你关于使用htmlFieldPrefix工作的问题。。。“优雅”与否,如果您不能支持验证消息,那么支持视图的显示/呈现/处理就没有意义了。我正在尝试让EditorFor也为我工作(现在),但如果我有时间,回到RenderPartial,我会回到这里发布解决方案


对于那些可能通过谷歌搜索问题找到解决方法的人来说,原因是ModelState包含“ComplexObjectProperty.ModelProperty”之类的键,但ValidationMessageFor只尝试查找“ModelProperty”。重大疏忽。

对于在谷歌上搜索此问题的人:

当使用HtmlFieldPrefix时,ModelState不能以正确的方式传递到局部视图,这是由于该原因导致的问题。此html帮助程序解决了问题(对我而言),验证错误显示正确:

public static void RenderPartialWithPrefix(this HtmlHelper helper, string partialViewName, object model, string prefix)
    {
        ViewDataDictionary WDD = new ViewDataDictionary {TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = prefix } };

        foreach(string key in helper.ViewData.ModelState.Keys)
        {
            if(key.StartsWith(prefix+"."))
            {
                foreach (ModelError err in helper.ViewData.ModelState[key].Errors)
                {
                  if(!string.IsNullOrEmpty(err.ErrorMessage))
                    WDD.ModelState.AddModelError(key, err.ErrorMessage);
                  if (err.Exception != null)
                      WDD.ModelState.AddModelError(key, err.Exception);
                }
                WDD.ModelState.SetModelValue(key, helper.ViewData.ModelState[key].Value);
            }
        }

        helper.RenderPartial(partialViewName,model,WDD);
    }
只需使用它来渲染带有前缀的局部视图

@{Html.RenderPartialWithPrefix("_StructureEditSharePartView", Model.sharePart,"sharePart");}

将Html.ViewData对象添加到ViewDataDictionary的构造函数中也可以

<%Html.RenderPartial("_EntryItemForm", Model.EntryItem1, new ViewDataDictionary(Html.ViewData) { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem1" } }); %>


这样做的目的是,它为新创建的ViewDataDictionary提供当前上下文(包括ModelState),而不是为其提供单独的上下文。这样,就不需要扩展方法。

谢谢您的建议。我尝试按照您的说明使用EditorFor,但完全没有得到任何结果:没有错误,也没有输出!你知道是什么原因吗?@Paul Suart,编辑器模板的名称和位置很重要。它必须位于
~/Views/Shared/EditorTemplates
文件夹中,并命名为
XXX.ascx
,其中
XXX
是强类型的类型名称。这一定是属性
EntryItem1
的类型。嗯,我得到了editor(这是我自己的错,因为我没有意识到它输出了一个MvcHtmlString而不是写入响应),但仍然没有乐趣。已更新问题。更正-抱歉,EditorFor工作正常。然而,如果我试图呈现IEnumerable,则它不起作用——抛出一个参数异常“路径中的非法字符”。我想我不需要将我的视图重命名为“IEnumerable”!我也有点困惑,为什么我的第一个(不那么优雅的)解决方案不能正常工作。所以我必须使用UIHint?对我来说就像是精灵的魔法!我也得出结论,ValidationMessageFor无法在ModelState中查找正确的密钥。这是一个巨大的帮助,谢谢!我还为Partial创建了一个名为PartialWithPrefix的版本,该版本最后调用helper.Partial(而不是helper.RenderPartial),并返回MvcHtmlString。对于我的Partial是列表且html中有[0]索引的情况,我必须添加另一个条件。if(key.StartsWith(prefix+“[”)这里是modelstate命令中的我的密钥。PSoftAccessRequirements.PSoftAccountsPayable.VoucherApprovalMatrix[0].LEVELValidation prefix=Command.PSoftAccessRequirements.PSoftAccountsPayable.voucherApprovalMatrix这是一个救命稻草,谢谢!这应该是一个可接受的answser。确保“prefix”的大小写与ModelState.Keys匹配。我使用ToLowerInvariant()检查键是否以前缀开头。
@{Html.RenderPartialWithPrefix("_StructureEditSharePartView", Model.sharePart,"sharePart");}
<%Html.RenderPartial("_EntryItemForm", Model.EntryItem1, new ViewDataDictionary(Html.ViewData) { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "EntryItem1" } }); %>