基于来自数据库的配置的ASP.NET Core 2.1动态显示属性

时间:2018-12-06 12:12:45

标签: c# asp.net-core asp.net-core-mvc asp.net-core-webapi asp.net-core-2.1

我们有一个非常重要的要求,即同一个视图模型(JournalVoucher)可以具有许多“类型”(由用户配置),并且对于每个“类型”,JournalVoucher中的属性将具有不同的显示名称和验证规则,所有来自数据库中用户定义的配置。例如,在销售凭单中,“代理”属性的显示名称为“客户”,在购买凭单中,显示名称为“供应商”,依此类推。

经过一番研究,我无意间偶然发现了一个看起来过于简单以至于无法实现的解决方案,但到目前为止它仍然有效。我想知道是否有更多经验的人可以看看我是否做对了。也许其他开发人员也可以从代码中受益。

想法是从DefaultModelMetadataProvider继承并像这样覆盖CreatePropertyDetails

public class CustomModelMetadataProvider : DefaultModelMetadataProvider
{
    private readonly IMyContext _context;

    public CustomModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider, IMyContext context) : base(detailsProvider)
    {
        _context = context;
    }

    public CustomModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider, IOptions<MvcOptions> optionsAccessor, IMyContext context) : base(detailsProvider, optionsAccessor)
    {
        _context = context;
    }

    protected override DefaultMetadataDetails[] CreatePropertyDetails(ModelMetadataIdentity key)
    {
        // Call the base implementation
        var propsDetails = base.CreatePropertyDetails(key);

        // If the model type is our dynamic entity
        if (key.ModelType == typeof(JournalVoucher))
        {
            // Loop over the properties
            foreach (var propDetails in propsDetails)
            {
                // If the property is one of our dynamic properties
                string propertyName = propDetails.Key.Name;
                if (propertyName == nameof(JournalVoucher.Agent))
                {
                    // Set the display metadata passing a Func that dynamically 
                    // determines the display name by calling a custom service that
                    // we inject in the constructor, the service may call
                    // the database or rely on info from the HTTP Context
                    propDetails.DisplayMetadata = new DisplayMetadata
                    {
                        // Dynamic display name!!
                        DisplayName = () => _context.GetJournalVoucherPropertyDisplayName(propertyName)
                    };
                }
            }
        }

        return propsDetails;
    }
}

当然,您必须在Startup.cs中注册此实现:

services.AddSingleton<IMyContext, MyContext>();
services.AddSingleton<IModelMetadataProvider, CustomModelMetadataProvider>();

0 个答案:

没有答案