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

Razor Pages自定义TagHelper无法显示服务器端验证错误求助

问题原因

自定义的text-required-field标签助手在构建验证span时,没有主动读取ModelState中的错误信息并填充到span内容里。原生的asp-validation-for标签助手会自动完成这一步:它会从当前ViewContext的ModelState中查找对应字段的错误,然后将错误文本插入到span中,同时管理显示/隐藏的样式类。

解决方案

修改自定义TagHelper,注入ViewContext以访问ModelState,手动获取并填充验证错误信息,同时完善验证span的样式逻辑。

修改后的TagHelper代码

[HtmlTargetElement(tag: "text-required-field")]
public class StringRequiredFieldHelper : TagHelper
{
    // 注入ViewContext,用于访问ModelState
    [ViewContext]
    public ViewContext? ViewContext { get; set; }

    [HtmlAttributeName("asp-for")]
    public ModelExpression? For { get; set; }
    
    [HtmlAttributeName("asp-validation-for")]
    public ModelExpression? Validation { get; set; }
    
    [HtmlAttributeName("label-for")]
    public string? LabelName { get; set; }

    // 可选:支持自定义容器类
    [HtmlAttributeName("container-class")]
    public string? ContainerClass { get; set; } = "form-group mx-2 my-2 w-full sm:w-1/2 md:w-1/3 lg:w-1/4";
    
    public override void Process(TagHelperContext Context, TagHelperOutput Output)
    {
        var container = new TagBuilder("div");
        // 设置容器类
        container.AddCssClass(ContainerClass ?? string.Empty);
        
        // 构建Label标签
        var label = new TagBuilder("label");
        label.Attributes["for"] = For?.Name;
        label.AddCssClass("block");
        label.InnerHtml.Append(LabelName ?? string.Empty);
        
        // 构建Input标签
        var input = new TagBuilder("input");
        input.Attributes["name"] = For?.Name;
        input.Attributes["id"] = For?.Name;
        input.Attributes["value"] = For?.Model?.ToString();
        input.AddCssClass("form-input w-full bg-yellow-100 dark:bg-yellow-100 dark:text-black");
        input.Attributes["type"] = "text";

        // 构建验证Span标签
        var validation = new TagBuilder("span");
        validation.AddCssClass("text-red-600");
        
        // 从ModelState获取错误信息
        var validationMessage = string.Empty;
        if (ViewContext != null && Validation != null)
        {
            if (ViewContext.ModelState.TryGetValue(Validation.Name, out var modelStateEntry) 
                && modelStateEntry.Errors.Any())
            {
                validationMessage = modelStateEntry.Errors.First().ErrorMessage;
                validation.AddCssClass("field-validation-error");
            }
            else
            {
                validation.AddCssClass("field-validation-valid");
            }
        }
        
        // 设置验证span的属性和内容
        validation.Attributes["data-valmsg-for"] = Validation?.Name;
        validation.Attributes["data-valmsg-replace"] = "true";
        validation.InnerHtml.Append(validationMessage);
        
        // 组装所有元素
        container.InnerHtml.AppendHtml(label);
        container.InnerHtml.AppendHtml(input);
        container.InnerHtml.AppendHtml(validation);
        
        Output.Content.SetHtmlContent(container);
    }
}

关键修改点说明

  1. 注入ViewContext:通过[ViewContext]属性注入当前视图的上下文,这样才能访问ModelState集合。
  2. 读取ModelState错误:检查对应字段的ModelState条目,提取第一条错误信息作为验证提示文本。
  3. 完善样式类逻辑:根据是否存在错误,动态添加field-validation-error或field-validation-valid类,和原生标签助手的行为保持一致。
  4. 可选:容器类自定义:添加container-class属性,让你可以灵活设置外层div的样式,和原表单结构保持一致。

使用修改后的TagHelper

<text-required-field 
    asp-for="Record.Name" 
    asp-validation-for="Record.Name" 
    label-for="@RS_Relationships.name"
    container-class="form-group mx-2 my-2 w-full sm:w-1/2 md:w-1/3 lg:w-1/4"></text-required-field>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:56:08