排除模型验证类型 [英] Exclude a type from model validation

查看:154
本文介绍了排除模型验证类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:作为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#

System.Web.Http.dll!System.Web.Http.Metadata.Providers.AssociatedMetadataProvider.GetMetadataForPropertiesImpl.AnonymousMethod__0() Line 40 C# System.Web.Http.dll!System.Web.Http.Metadata.ModelMetadata.Model.get() Line 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) Line 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) Line 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) Line 130 C# System.Web.Http.dll!System.Web.Http.Validation.DefaultBodyModelValidator.ValidateElements(System.Collections.IEnumerable model, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext) Line 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.

这篇关于排除模型验证类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆