如何获取 razor 视图引擎中集合中项目的元数据?

2024-02-06

我有一个项目写在C#位于 ASP.NET MVC 5 框架的顶部。我试图将我的视图与视图模型分离,以便我可以使我的视图可重用。随着大量使用EditorTemplates我能够通过评估来创建所有标准视图(即创建、编辑和详细信息)ModelMetadata以及模型上每个属性的数据注释属性,然后渲染页面。唯一令我困惑的是如何渲染Index view.

我的索引视图通常接受IEnumerable<object> or IPagedList<object>收藏。在我看来,我希望能够评估每个模型的 ModelMetadataobject/record 判断集合中的某个属性是否object应该显示或不显示。

换句话说,我的视图模型看起来像这样

public class DisplayPersonViewModel
{
    public int Id{ get; set; }

    [ShowOnIndexView]
    public string FirstName { get; set; }

    [ShowOnIndexView]
    public string LastName { get; set; }

    [ShowOnIndexView]
    public int? Age { get; set; }

    public string Gender { get; set; }
}

Then my Index.cshtml视图将接受IPagedList<DisplayPersonViewModel>对于集合中的每条记录,我想显示装饰有的属性的值ShowOnIndexView属性。

通常,我可以用这样的方法来评估我看来的 ModelMetadata

@model IPagedList<object>
@{
var elements = ViewData.ModelMetadata.Properties.Where(metadata => !metadata.IsComplexType && !ViewData.TemplateInfo.Visited(metadata))
                                                .OrderBy(x => x.Order)
                                                .ToList();
}

<tr>
    @foreach(var element in elements)
    {
        var onIndex = element.ContainerType.GetProperty(element.PropertyName)
                             .GetCustomAttributes(typeof(ShowOnIndexView), true)
                             .Select(x => x as ShowOnIndexView)
                             .FirstOrDefault(x => x != null);
        if(onIndex == null) 
        {
            continue;
        }

        @Html.Editor(element.PropertyName, "ReadOnly")
    }
</tr>

然后我的控制器看起来像这样

public class PersonController : Controller
{
        public ActionResult Index()
        {
            // This would be a call to a service to give me a collection with items. but I am but showing the I would pass a collection to my view
            var viewModel = new List<DisplayPersonViewModel>();

            return View(viewModel);
        }
}

然而评估的问题ModelMetadata为了IPagedList<DisplayPersonViewModel>是它为我提供了有关集合本身的信息,而不是有关集合中的泛型类型或单个模型的信息。换句话说,我得到的信息包括总页数、每页条目数、总记录数......

Question

我怎样才能访问ModelMetadata集合中每一行的信息以便能够知道要显示哪些属性以及不显示哪些属性?


我将通过建议您不要用此类代码污染您的视图来作为这个答案的序言。更好的解决方案是创建一个自定义的HtmlHelper扩展方法来生成 html,这为您提供了更大的灵活性,可以进行单元测试,并且可以重用。

您需要更改的第一件事是视图中的模型声明,需要将其更改为

@model object

否则你会扔这个例外 https://stackoverflow.com/questions/40373595/the-model-item-passed-into-the-dictionary-is-of-type-but-this-dictionary-requ (List<DisplayPersonViewModel> is not IEnumerable<object> or IPagedList<object>, 但它是object)

请注意,尚不清楚您是否想要ModelMetadata为了type在集合中或集合中的每个项目中,所以我都包含了两者,以及获取type

@model object
@{
    var elements = ViewData.ModelMetadata.Properties.Where(metadata => !metadata.IsComplexType && !ViewData.TemplateInfo.Visited(metadata)).OrderBy(x => x.Order).ToList();

    // Get the metadata for the model
    var collectionMetaData = ViewData.ModelMetadata;
    // Get the collection type
    Type type = collectionMetaData.Model.GetType();
    // Validate its a collection and get the type in the collection
    if (type.IsGenericType)
    {
        type = type.GetInterfaces().Where(t => t.IsGenericType)
            .Where(t => t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
            .Single().GetGenericArguments()[0];
    }
    else if (type.IsArray)
    {
        type = type.GetElementType();
    }
    else
    {
        // its not a valid model
    }
    // Get the metadata for the type in the collection
    ModelMetadata typeMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, type);
}
....
@foreach (var element in collectionMetaData.Model as IEnumerable))
{
    // Get the metadata for the element
    ModelMetadata elementMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => element, type);
    ....

请注意,使用反射来确定循环的每次迭代中是否存在该属性的效率很低,我建议您这样做一次(基于typeMetadata)。然后你可以(例如)生成一个数组bool值,然后在循环中使用索引器来检查该值)。更好的选择是让你的ShowOnIndexView属性工具IMetadataAware并添加一个值AdditionalValues of ModelMetadata以便var onIndex根本不需要代码。一个实施的例子IMetadataAware, refer CustomAttribute反映html属性MVC5 https://stackoverflow.com/questions/26519493/customattribute-reflects-html-attribute-mvc5/26519946#26519946

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何获取 razor 视图引擎中集合中项目的元数据? 的相关文章

随机推荐