本文介绍了排除模型验证(例如DbGeography)一类以避免InsufficientExecutionStackException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:作为TL;博士版本跳到底部

UPDATE: for the tl;dr version skip to the bottom

我有一个非常简单的JsonConverter的子类,我使用的是使用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#
系统。 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?

更新:脑果汁有点补充,我已经通过大部分的代码退了一步,似乎验证模型的 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 方法,添加

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.

这篇关于排除模型验证(例如DbGeography)一类以避免InsufficientExecutionStackException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-26 19:54