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

如何在ASP.NET Core中动态传递AspFor构建通用Input组件

问题分析

你遇到的核心问题是:当通过字符串(如"Contactos.Email")传递AspFor值给部分视图时,asp-for="@Model.AspFor"会被标签助手解析为当前部分视图模型(InputModel)的AspFor属性,而非父页面视图模型(RegistoViewModel)中的Contactos.Email属性。而直接在页面中写asp-for="Contactos.Email"时,上下文是父模型,所以能正常工作。

解决方案

方案一:使用表达式树传递(类型安全,推荐)

通过表达式树替代字符串传递绑定路径,让标签助手能正确识别父模型的属性。

1. 修改InputModel定义

替换字符串类型的AspFor为表达式树类型:

public class InputModel : ComponentModel
{
    public Expression<Func<object>> AspFor { get; set; }
    public string? Disabled { get; set; } 
    // 移除手动Value属性,asp-for会自动绑定值
}

2. 页面中构建InputModel

传递父模型的属性表达式,而非字符串路径:

@{ 
    var input = new InputModel
    {
        Id = "inputId",
        Label = "Email",
        Componente = ComponentEnum.Input,
        AspFor = () => Model.Contactos.Email,
        IsMandatory = true
    };
}
 
@await Html.PartialAsync(ComponentEnum.Input.GetPath(), input)

3. 修改Input部分视图

直接使用表达式树作为asp-for的参数:

@model InputModel

<div id="@Model.Id-container" class="form-select-container">
    <label class="text-blue800 steps-subtitle">@Model.Label</label>
    @if (Model.IsMandatory)
    {
        <span class="text-primary">(Mandatory)</span>
    }
    <label asp-for="@Model.AspFor" class="form-label"></label>
    <input asp-for="@Model.AspFor" class="form-control" />
    <!-- 自动生成验证信息 -->
    <span asp-validation-for="@Model.AspFor" class="text-danger"></span>
</div>

方案二:通过ViewContext解析字符串路径(兼容字符串传递场景)

如果坚持使用字符串传递路径,可以在部分视图中通过ViewContext获取父模型,手动解析路径生成表达式。

修改Input部分视图代码

@model InputModel
@using System.Linq.Expressions
@using System.Reflection

@{
    // 获取父页面的视图模型
    var parentModel = ViewData.Model;
    if (parentModel == null || string.IsNullOrEmpty(Model.AspFor)) return;

    // 解析路径(如"Contactos.Email"拆分为["Contactos", "Email"])
    var propertySegments = Model.AspFor.Split('.');
    Expression currentExpression = Expression.Constant(parentModel);
    Type currentType = parentModel.GetType();

    // 逐层解析属性路径
    foreach (var segment in propertySegments)
    {
        var property = currentType.GetProperty(segment);
        if (property == null) break;
        currentExpression = Expression.Property(currentExpression, property);
        currentType = property.PropertyType;
    }

    // 转换为标签助手支持的表达式类型
    var bindingExpression = Expression.Lambda<Func<object>>(Expression.Convert(currentExpression, typeof(object)));
}

<div id="@Model.Id-container" class="form-select-container">
    <label class="text-blue800 steps-subtitle">@Model.Label</label>
    @if (Model.IsMandatory)
    {
        <span class="text-primary">(Mandatory)</span>
    }
    <label asp-for="@bindingExpression" class="form-label"></label>
    <input asp-for="@bindingExpression" class="form-control" />
    <span asp-validation-for="@bindingExpression" class="text-danger"></span>
</div>
注意事项
  • 方案一为类型安全实现,编译时即可检查路径是否合法,避免拼写错误,优先推荐。
  • 方案二需自行处理路径解析异常(如路径不存在、类型不匹配等),适合必须使用字符串传递的场景。
  • 两种方案均无需手动设置value属性,asp-for会自动完成值绑定、name/id生成及验证逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:26:02