问题描述
更新:作为TL;博士版本跳到底部
UPDATE: for the tl;dr version skip to the bottom
我有JsonConverter的pretty简单的子类,我使用的是使用Web API:
I have a pretty simple subclass of JsonConverter that I'm using with 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
返回,因为它似乎是停留在一个无限验证循环的应用程序将不会返回绑定对象的操作方法。
The problem is, after ReadJson
returns the application never returns a bound object to the action method as it appears to be stuck in an infinite validation loop.
下面是调用堆栈,当我暂停执行顶部:
Here's the top of the call stack when I pause execution:
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元数据,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器),94号线C#
System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(System.Web.Http.Metadata.ModelMetadata元数据,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)线156 C#
System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(System.Web.Http.Metadata.ModelMetadata元数据,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext,对象容器)线130 C#
System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateElements(System.Collections.IEnumerable模型,System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext)线176 C#
在这之后,电话的DefaultBodyModelValidator.Validation *模式重复一遍又一遍又一遍。每次我暂停执行,这似乎是在大约相同的深度,所以也不会出现越来越递归更深
After that, the DefaultBodyModelValidator.Validation* pattern of calls repeats over and over and over again. Everytime I pause execution, it appears to be at about the same depth, so it doesn't appear to be getting recursively deeper.
如果我强迫JsonConverter返回空
,控制返回到API控制器的操作方法,我假设,因为没有什么验证。
If I force the JsonConverter to return null
, control returns to the API controller action method, I'm assuming because there's nothing to validate.
我没有大脑果汁离开推测这一个。我在做什么错了?
I don't have the brain juices left to figure this one out. What am I doing wrong?
更新:脑果汁有点补充,我已经通过大部分的code阶梯,看来,验证模型时, DefaultBodyModelValidator
是一路下滑到 SqlTypesAssembly
钻井和被陷在一个循环中读书的地方属性。我真的不关心精确地找出,因为我不想让 DefaultBodyModelValidator
钻进 DbGeography
键入实例做下手。
UPDATE: With brain juices somewhat replenished, I've stepped through most of the code and it appears that when validating the model the DefaultBodyModelValidator
is drilling way down into the SqlTypesAssembly
and getting stuck in a loop reading attributes somewhere. I don't really care to find out exactly where because I don't want the DefaultBodyModelValidator
drilling into DbGeography
type instances to start with.
有没有理由为模型验证向下钻取到 DbGeography
类。我需要弄清楚如何获得 MediaTypeFormatterCollection.IsTypeExcludedFromValidation
法的typeof(DbGeography),这将为返回true导致
DefaultBodyModelValidator
在任何 DbGeography
实例进行浅验证。所以,现在眼下的问题是 - 我该如何排除模型校验类型?在 ShouldValidateType
DefaultBodyModelValidator
的方法被标记为虚拟的,但有没有一个简单的方法来在启动时添加排除类型?
There's no reason for model validation to drill down into the DbGeography
class. I need to figure out how to get the MediaTypeFormatterCollection.IsTypeExcludedFromValidation
method to return true for typeof(DbGeography)
, which will cause the DefaultBodyModelValidator
to perform shallow validation on any DbGeography
instances. So now the question at hand is- how do I exclude a type from model validation? The ShouldValidateType
method of DefaultBodyModelValidator
is marked virtual, but is there not a simple way to add an excluded type at startup?
推荐答案
不管这个问题是一个bug或Web API的限制,我不知道,但这里是我的解决方法:
Whether this issue is a bug or a limitation of Web API, I do not know, but here's my workaround:
首先,我们需要继承的 DefaultBodyModelValidator
并重写 ShouldValidateType
方法。
First, we need to subclass the DefaultBodyModelValidator
and override the ShouldValidateType
method.
public class CustomBodyModelValidator : DefaultBodyModelValidator
{
public override bool ShouldValidateType(Type type)
{
return type!= typeof(DbGeography) && base.ShouldValidateType(type);
}
}
现在在Global.asax中的的Application_Start
方法,添加
Now in global.asax's Application_Start
method, add
GlobalConfiguration.Configuration.Services.Replace(typeof(IBodyModelValidator), new CustomBodyModelValidator());
,就是这样。验证浅现在将执行的 DbGeography
键入实例,一切都很好地结合。
and that's it. Shallow validation will now be performed on the DbGeography
type instances and everything binds nicely.
这篇关于排除模型验证类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!