I have an C# MVC application which stores data as JSON strings in an XML document and also in MySQL DB Tables.
Recently I have received the requirement to store JSON strings in MySQL Database fields, to be converted into C# objects via Newtonsoft.Json, so I decided to implement a TypeConverter to convert JSON strings into custom C# Models.
Unfortunately I cannot use the following command anywhere in my solution to deserialize my JSON strings when the TypeConverter attribute is added to my C# Model:
JsonConvert.DeserializeObject<Foo>(json);
Removing the attribute resolve the issue however this prevents me from converting MySQL DB fields into custom C# objects.
Here is my C# Model with the TypeConverter Attribute added:
using System.ComponentModel;
[TypeConverter(typeof(FooConverter))]
public class Foo
{
public bool a { get; set; }
public bool b { get; set; }
public bool c { get; set; }
public Foo(){}
}
Here is my TypeConverter Class:
using Newtonsoft.Json;
using System;
using System.ComponentModel;
public class FooConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
string s = value.ToString().Replace("\\","");
Foo f = JsonConvert.DeserializeObject<Foo>(s);
return f;
}
return base.ConvertFrom(context, culture, value);
}
}
}
As soon as I add the attribute to the Foo Class I receive the following error:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'Models.Foo' because the type requires a JSON string value to deserialize correctly.
To fix this error either change the JSON to a JSON string value or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
I am using the following string (which works perfectly without adding the TypeConverter Attribute):
"{\"Foo\":{\"a\":true,\"b\":false,\"c\":false}}"
Not sure what's going on here, any ideas?
Many Thanks!!!
UPDATE
I have have discovered that I also have issues with actions on MVC API Controllers that accept the Test Class with Foo as a property or on controllers that accept Foo as an object when the TypeConverter attribute is added to the Foo Class.
Here is an example of a test controller which has issues:
public class TestController : ApiController
{
[AcceptVerbs("POST", "GET")]
public void PostTestClass(TestClass t)
{
// Returns null when TypeConverter attribute is added to the Foo Class
return t.Foo;
}
AcceptVerbs("POST", "GET")]
public void PostFooObj(Foo f)
{
// Returns null when TypeConverter attribute is added to the Foo Class
return f;
}
}
The TypeConverter may be causing issues overriding the WebAPI model binding and returns null when either action above receives JSON via AJAX with the following structure:
// eg. PostTestClass(TestClass T)
{'Foo': {'a': false,'b': true,'c': false}};
// eg. PostFooObj(Foo f)
{'a': false,'b': true,'c': false}
When the TypeConverter Attribute is added to the Foo Class, the following method on the FooConverter TypeConverter class is called as soon the route is found:
public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}
The ConvertFrom method on the FooConverter TypeController is NOT called by the ApiController's action, which may be the cause of the issue.
Again it's a similar situation, where the controllers actions will work fine without the TypeConverter Attribute.
Any further help greatly appreciated!!
Many thanks.
"{\"Foo\":...}"
? – Exam"{\"a\":true,\"b\":false,\"c\":false}"
e.g. without the wrapping"{\"Foo\":...}"
object. This JSON could be deserialized directly usingJsonConvert.DeserializeObject<Foo>(json)
– Exam