9

इस के साथ लंबे समय से लंबे समय से संघर्ष ... के लिएJSON.Net JsonConverter DbGeography

मूल रूप से मैं एक DbGeography संपत्ति के साथ एक मॉडल-पहले EF5 वस्तु है। मैं JsonConverter लागू करना चाहता हूं जो इसे सरल अक्षांश/देशांतर मानों के रूप में राउंडट्रिप करने दें। मैं वेबएपीआई का उपयोग कर रहा हूँ।

तो जैसे JSON उत्पादन और इनपुट के लिए खोज रहे:

{ 
    "location": 
    { 
     "geopoint": 
     { 
      "latitude":40.770712, 
      "longitude":-73.962011 
     } 
    } 
} 

यहाँ मेरी कक्षा परिभाषा और JsonConverter है:

[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 }); 
    } 
} 

तो इस का उपयोग करते हुए मैं सफलतापूर्वक को क्रमानुसार और यहां तक ​​कि एक वस्तु deserialize कर सकती हूं ठीक है लेकिन इससे पहले कि मैंने कभी भी ApiController कार्रवाई को मारा, मुझे निम्न त्रुटि मिलती है:

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) 

चारों ओर घूमने और सभी प्रकार की चीजों को गुगल करने के बाद, मैं बिल्कुल नुकसान में हूं। मुझे लगता है कि आम तौर पर यह संपत्ति को मान्य करने का प्रयास कर रहा है लेकिन एक एसक्यूएल डबल?

उत्तर

4

समस्या आपके कनवर्टर के साथ नहीं है। यह ज्ञात सत्यापन बग है जो तब होता है जब सार्वजनिक संपत्ति का गेट ऑब्जेक्ट ग्राफ़ में फेंकता है। इस काम के आइटम पटरियों मुद्दा:

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

मतलब समय में, आपको पुष्टिकरण को अक्षम करके उसके चारों ओर पाने के लिए सक्षम होना चाहिए:

config.Services.Clear(typeof(ModelValidatorProvider)); 

असुविधा के लिए खेद है।

+0

अस्थायी है या नहीं, कम से कम है कि देता है मुझे मेरे सिर पर बालों की कुछ रहते हैं। धन्यवाद! – Arno

+0

आपको पूरी तरह से योग्य नाम का उपयोग करना पड़ सकता है: System.Web.Http.Validation.ModelValidatorProvider जैसा कि यहां बताया गया है: https://aspnetwebstack.codeplex.com/workitem/55 – Scott

+0

@Youssef, कृपया मेरे लिंक में एक नज़र डालें जवाब। मुझे यह जानकर उत्सुकता है कि यह एक ज्ञात मुद्दा है या नहीं। – joelmdev

4

बग युसुफ ने उल्लेख के बाद से निर्धारित किया गया है, लेकिन मैं अभी भी जब सत्यापन प्रक्रिया DefaultBodyModelValidator एक पाश में फंस में है कि कहीं में DbGeography के लिए एक कस्टम JsonConverter बनाने मुद्दों में भाग गया। मेरा समाधान मॉडल सत्यापन को पूरी तरह से अक्षम नहीं करना था, लेकिन डिफ़ॉल्ट सत्यापनकर्ता को एक व्युत्पन्न व्यक्ति के साथ प्रतिस्थापित करने के लिए जो DbGeography गहरे सत्यापन से टाइप करता है।

तो जैसा कि अपने आप को दोहराना नहीं, you can see the full solution here.

+0

से अधिक हो रही है, आपने मुझे क्रोध का एक और दिन बचाया है, यह डीबीजीओगर्फी है .... वास्तव में मेरे जीवन में मैंने कभी भी बेकार प्रकार देखा है। –