user6201138 user6201138 - 1 year ago 128
C# Question

Web Api Ignoring Custom JsonConverter for DbGeography

Major struggles with this. So I'm trying to send nested Json data to my web api. I have a custom son converter for my DbGeography type. However, when i send my request, it seems like my custom converter is never called. I get error saying: Unable to cast object type Object to DbGeography. I am using a database first EF for my data model.
Commenting out the locationAccountCreated property, everything else works fine and the data is persisted successfully to the database.

Please any help would be very much appreciated.

Please relevant see code below


public HttpResponseMessage PostNewAccount([FromBody]IDictionary<string, object> formData)
if (formData != null)
var nValueCol = formData;

var account = new Account()
Email = (string)nValueCol["email"],
Password = (string)nValueCol["password"],
AgreedToTerms = Convert.ToBoolean(nValueCol["agreesToTerms"]),
LocationAccountCreated = (DbGeography)nValueCol["userLocation"]//source of error
//LocationAccountCreated = (DbGeography)(IDictionary<string, IDictionary<string, double>>)nValueCol["userLocation"]

// of code unrelated to problem

Custom Conveter

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) // checks if token is null.
return default(DbGeography);

var jObject = JObject.Load(reader);

if (!jObject.HasValues || (jObject.Property(LATITUDE_KEY)) == null || (jObject.Property(LONGITUDE_KEY)) == null) //checks if Json Object is null, and if longitude or latitude properties are null
return default(DbGeography);

string wellKnownText = string.Format("POINT({0} {1})", jObject[LATITUDE_KEY], jObject[LONGITUDE_KEY]);
return DbGeography.FromText(wellKnownText, 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 });

public class QueryLocationMetadata
public virtual System.Data.Entity.Spatial.DbGeography LocationAccountCreated { get; set; }

Partial Class

public partial class Account


protected void Application_Start()
var config = GlobalConfiguration.Configuration;

//Registering routes from the WebApi.Config file

//Registering Autofac

//Registering Formatter
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new DbGeographyConverter());

Fiddler Request


User-Agent: Fiddler
Content-type: application/json
Host: localhost:9576
Content-Length: 316

"userName" : "Cool User",
"gender" : "Female",
"userLocation": {"geopoint":{"latitude" : 40.334910, "longitude" : -32.254586}}

Answer Source

Try inserting it as the first provider:

config.Formatters.JsonFormatter.SerializerSettings.Converters.Insert(0, new DbGeographyConverter());

I tried this in a Web Api 2 Controller with your converter code like this:

public void Post([FromBody]System.Data.Entity.Spatial.DbGeography value)

Take care of number formatting issues also. The WKT part might need to look something like this:

string wellKnownText = string.Format("POINT({0} {1})", jObject[LATITUDE_KEY].Value<double>().ToString(System.Globalization.NumberFormatInfo.InvariantInfo), jObject[LONGITUDE_KEY].Value<double>().ToString(System.Globalization.NumberFormatInfo.InvariantInfo));