ОБНОВЛЕНИЕ: для версии tl;dr пропустить вниз
У меня есть довольно простой подкласс JsonConverter, который я использую с веб-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
приложение никогда не возвращает связанный объект методу действия, поскольку он застревает в бесконечном цикле проверки.
Вот вершина стека вызовов, когда я приостанавливаю выполнение:
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, объектный контейнер ) Строка 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 метаданные, System.Web.Http.Validation.DefaultBodyModelValidator.ValidationContext validationContext, obj ect container) Строка 130 C# System.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, как я предполагаю, потому что нечего проверять.
У меня не осталось мозговых соков, чтобы понять это. Что я делаю неправильно?
ОБНОВЛЕНИЕ: С несколько пополненными мозговыми соками я прошел большую часть кода, и оказалось, что при проверке модели DefaultBodyModelValidator
углубляется в SqlTypesAssembly
и где-то застревает в цикле чтения атрибутов. . На самом деле мне все равно, где именно, потому что я не хочу начинать с DefaultBodyModelValidator
углубления в экземпляры типа DbGeography
.
Нет причин для валидации модели углубляться в класс DbGeography
. Мне нужно выяснить, как заставить метод MediaTypeFormatterCollection.IsTypeExcludedFromValidation
возвращать true для typeof(DbGeography)
, что заставит DefaultBodyModelValidator
выполнять неглубокую проверку любых экземпляров DbGeography
. Итак, теперь возникает вопрос: как исключить тип из проверки модели? Метод ShouldValidateType
DefaultBodyModelValidator
помечен как виртуальный, но нет ли простого способа добавить исключенный тип при запуске?