我正在按照John Papa在其最新的PluralSight课程中概述的方法,使用Angular,Breeze和Web API 2构建SPA.
一切运作良好,我可以拉取信息,更新,插入,删除回服务器.但是我正在使用空间类型,当我尝试更新具有空间类型的实体时,我收到以下错误
Newtonsoft.Json.dll中出现"Newtonsoft.Json.JsonSerializationException"类型的异常,但未在用户代码中处理
附加信息:从'System.Data.Entity.Spatial.DbGeometry'上的'WellKnownValue'获取值时出错.
内部异常似乎指向WellKnownValue为空的事实,但它不是,因为我检查了发送到服务器的JSON,然后将其发送到Breeze ContextProvider并使用SaveChanges方法保存.
{ "entities": [ { "TableKey": 2, "CaseName": "Mikhail Lermontov", "StartDate": "2013-06-11T00:00:00Z", "EndDate": null, "IsCurrent": true, "SRID": 109, "Shape": { "$id": "2", "$type": "System.Data.Entity.Spatial.DbGeometry, EntityFramework", "Geometry": { "$id": "3", "$type": "System.Data.Entity.Spatial.DbGeometryWellKnownValue, EntityFramework", "CoordinateSystemId": 2193, "WellKnownText": "POLYGON ((1695943 5462665, 1713098 5462665, 1713098 5449659, 1695943 5449659, 1695943 5462665))" } }, "SpillLocation": "Marlborough Sounds", "Image": "http://www.nzmaritime.co.nz/images/lm5.jpg\r\n", "DefaultBaseMapKey": 2, "__unmapped": { "isPartial": false }, "entityAspect": { "entityTypeName": "DatSpillCase:#Osiris.Model", "defaultResourceName": "DatSpillCases", "entityState": "Modified", "originalValuesMap": { "CaseName": "Mikhail Lermontov" }, "autoGeneratedKey": { "propertyName": "TableKey", "autoGeneratedKeyType": "Identity" } } } ], "saveOptions": {} }
所以我的问题是,可以在NewtonSoft库中反序列化DbGeometry类型,如果没有,有什么建议可以解决这个问题.
上面的答案很有效,但是对于SRID(CoordinateSystemId)2193是硬编码的.然而,坐标系统ID可以出现在问题中所示的序列化数据中,或者它可以出现在WellKnownText"SRID = 2193; POINT(0)中0)".此方法也只会读取多边形,但WellKnownText可以是很多东西,如Geometry Collections,Point,Linestring等.要进行检索,可以更新ReadJson方法以使用更通用的FromText方法,如下所示.以上是使用更通用的坐标系更新的类,也适用于任何几何类型.我还添加了地理版本以供参考.
public class DbGeometryConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsAssignableFrom(typeof(string)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject location = JObject.Load(reader); JToken token = location["Geometry"]["WellKnownText"]; string value = token.ToString(); JToken sridToken = location["Geometry"]["CoordinateSystemId"]; int srid; if (sridToken == null || int.TryParse(sridToken.ToString(), out srid) == false || value.Contains("SRID")) { //Set default coordinate system here. srid = 0; } DbGeometry converted; if (srid > 0) converted = DbGeometry.FromText(value, srid); else converted = DbGeometry.FromText(value); return converted; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // Base serialization is fine serializer.Serialize(writer, value); } } public class DbGeographyConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsAssignableFrom(typeof(string)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject location = JObject.Load(reader); JToken token = location["Geometry"]["WellKnownText"]; string value = token.ToString(); JToken sridToken = location["Geometry"]["CoordinateSystemId"]; int srid; if (sridToken == null || int.TryParse(sridToken.ToString(), out srid) == false || value.Contains("SRID")) { //Set default coordinate system here. //NOTE: Geography should always have an SRID, and it has to match the data in the database else all comparisons will return NULL! srid = 0; } DbGeography converted; if (srid > 0) converted = DbGeography.FromText(value, srid); else converted = DbGeography.FromText(value); return converted; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // Base serialization is fine serializer.Serialize(writer, value); } }
System.Data.Spatial.DbGeometry
不能很好地发挥 Newtonsoft.Json
你需要创建一个JsonConverter
转换DbGeometry
public class DbGeometryConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsAssignableFrom(typeof(string)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject location = JObject.Load(reader); JToken token = location["Geometry"]["WellKnownText"]; string value = token.ToString(); DbGeometry converted = DbGeometry.PolygonFromText(value, 2193); return converted; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // Base serialization is fine serializer.Serialize(writer, value); } }
然后在模型中的属性上添加属性
[JsonConverter(typeof(DbGeometryConverter))] public DbGeometry Shape { get; set; }
现在当你点击你的BreezeController时,反序列化将由我们新的DbGeometryConverter处理.
希望能帮助到你.