【问题标题】:Get Metadata from navigation property从导航属性获取元数据
【发布时间】:2014-06-21 18:12:06
【问题描述】:

我想知道是否有更好的方法来借助ModelMetadataProviders 类获取导航属性元数据值?

cshtml示例:

@model IEnumerable<WebApp.Web.Service.OfficeService.PlayerDeposit>

<div id="pagedList">
    <table class="table Report tablesorter table-bordered table">
        <thead>
            <tr>
                <th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.PaymentProvider.Name)
                </th>
                <th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.Country.CountryName)
                </th>
                <th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.NumberOfPlayers)
                </th>
                <th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.AmountDeposited)
                </th>
                <th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.Collected)
                </th>
                <th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.TransactionFee)
                </th>
                <th class="table-head sortTable">Balance
                </th>
                <th></th>
            </tr>
        </thead>

因此,为了获取元数据名称,我必须使用 ModelMetadataProviders 类创建视图助手。

我找不到直接的方法来访问提供的实体名称的导航属性名称,所以我不得不使用旧的字符串操作(我知道有点混乱):

 public static IHtmlString DisplayColumnNameFor<TModel, TClass, TProperty>
    (this HtmlHelper<TModel> helper, IEnumerable<TClass> model,
    Expression<Func<TClass, TProperty>> expression)
        {
            string entity = "";
            string name = "";
            ModelMetadata metadata = null;

            var expressionText = ExpressionHelper.GetExpressionText(expression);
            name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expressionText);

            if (name.Contains('.'))
            {
                int indexOfDot = name.IndexOf('.');

                entity = name.Substring(0, indexOfDot);
                name = name.Substring(indexOfDot + 1, name.Length - (indexOfDot + 1));

                Type classType = Type.GetType("WebApp.Web.Service.OfficeService." + entity);

                metadata =
                    ModelMetadataProviders
                        .Current
                        .GetMetadataForProperty(() => Activator.CreateInstance(classType), classType, name);
            }
            else
            {
                metadata = ModelMetadataProviders.Current.GetMetadataForProperty(
                    () => Activator.CreateInstance<TClass>(), typeof(TClass), name);
            }

            return new MvcHtmlString(metadata.DisplayName);
        }

如您所见,由于我真的不知道是否有更好的方法可以直接从表达式访问导航属性,所以我首先将实体和名称分开(我只计算一级深度导航属性),然后借助反射我得到了类类型,所以我可以访问实体元数据......

我尝试在 html 中使用旧的 hack 方法来实例化 PlayerDeposit,然后直接在 html 中使用 @Html.DisplayNameFor 的模型,但由于某种原因它不允许我使用(模棱两可的错误):@Html.DisplayNameFor(model =&gt; model.Carriers.FirstOrDefault().Name)

【问题讨论】:

    标签: c#


    【解决方案1】:

    我认为正确的做法是使用ModelMetadata.FromLambdaExpression。需要注意的是,对于这个应用程序,传递给FromLambdaExpressionViewDataDictionary 不会用于任何事情,因为我们不需要检查视图数据的值。我们从属性本身获取显示名称。通过允许我们创建一个正确键入的 ViewDataDictionary 来用于调用,这使得它相对容易。

    public static class HtmlHelperExtensions
    {
        public static IHtmlString DisplayColumnNameFor<TModel, TCollection, TProperty>(
            this HtmlHelper<TModel> helper,
            IEnumerable<TCollection> model,
            Expression<Func<TCollection, TProperty>> expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
    
            var dictionary = new ViewDataDictionary<TCollection>();
    
            var metadata = ModelMetadata.FromLambdaExpression(expression, dictionary);
    
            return MvcHtmlString.Create(metadata.DisplayName);
        }
    }
    

    【讨论】:

    • 因为在详细信息视图中使用项目时,您可能希望模型属性具有不同的名称似乎是合理的,所以我创建了一个类似的扩展,它使用列名称的自定义属性.您可以在github.com/tvanfosson/MvcExtensions 找到上面的示例(使用不同的名称)和附加方法
    猜你喜欢
    • 2019-09-09
    • 2012-05-24
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多