首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >针对DbGeography的JSON.Net JsonConverter

针对DbGeography的JSON.Net JsonConverter
EN

Stack Overflow用户
提问于 2013-01-04 05:10:52
回答 2查看 5.7K关注 0票数 10

漫长而漫长的斗争……

基本上,我有一个具有DbGeography属性的模型优先的EF5对象。我想应用一个JsonConverter,让它往返于简单的纬度/经度值。我使用的是WebAPI。

如下所示查找JSON输出和输入:

代码语言:javascript
复制
{
    "location":
    {
        "geopoint":
        {
            "latitude":40.770712,
            "longitude":-73.962011
        }
    }
}

下面是我的类定义和JsonConverter:

代码语言:javascript
复制
[MetadataType(typeof(QueryLocationMetadata))]
partial class Location
{
}

public class QueryLocationMetadata
{
    [JsonConverter(typeof(DbGeographyConverter))]
    public virtual DbGeography GeoPoint { get; set; }
}


public class DbGeographyConverter : JsonConverter
{
    private const string LATITUDE_KEY = "latitude";
    private const string LONGITUDE_KEY = "longitude";

    public override bool CanConvert(Type objectType)
    {
        return objectType.Equals(typeof(DbGeography));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return default(DbGeography);

        var jObject = JObject.Load(reader);

        if (!jObject.HasValues || (jObject.Property(LATITUDE_KEY) == null || jObject.Property(LONGITUDE_KEY) == null))
            return default(DbGeography);

        string wkt = string.Format("POINT({1} {0})", jObject[LATITUDE_KEY], jObject[LONGITUDE_KEY]);
        return DbGeography.FromText(wkt, DbGeography.DefaultCoordinateSystemId);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var dbGeography = value as DbGeography;

        serializer.Serialize(writer, dbGeography == null || dbGeography.IsEmpty ? null : new { latitude = dbGeography.Latitude.Value, longitude = dbGeography.Longitude.Value });
    }
}

因此,使用它,我能够成功地序列化甚至反序列化一个对象,但是在我执行ApiController操作之前,我得到了以下错误:

代码语言:javascript
复制
System.Data.SqlTypes.SqlNullValueException: Data is Null. This method or property cannot be called on Null values.
   at System.Data.SqlTypes.SqlDouble.get_Value()
   at GetValueFromSqlDouble(Object )
   at System.Web.Http.Metadata.Providers.AssociatedMetadataProvider`1.<>c__DisplayClass3.<GetMetadataForPropertiesImpl>b__0()
   at System.Web.Http.Metadata.ModelMetadata.get_Model()
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateElements(IEnumerable model, ValidationContext validationContext)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateProperties(ModelMetadata metadata, ValidationContext validationContext)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateElements(IEnumerable model, ValidationContext validationContext)
   at System.Web.Http.Validation.DefaultBodyModelValidator.ValidateNodeAndChildren(ModelMetadata metadata, ValidationContext validationContext, Object container)
   at System.Web.Http.Validation.DefaultBodyModelValidator.Validate(Object model, Type type, ModelMetadataProvider metadataProvider, HttpActionContext actionContext, String keyPrefix)
   at System.Web.Http.ModelBinding.FormatterParameterBinding.<>c__DisplayClass1.<ExecuteBindingAsync>b__0(Object model)
   at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass36`1.<>c__DisplayClass38.<Then>b__35()
   at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass49.<ToAsyncVoidTask>b__48()
   at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)

在玩弄和搜索了各种各样的东西之后,我完全不知所措。我知道通常它是在尝试验证属性,但是SqlDouble?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-01-04 05:46:33

问题不在于您的转换器。这是一个已知的验证错误,当公共属性的getter在对象图中抛出时就会发生。此工作项跟踪问题:

http://aspnetwebstack.codeplex.com/workitem/740

同时,您应该能够通过禁用验证来绕过它:

代码语言:javascript
复制
config.Services.Clear(typeof(ModelValidatorProvider));

很抱歉给您带来不便。

票数 4
EN

Stack Overflow用户

发布于 2013-11-14 22:35:49

Youssef提到的错误已经修复了,但我在为DbGeography创建自定义JsonConverter时仍然遇到了问题,因为在验证过程中的某个地方,DefaultBodyModelValidator陷入了循环。我的解决方案不是完全禁用模型验证,而是用一个派生的验证器替换默认的验证器,该验证器将DbGeography类型排除在深度验证之外。

为了不重复我的话,you can see the full solution here.

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14147299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档