C# ASP.NET Core无法将string转换为ModelExpression问题咨询
报错原因
出现Cannot convert 'string' to 'ModelExpression'的核心原因是传参逻辑错误:你写的Model.FirstName是FirstName属性的实际字符串值,而FieldViewModel构造函数要求的ModelExpression类型是ASP.NET Core MVC用来存储模型属性访问路径、元数据(验证规则、显示名等)、属性值的特殊结构,不是属性本身的值,二者类型完全不匹配。
不要尝试手动直接new ModelExpression实例,它的构造依赖全局模型元数据提供器生成的属性元数据,手动构造很容易丢失关键信息,导致标签助手无法正常工作。
实现方案
方案1:保留分部视图实现,通过框架提供器构造ModelExpression
如果要保留现有分部视图的结构,只需要修正传参逻辑,用官方提供的IModelExpressionProvider生成正确的ModelExpression即可:
- 在调用分部视图的Razor页面顶部注入模型表达式提供器:
@inject Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider ModelExpressionProvider - 调用分部视图时,先通过lambda表达式构造对应属性的ModelExpression,再传入ViewModel:
@{ // 构造指向FirstName属性的ModelExpression var firstNameExpression = ModelExpressionProvider.CreateModelExpression(ViewData, m => m.FirstName); } @await Html.PartialAsync("_Field", new FieldViewModel(firstNameExpression, "First Name"))
你原来写的_Field.cshtml内部代码不需要修改,asp-for="@Model.Data"可以直接识别正确构造的ModelExpression对象,正常完成模型绑定、验证、值填充的逻辑。
方案2:自定义表单字段标签助手(推荐,复用性更高)
如果要大量复用表单字段模板,更推荐实现自定义标签助手,调用方式和原生asp-for完全一致,不需要每次手动构造ModelExpression:
- 新建标签助手类
FormFieldTagHelper.cs:using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Razor.TagHelpers; [HtmlTargetElement("form-field", Attributes = "asp-for")] public class FormFieldTagHelper : TagHelper { [HtmlAttributeName("asp-for")] public ModelExpression For { get; set; } [HtmlAttributeName("label")] public string LabelText { get; set; } [ViewContext] [HtmlAttributeNotBound] public ViewContext ViewContext { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; output.TagMode = TagMode.StartTagAndEndTag; // 这里替换成你自己的表单字段样板代码 var finalLabel = string.IsNullOrEmpty(LabelText) ? For.Metadata.DisplayName ?? For.Name : LabelText; output.Content.AppendHtml($"<label asp-for=\"{For.Name}\" class=\"form-label\">{finalLabel}</label>"); output.Content.AppendHtml($"<input asp-for=\"{For.Name}\" class=\"form-control\" />"); output.Content.AppendHtml($"<span asp-validation-for=\"{For.Name}\" class=\"text-danger\"></span>"); } } - 在
_ViewImports.cshtml中注册你写的标签助手,把YourProjectNamespace替换成你项目的实际命名空间:@addTagHelper YourProjectNamespace.*, YourProjectNamespace - 之后在任意视图中可以直接用标签语法调用,不需要写任何构造逻辑,自动识别模型属性:
<form-field asp-for="FirstName" label="First Name"></form-field> <form-field asp-for="LastName"></form-field> @* 不传label时自动取模型属性的Display名称*@
内容的提问来源于stack exchange,提问作者DimChtz
相关产品推荐
相关产品推荐

