You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET5中如何让ValidationSummary仅显示对应分部视图的验证错误

问题根因

原生asp-validation-summary标签助手默认遍历ModelState字典存储的全量验证错误,不会自动根据当前分部视图绑定的模型层级过滤错误;你当前渲染分部时传入的是全新空ViewDataDictionary,没有携带当前子模型对应的属性路径前缀(HtmlFieldPrefix),最终导致所有分部的验证汇总区域都会展示全页面的所有错误。

实现方案

方案1:自定义支持前缀过滤的ValidationSummary标签助手(推荐,适配多层嵌套分部场景)

该方案可以自动识别当前视图的HtmlFieldPrefix,仅展示前缀匹配的验证错误,完全适配动态渲染、多层分部嵌套的业务场景。

  1. 编写自定义标签助手代码:
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Linq;

[HtmlTargetElement("div", Attributes = "asp-partial-validation-summary")]
public class PartialValidationSummaryTagHelper : ValidationSummaryTagHelper
{
    public PartialValidationSummaryTagHelper(IHtmlGenerator generator) : base(generator)
    {
    }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        var currentPrefix = ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix;
        if (!string.IsNullOrEmpty(currentPrefix))
        {
            // 筛选当前前缀下的所有验证错误
            var matchedKeys = ViewContext.ModelState.Keys
                .Where(k => k.StartsWith(currentPrefix) || k == string.Empty)
                .ToList();
            var originalModelState = ViewContext.ModelState;
            var filteredModelState = new ModelStateDictionary();
            foreach (var key in matchedKeys)
            {
                foreach (var err in originalModelState[key].Errors)
                {
                    filteredModelState.AddModelError(key, err.ErrorMessage);
                }
            }
            // 用过滤后的ModelState执行原生汇总逻辑,执行完还原原始状态避免影响其他组件
            ViewContext.ModelState = filteredModelState;
            base.Process(context, output);
            ViewContext.ModelState = originalModelState;
        }
        else
        {
            base.Process(context, output);
        }
    }
}
  1. 在_ViewImports.cshtml中注册自定义标签助手:
@addTagHelper *, 你的项目程序集名称
  1. 修正主视图渲染分部的逻辑,给每个分部传入带正确属性前缀的ViewData,不要传空的ViewDataDictionary:
@model Customer

<div class="row">
    <div class="table-responsive pl-1">
    @{
        var addressViewData = new ViewDataDictionary(ViewData);
        // 给Address分部设置对应模型前缀
        addressViewData.TemplateInfo.HtmlFieldPrefix = nameof(Model.Address);
        await Html.RenderPartialAsync("_Address", Model.Address, addressViewData);
    }
    </div>
    <div class="table-responsive pl-1">
    @{
        var historyViewData = new ViewDataDictionary(ViewData);
        // 给History分部设置对应模型前缀
        historyViewData.TemplateInfo.HtmlFieldPrefix = nameof(Model.History);
        await Html.RenderPartialAsync("_History", Model.History, historyViewData);
    }
    </div>
</div>
  1. 将分部视图中原生的asp-validation-summary替换为自定义标签即可,参数用法和原生完全一致:传All显示所有匹配错误,传ModelOnly仅显示模型级错误,传None不显示。示例:
<div class="text-danger" asp-partial-validation-summary="All">
</div>

注意:你提供的示例代码中asp-validation-for存在笔误,City、ZipCode、History板块下的验证指向都写了StreetAddress,需修正为对应属性名,否则字段级行内提示会异常。

方案2:不自定义组件,手动遍历匹配错误渲染汇总

如果不想引入自定义标签助手,可以直接在分部视图中手动拉取当前前缀下的错误渲染汇总,同样需要先按照方案1的步骤给分部设置正确的HtmlFieldPrefix,示例代码:

<div class="text-danger">
    <ul>
    @foreach (var error in ViewContext.ModelState
        .Where(kv => kv.Key.StartsWith(ViewData.TemplateInfo.HtmlFieldPrefix))
        .SelectMany(kv => kv.Value.Errors))
    {
        <li>@error.ErrorMessage</li>
    }
    </ul>
</div>
嵌套分部适配说明

如果分部视图内部需要继续嵌套下一级分部,只需要在渲染下级分部时,在当前前缀基础上拼接下一级模型的属性名作为新的HtmlFieldPrefix即可,例如Address板块内嵌套邮编子分部,前缀设为$"{ViewData.TemplateInfo.HtmlFieldPrefix}.{nameof(Model.ZipCode)}",自定义标签助手会自动识别当前层级前缀做过滤,无需额外修改逻辑。

内容的提问来源于stack exchange,提问作者flyingniner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 02:27:31