从模型validation中排除类型(示例DbGeography)以避免InsufficientExecutionStackException
更新:对于tl; dr版本跳到底部
我有一个非常简单的JsonConverter子类,我正在使用Web API:
public class DbGeographyJsonConverter : JsonConverter { public override bool CanConvert(Type type) { return typeof(DbGeography).IsAssignableFrom(type); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var value = (string)reader.Value; if (value.StartsWith("POINT", StringComparison.OrdinalIgnoreCase)) { return DbGeography.PointFromText(value, DbGeography.DefaultCoordinateSystemId); } else if (value.StartsWith("POLYGON", StringComparison.OrdinalIgnoreCase)) { return DbGeography.FromText(value, DbGeography.DefaultCoordinateSystemId); } else //We don't want to support anything else right now. { throw new ArgumentException(); } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, ((DbGeography)value).AsText()); } }
问题是,在ReadJson
返回后,应用程序永远不会将绑定对象返回到action方法,因为它似乎停留在无限的validation循环中。
当我暂停执行时,这是调用堆栈的顶部:
System.Web.Http.dll!System.Web.Http.Metadata.Providers.AssociatedMetadataProvider.GetMetadataForPropertiesImpl.AnonymousMethod__0()第40行C#System.Web.Http.dll!System.Web.Http.Metadata.ModelMetadata.Model.get( )第85行C#System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata metadata,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,object container )第94行C#System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata metadata,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)第156行C#System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata metadata,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,object container)第130行C#S ystem.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateElements(System.Collections.IEnumerable model,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)第176行C#
之后,DefaultBodyModelValidator.Validation *调用模式一遍又一遍地重复。 每次我暂停执行时,它似乎都在大约相同的深度,所以它似乎没有递归更深。
如果我强制JsonConverter返回null
,控制返回到API控制器动作方法,我假设因为没有什么可以validation。
我没有留下脑汁来解决这个问题。 我究竟做错了什么?
更新:脑汁有点补充,我已经介绍了大部分代码,看来在validation模型时, DefaultBodyModelValidator
正在钻进SqlTypesAssembly
并陷入循环读取属性的某个地方。 我并不真正关心DbGeography
里,因为我不希望DefaultBodyModelValidator
钻进DbGeography
类型实例开始。
模型validation没有理由深入到DbGeography
类中。 我需要弄清楚如何获取MediaTypeFormatterCollection.IsTypeExcludedFromValidation
方法为typeof(DbGeography)
返回true,这将导致DefaultBodyModelValidator
对任何DbGeography
实例执行浅层validation。 那么现在的问题是 – 如何从模型validation中排除类型? DefaultBodyModelValidator
的ShouldValidateType
方法标记为虚拟,但是没有一种简单的方法可以在启动时添加排除类型吗?
无论这个问题是Web API的错误还是限制,我都不知道,但这是我的解决方法:
首先,我们需要ShouldValidateType
DefaultBodyModelValidator
并覆盖ShouldValidateType
方法。
public class CustomBodyModelValidator : DefaultBodyModelValidator { public override bool ShouldValidateType(Type type) { return type!= typeof(DbGeography) && base.ShouldValidateType(type); } }
现在在global.asax的Application_Start
方法中添加
GlobalConfiguration.Configuration.Services.Replace(typeof(IBodyModelValidator), new CustomBodyModelValidator());
就是这样。 现在将在DbGeography
类型实例上执行浅层validation,并且一切都很好地绑定。
只是有完全相同的问题,但后来有一个自定义类型。 经过相当多的研究,结果certificate这个线程的知识非常符合逻辑。 自定义类有一个public readonly属性,它返回同一个类的另一个实例。 validation器会查看该类的所有属性(即使您根本不进行任何validation)并获取该值。 如果你的类返回一个同一个类的新实例,这会一次又一次地发生……看起来Geography类中的StartPoint属性有同样的问题。 https://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeography.startpoint(v=vs.110).aspx
joelmdev的答案引导我朝着正确的方向发展,但是在MVC和WebApi 5.2.3中使用我的WebApi配置时,放置在Global.asax中时不会调用新的validation器。
解决方案是将它放在我的WebApiConfig.Register方法中,使用其他WebApi路由: config.Services.Replace(typeof(IBodyModelValidator), new CustomBodyModelValidator());
上述就是C#学习教程:从模型validation中排除类型(示例DbGeography)以避免InsufficientExecutionStackException分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/989858.html