Razor MVC 5 ValidationMessage部分显示,但不在EditorFor模板中显示

Razor MVC 5 ValidationMessage部分显示,但不在EditorFor模板中显示,razor,asp.net-mvc-5,modelstate,viewdata,Razor,Asp.net Mvc 5,Modelstate,Viewdata,我有一个页面,它由其他页面组成,这些页面都是部分模板和编辑器模板。我在这两种情况下都正确显示了模板,但验证消息除外。当我使用@Html.partial(…)将下面显示的razor页面模板呈现为分部时,当我使用@Html.EditorFor(…)时,我会在每个字段旁边获得预期的验证消息(但表单数据不包括在呈现为分部的模板内的字段中)helper页面按预期呈现,字段值作为表单数据的一部分包含,但由于某些原因,验证消息未显示。它是完全相同的模板,只是使用了不同的html助手 Razor页面模板: @M

我有一个页面,它由其他页面组成,这些页面都是部分模板和编辑器模板。我在这两种情况下都正确显示了模板,但验证消息除外。当我使用@Html.partial(…)将下面显示的razor页面模板呈现为分部时,当我使用@Html.EditorFor(…)时,我会在每个字段旁边获得预期的验证消息(但表单数据不包括在呈现为分部的模板内的字段中)helper页面按预期呈现,字段值作为表单数据的一部分包含,但由于某些原因,验证消息未显示。它是完全相同的模板,只是使用了不同的html助手

Razor页面模板:

@ModelType PreferencesModel

@If Model.Preferences.Count > 0 Then
    @For Each kvp As KeyValuePair(Of String, Pref) In Model.Preferences
        @<div class="row">
            <div class="col-md-2">
                @Html.Label(Model.Preferences(kvp.Key).Name)
            </div>
            <div class="col-md-2">
                @If kvp.Value.IsReadOnly Then
                    @kvp.Value.CurrentValue
                Else
                    @Html.TextBoxFor(Function(m) m.Preferences(kvp.Key).CurrentValue)
                End If
            </div>
            <div class="col-md-2">
                @Html.ValidationMessage(kvp.Key)
            </div>
        </div>
    Next
End If
型号:

public class Pref
{
    public string Name { get; set; }
    public string CurrentValue { get; set; }
}

public class PreferencesModel
{
    public Dictionary<string, Pref> Preferences { get; set; }
}

public class EditPreferencesModel 
{
    public PreferencesModel PreferencesModel { get; set; }
}
如上所述,当将其渲染为部分时,模型错误将按预期显示,但当我将其渲染为EditorFor模板时,不会显示错误

在使用EditorFor时,我在模板上设置了一个断点,在检查ViewState时,我可以看到我希望在验证消息字段上看到的错误确实存在于ModelState中

我是否误用了EditorFor?
使用EditorFor识别每个字段的错误时,是否需要额外的步骤来获取模板?
这是EditorFor的预期行为吗?

不确定为什么它以前会起作用,但您的验证消息应该使用与您在
TextBoxFor
或其他任何内容中使用的属性lambda相同的属性。换言之:

@Html.ValidationMessageFor(Function(m) m.Preferences(kvp.Key).CurrentValue)

在花了好几个小时浏览各种资源寻找我的问题的答案后,我能找到的唯一答案是Html.ValidationMessage()助手功能根本不适用于编辑器模板。在我看来,这似乎是一个疏忽,因为我还没有看到或听到一个很好的理由,说明为什么它在这方面的行为会与Partial不同,特别是因为编辑器模板可以用于整个模型,而不仅仅是一个字段。因此,我似乎正确地使用了编辑器模板概念,这是迄今为止我发现的唯一一种将模板字段作为发布表单的一部分包含在内的方法

最终,我不得不通过手动检查是否存在并显示可用的错误消息来解决这个问题

因此,与通常的做法不同(使用部分但不使用编辑器):

我必须(与部分和编辑一起工作):


也许我遗漏了一些东西,但是您的
EditPreferencesModel
类没有属性
PreferencesModel
,因此当视图的模型是
EditPreferencesModel
并且您引用了
模型。PreferencesModel
时,您应该会得到一个运行时错误。不,我遗漏了该模型。很抱歉,我不得不从这个例子中去掉一些东西,并重命名一些项目,这样我就可以发布它,而忘记了包括那个模型。问题已更新。它与partials一起工作,因为我使用相同的键检索用于存储错误的错误。问题是为什么editorfortemplates不起作用,我试图用同样的方法从相同的结构中检索相同的错误。我同意,如果我使用decorators(不引人注目的验证)为我正在寻找输入的字段定义约束,我应该使用validationmessageforhelper,但由于这些字段是动态的,我不能使用decorators。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditPrefs(EditPreferencesModel model, string id)
{
    try
    {
        bool preferenceChangesAreValid = false;
        try {
            ValidatePreferenceChanges(model.PreferencesModel);
            preferenceChangesAreValid  = true;
        }
        catch(Exception e)
        {
            Logger.Error("Invalid preference information entered. Error: " + e.ToString());
        }

        if (preferenceChangesAreValid)
        {
            UpdatePreferencesFromViewModel(model.PreferencesModel);
            ... redirect to another view ...
        }

        model = PrepareEditPreferencesViewModel(model);
    }
    catch (Exception e)
    {
        Logger.Error("An unexpected error occurred. Error: " + e.ToString());
        ModelState.AddModelError("", "An error occurred with your request, please try again later.");
    }

    return View(model);
}


private void ValidatePreferenceChanges(PreferencesModel model)
{
    ... iterate preferences and validate ...

    if (preferenceIsInvalid)
        ModelState.AddModelError(kvp.Key, "Numeric value expected.");

    ...
}
@Html.ValidationMessageFor(Function(m) m.Preferences(kvp.Key).CurrentValue)
@Html.ValidationMessage(kvp.Key)
@If ViewData.ModelState.ContainsKey(kvp.Key) AndAlso ViewData.ModelState(kvp.Key).Errors.Count >= 1 Then
    @ViewData.ModelState(kvp.Key).Errors(0).ErrorMessage
End If