我正在尝试构建一个可以访问modelmetadata的html帮助器。 我需要两个版本的helper才能工作:来自字符串表达式和来自lambda表达式: 例如:
public static MvcHtmlString MyLabel(this HtmlHelper html, string htmlFieldName)
{
return LabelHelper(html, htmlFieldName);
}
public static MvcHtmlString MyLabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
{
return LabelHelper(html, ExpressionHelper.GetExpressionText(expression));
}
private MvcHtmlString LabelHelper(HtmlHelper html, string htmlFieldName)
{
ModelMetadata m = ModelMetadata.FromStringExpression(htmlFieldName);
// the rest of the code...
}
上面代码的问题在于它不适用于复杂类型。例如,如果我的模型看起来像这样:
public class MyViewModel
{
public int Id { get; set; }
public Company Company { get; set; }
}
public class Company
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
我的html助手无法读取以下内容的元数据:
@Html.MyLabel("Company.Name")
我可以让它适用于带有表达式的助手,因为ModelMetadata.FromLambdaExpression(...)
实际上可以很好地处理复杂的对象,但这对我来说还不够。
任何建议都表示赞赏。
答案 0 :(得分:4)
总之,不可能只使用FromStrinExpression(...)方法。在内部,ModelMetadata.FromStringExpression(...)将尝试获取嵌套属性的ViewDataInfo - 在您的情况下为“Name”。如果View是一个stongly-typed,但Model是null然后是 ViewData.GetViewDataInfo将返回null。在这种情况下,它将仅循环ModelMetadata.Properties,并且将无法找到嵌套属性。如果Model不为null,则该方法将返回正确的ModelMetadata,因为正确的ViewDataInfo。另一方面,ModelMetadata.FromLamdaExpression(...)具有关于容器和属性类型的足够信息,这就是它适用于复杂对象的原因。
我有一个勇敢的建议:)。你有字符串表达式和Html.ViewData。您可以递归循环Html.ViewData.ModelMetadata.Properties并尝试获取嵌套属性的ModelMetadata。