5

I'm building an OData v3 Web API with Entity Framework 6.0 Code First.

Everything works well and I can execute CRUD operations back to the api server.

However I'm using Spatial Types and some of my entities have DbGeometry properties. When I try to update/post an entity with a DbGeometry type from a client application (just a console application for tests) I get this DataServiceRequestException:

No parameterless constructor defined for this object.

It took me a while but I identified the DbGeometry type as the responsible. I already looked at this topic here and made a custom JsonConverter, where I applied to the property:

[Required]
[JsonConverter(typeof(DbGeometryConverter))]
[Column("geometria")]
public DbGeometry Geometria { get; set; }

That didn't worked. The object is not deserialized on the web api server unless I remove the DbGeometry property.

I also tried to change the Global json serializer behavior

var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
jsonFormatter.SerializerSettings.Converters.Add(new DbGeometryConverter());

Also futile. I really need the DbGeometry properties. What else can I do to work around this issue?

Community
  • 1
  • 1
Eduardo
  • 283
  • 2
  • 9

1 Answers1

0

A little late, but for those who'll seek an answer:

I've managed to do it with the exact same code on a controller level. The idea was taken from this SO Question&Answer.

So, here is the code including the DbGeometryConverter.

DbGeometryConverter.cs:

public class DbGeometryConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsAssignableFrom(typeof(DbGeometry));
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var location = JObject.Load(reader);
        var token = location["Geometry"]["WellKnownText"];
        string geom = token.ToString();

        token = location["Geometry"]["CoordinateSystemId"];
        int srid = token != null ? int.Parse(token.ToString()) : 0;
        var converted = DbGeometry.FromText(geom, srid);
        return converted;
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanWrite => false;
}

CustomJsonAttribute.cs:

public class CustomJsonAttribute : Attribute, IControllerConfiguration
{
    public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
    {
        var formatter = controllerSettings.Formatters.JsonFormatter;
        formatter.SerializerSettings.Converters.Add(new DbGeometryConverter());
    }
}

And [CustomJson] attribute on a controller that uses DbGeometry.

Igor Kleinerman
  • 143
  • 1
  • 8