one*_*ill 3 asp.net asp.net-core asp.net-core-2.0
这是一个棘手的问题,需要深入了解ASP.NET Core框架.我将首先解释我们的应用程序在MVC 3实现中发生了什么.
对于特定视图上的ViewModel,需要解决涉及ModelMetaData的复杂需求.这是一个高度可配置的应用程序.因此,对于一个"期刊类型",属性可能是强制性的,而对于另一个,完全相同的属性可能是非强制性的.此外,它可以是一个"日志类型"的单选按钮和另一个的选择列表.由于存在大量组合,混合和匹配所有这些配置选项,因此为每个可能的排列创建单独的ViewModel类型是不切实际的.因此,有一个ViewModel类型,并且动态地在该类型的属性上设置了ModelMetaData.
这是通过创建自定义ModelMetadataProvider(通过继承DataAnnotationsModelMetadataProvider)完成的.
Smash-cut到现在,我们正在升级应用程序并在ASP.NET Core中编写服务器内容.我已经确定实现IDisplayMetadataProvider是在ASP.NET Core中修改模型元数据的等效方法.
问题是,框架内置了缓存,任何实现的类IDisplayMetadataProvider只运行一次.我在调试ASP.NET Core框架时发现了这个,这个评论证实了我的发现.我们的要求将不再符合此类缓存,因为第一次访问ViewModel类型时,MetadataDetailsProvider将运行并将缓存结果.但是,如上所述,由于高度动态的配置,我需要它在每个之前运行ModelBinding.否则,我们将无法利用ModelState.第一次触发该端点时,元数据将在未来的所有请求中一致.
我们有点需要利用反射来通过所有属性的递归过程来设置元数据,因为我们不希望自己必须这样做(超出我的薪酬规模的巨大努力).
所以,如果有人认为我错过了新Core框架中的某些内容,请务必告诉我.即使是为消除那缓存功能简单ModelBinders和IDisplayMetadataProviders(这就是我将通过ASP.NET源会寻找到在未来几天内).
由于性能考虑,模型元数据被缓存.类DefaultModelMetadataProvider是IModelMetadataProvider接口的默认实现,负责此缓存.如果您的应用程序逻辑要求在每个请求上重建元数据,则应将此实现替换为您自己的实现.
如果从DefaultModelMetadataProvider继承实现并覆盖最低限度以实现目标,您将使您的生活更轻松.似乎GetMetadataForType(Type modelType)应该足够了:
public class CustomModelMetadataProvider : DefaultModelMetadataProvider
{
public CustomModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider)
: base(detailsProvider)
{
}
public CustomModelMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider, IOptions<MvcOptions> optionsAccessor)
: base(detailsProvider, optionsAccessor)
{
}
public override ModelMetadata GetMetadataForType(Type modelType)
{
// Optimization for intensively used System.Object
if (modelType == typeof(object))
{
return base.GetMetadataForType(modelType);
}
var identity = ModelMetadataIdentity.ForType(modelType);
DefaultMetadataDetails details = CreateTypeDetails(identity);
// This part contains the same logic as DefaultModelMetadata.DisplayMetadata property
// See https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Metadata/DefaultModelMetadata.cs
var context = new DisplayMetadataProviderContext(identity, details.ModelAttributes);
// Here your implementation of IDisplayMetadataProvider will be called
DetailsProvider.CreateDisplayMetadata(context);
details.DisplayMetadata = context.DisplayMetadata;
return CreateModelMetadata(details);
}
}
Run Code Online (Sandbox Code Playgroud)
要替换DefaultModelMetadataProvider为CustomModelMetadataProvider以下内容ConfigureServices():
services.AddSingleton<IModelMetadataProvider, CustomModelMetadataProvider>();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
551 次 |
| 最近记录: |