MVC 5 ValidationMessage 显示在 Partial 但不显示在 EditorFor 模板中

MVC 5 ValidationMessage displays in Partial but not in EditorFor template

我有一个页面由其他页面组成,这些页面既是局部页面又是编辑器模板。除了验证消息外,我在这两种情况下都正确显示了模板。当我使用 @Html.Partial(...) 将下面显示的剃刀页面模板呈现为部分时,我在每个字段旁边得到预期的验证消息(但表单数据不包含在呈现为的模板中的字段中a Partial) 当我使用 @Html.EditorFor(...) 助手时,页面按预期呈现,字段值作为表单数据的一部分包含在内,但由于某种原因,验证消息未显示。它是完全相同的模板,只是使用了不同的 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

Razor 父页面:

@ModelType EditPreferencesModel

@Using Html.BeginForm("EditPrefs", "PrefsController", FormMethod.Post, New With {.id = "updatePrefs", .class = "form-horizontal", .role = "form"})
    @Html.AntiForgeryToken

    @If Not Model.PreferencesModel Is Nothing Then
        @Html.EditorFor(Function(m) m.PreferencesModel) 
        @*@Html.Partial("~/Views/Prefs/EditorTemplates/Pref.vbhtml", Model.PreferencesModel)*@
    End If

End Using

型号:

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; }
}

PrefsController 操作:

[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.");

    ...
}

正如我上面提到的,将其渲染为局部时,模型错误会按预期显示,但是当我将其渲染为 EditorFor 模板时,不会显示错误。

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

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

不确定为什么它以前会起作用,但您的验证消息应该使用与您用于 TextBoxFor 或其他任何东西相同的 属性 lambda。换句话说:

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

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

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

所以不是通常的(使用部分而不是编辑器):

@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