Json deserialize error AggregateException c# - json

I am getting an error trying to move a DataSourceResult from one web service to another... the client calls web service A which resides on our web server. We then make a call to web service B which resides on our db server. The intent is that web service A adds certain sensitive data to the call, that we want hidden behind our firewall... then the call gets handled by web service B, gets a DataSourceResult, and seems to serialize it just fine... note I am using the same set of serilization properties to bot serialize and deserialize, I am just not showing the call to serilize here for brevity. When I go to deserialize this, I get a System.AggregateException - thrown on line "return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;" of my deserialization code... any ideas? anything would be much appreciated :)
Serilize code:
string Serialize<T>(MediaTypeFormatter formatter, T value)
{
// Create a dummy HTTP Content.
Stream stream = new MemoryStream();
var content = new StreamContent(stream);
/// Serialize the object.
formatter.WriteToStreamAsync(typeof(T), value, stream, content, null).Wait();
// Read the serialized string.
stream.Position = 0;
return content.ReadAsStringAsync().Result;
}
Deserialize code:
T Deserialize<T>(MediaTypeFormatter formatter, string str) where T : class
{
// Write the serialized string to a memory stream.
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0;
// Deserialize to an object of type T
return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;
}
Json Object / settings being passed into methods:
var json = GlobalConfiguration.Configuration.Formatters.OfType<System.Net.Http.Formatting.JsonMediaTypeFormatter>().FirstOrDefault();
json.SerializerSettings.Formatting = Formatting.None;
json.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
json.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
json.SerializerSettings.NullValueHandling = NullValueHandling.Include;
json.UseDataContractJsonSerializer = false;
DataSourceResult result = Deserialize<DataSourceResult>(json, loansJson);
I have this string I try to deserialize and it throws this
error:
`System.AggregateException was unhandled by user code
HResult=-2146233088
Message=One or more errors occurred.
Source=mscorlib
StackTrace:
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Deserialize[T](MediaTypeFormatter formatter, String str) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 54
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Get(RelationshipDataSourceRequest request) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 96
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
InnerException: Newtonsoft.Json.JsonSerializationException
HResult=-2146233088
System.AggregateException was unhandled by user code
HResult=-2146233088
Message=One or more errors occurred.
Source=mscorlib
StackTrace:
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Deserialize[T](MediaTypeFormatter formatter, String str) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 54
at Cavatica35.Web.Api.Controllers.RelationshipsGridController.Get(RelationshipDataSourceRequest request) in c:\dev\Cavatica35\Code\MarginMaximizerInteractive\Cavatica35.Web\Api\Controllers\RelationshipsGridController.cs:line 96
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
InnerException: Newtonsoft.Json.JsonSerializationException
HResult=-2146233088
Message=Error converting value "{"$id":"1","Data":[{"$id":"2","Relationship_loanOfficerName":"Deva MMi Admin","guidID":"c4327c4a-7aa5-4503-b738-59a9241a5a1c","name":"New Deva","briefDescription":null,"fullDescription":"","autoRenewLOC":0,"numOfLoans":1,"loanBalance":1000000.0,"numOfDeposits":0,"Relationship_depositbalance":0.0,"numOfOtherRels":0,"otherRelBalance":0.0,"targetROE":0.0,"yearsRemaining":5,"ownedBy":"21973a46-c06e-4ddc-8a94-05bb53c949e6","modBy":"00000000-0000-0000-0000-000000000000","createdBy":"00000000-0000-0000-0000-000000000000","modDate":"12/18/2014","createdDate":"1/1/0001","Relationship_netincome":16955.0,"Relationship_relationshiproe":26.48,"Relationship_avgbalance":1000000.0,"monthsUntilFirstRenewal":"1/1/0001","requiresReview":false,"deleted":false,"extIDList":"","overrideOfficer":false,"selected":false,"ni":16954.908394431,"niOverROE":64028.495587965743,"tag":""}],"Total":1,"AggregateResults":[{"$id":"3","Value":1,"Member":"name","FormattedValue":1,"ItemCount":0,"Caption":null,"FunctionName":"Count_name_28477829","AggregateMethodName":"Count"},{"$id":"4","Value":16955.0,"Member":"Relationship_netincome","FormattedValue":16955.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_netincome_244267","AggregateMethodName":"Sum"},{"$id":"5","Value":26.48,"Member":"Relationship_relationshiproe","FormattedValue":26.48,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_relationshiproe_8060817","AggregateMethodName":"Sum"},{"$id":"6","Value":1000000.0,"Member":"Relationship_avgbalance","FormattedValue":1000000.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_avgbalance_64680392","AggregateMethodName":"Sum"},{"$id":"7","Value":1,"Member":"numOfLoans","FormattedValue":1,"ItemCount":0,"Caption":null,"FunctionName":"Sum_numOfLoans_54078176","AggregateMethodName":"Sum"},{"$id":"8","Value":1000000.0,"Member":"loanBalance","FormattedValue":1000000.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_loanBalance_39749352","AggregateMethodName":"Sum"},{"$id":"9","Value":0,"Member":"numOfDeposits","FormattedValue":0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_numOfDeposits_36660208","AggregateMethodName":"Sum"},{"$id":"10","Value":0.0,"Member":"Relationship_depositbalance","FormattedValue":0.0,"ItemCount":0,"Caption":null,"FunctionName":"Sum_Relationship_depositbalance_1827337","AggregateMethodName":"Sum"},{"$id":"11","Value":16954.908394431,"Member":"ni","FormattedValue":16954.908394431,"ItemCount":0,"Caption":null,"FunctionName":"Sum_ni_60302147","AggregateMethodName":"Sum"},{"$id":"12","Value":64028.495587965743,"Member":"niOverROE","FormattedValue":64028.495587965743,"ItemCount":0,"Caption":null,"FunctionName":"Sum_niOverROE_43813805","AggregateMethodName":"Sum"}],"Errors":null}" to type 'Kendo.Mvc.UI.DataSourceResult'. Path '', line 1, position 3087.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, Encoding effectiveEncoding, IFormatterLogger formatterLogger)
at System.Net.Http.Formatting.JsonMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, Encoding effectiveEncoding, IFormatterLogger formatterLogger)
at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
InnerException: System.ArgumentException
HResult=-2147024809
Message=Could not cast or convert from System.String to Kendo.Mvc.UI.DataSourceResult.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType)
at Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
InnerException: `

Related

AspNet WebApi Polymorphic Parameter via Json $type convention not deserializing

So here's the rub, I am actually doing this in Sitecore, but got so frustrated, I broke out a new boilerplate WebApi project, just to find my problem.
My assertion is that given the following request,
/api/Simple/AspNetJsonDeserializing?instance={%20"$type":%20"SimpleWebApi.Controllers.ConcreteTestInstance,%20SimpleWebApi",%20"hostName":%20"google.com"%20}
I should get a non-null parameter value of ConcreteTestInstance for ITestInstance Instance in my AspNetJsonDeserializing Action Method.
However, Instead I am receiving the following exception:
Cannot create an instance of an interface.
Instead, though if I use my NewtonsoftJsonDeserializing Action Method, and pass it a jsonString and explicitly deserialize it using the Newtonsoft JsonConvert, it will deserialize fine.
What am I doing Wrong?
Here's all the code
The Json
{
"$type": "SimpleWebApi.Controllers.ConcreteTestInstance, SimpleWebApi",
"hostName": "google.com"
}
Controller/Action
[JsonInterfaceBindingAndNonDefaultConstructors]
public class SimpleController : ApiController
{
[System.Web.Http.HttpGet]
public JsonResult<string> NewtonsoftJsonDeserializing(string jsonString) // [FromUri] ITestInstance instance) //
{
JsonSerializerSettings jsonSerializerSettingForTypeHandling = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor };
ITestInstance instance = JsonConvert.DeserializeObject<ITestInstance>(jsonString, jsonSerializerSettingForTypeHandling);
return Json("OK");
}
[System.Web.Http.HttpGet]
public JsonResult<string> AspNetJsonDeserializing([FromUri] ITestInstance instance)
{
return Json($"Uri:{((ConcreteTestInstance)instance)._instanceUri}");
}
}
Attribute for modifying SerializerSettings
[AttributeUsage(AttributeTargets.Class)]
public class JsonInterfaceBindingAndNonDefaultConstructors : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
IEnumerable<JsonMediaTypeFormatter> jsonFormatters = controllerSettings.Formatters.OfType<JsonMediaTypeFormatter>();
foreach (var jsonFormatter in jsonFormatters)
{
jsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver(); //new JsonContractResolver(new JsonMediaTypeFormatter() {});
jsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
jsonFormatter.SerializerSettings.ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor;
}
}
}
Interface
public interface ITestInstance
{
}
Concrete Subclass
public class ConcreteTestInstance : ITestInstance
{
private const string SCHEME = "http://";
private const int PORT = 80;
private const string API_PATH = "/";
private const string QUERYSTRING = "";
public readonly Uri _instanceUri;
public ConcreteTestInstance(string hostName)
{
_instanceUri = new UriBuilder(SCHEME, hostName, PORT, API_PATH, QUERYSTRING).Uri;
}
}
Exception: Cannot create an instance of an interface.
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>Cannot create an instance of an interface.</ExceptionMessage>
<ExceptionType>System.MissingMethodException</ExceptionType>
<StackTrace>
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at System.Web.Http.ModelBinding.Binders.MutableObjectModelBinder.CreateModel(HttpActionContext actionContext, ModelBindingContext bindingContext) at System.Web.Http.ModelBinding.Binders.MutableObjectModelBinder.EnsureModel(HttpActionContext actionContext, ModelBindingContext bindingContext) at System.Web.Http.ModelBinding.Binders.MutableObjectModelBinder.BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) at System.Web.Http.Controllers.HttpActionContextExtensions.Bind(HttpActionContext actionContext, ModelBindingContext bindingContext, IEnumerable`1 binders) at System.Web.Http.ModelBinding.Binders.CompositeModelBinder.BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) at System.Web.Http.ModelBinding.ModelBinderParameterBinding.ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) at System.Web.Http.Controllers.HttpActionBinding.<ExecuteBindingAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.AuthenticationFilterResult.<ExecuteAsync>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
</StackTrace>
</Error>
Just a quick update.
I have changed a few things, which have provided some new results.
First I have switched the AspNetJsonDeserializing attribute to HttpPost.
I have also switched the AspNetJsonDeserializing parameter ITestInstance instance attribute to [FromBody]
Obviously now, this if forcing me to call it via PostMan.
All of this has now removed the exception, but the instance is null. No breakpoints are hit on the ConcreteTestInstance constructors (I added another zero-parameter constructor to validate it both ways).
Here are the changes all together.
[System.Web.Http.HttpPost]
public JsonResult<string> AspNetJsonDeserializing([FromBody] ITestInstance instance)
{
ConcreteTestInstance myConcreteTestInstance = ((ConcreteTestInstance) instance);
return Json($"Uri:{myConcreteTestInstance._instanceUri}");
}
So short story, I am still on the hunt, for why instance is null
Another update.
I have got the code working now with a HttpPost. The problem was the json formatting :FACEPALM:
In PostMan I was using the format
{instance: {
"$type": "SimpleWebApi.Controllers.ConcreteTestInstance, SimpleWebApi",
"hostName": "google.com"
}}
When I removed the instance variable, it corrected the issue.
Also, I tested, and the [FromBody] attribute on the ITestInstance parameter, was irrelevant.
So the issue still remains as to how do I enable this functionality as an HttpGet.
At the moment, when I switch the attribute from HttpPost to HttpGet, I start recieving the exceptions mentioned in the first post.

JSON.NET Exception when deserializing a DateTime value

I reflected the JSON.NET JavaScriptDateTimeConverter class code, copied it, and renamed the class AS3DateTimeConverter so that I could modify it to format DateTime objects in a more precise and strongly-typed manor.
I have it output a type according to how JSON.NET outputs strongly-typed objects like so:
{"$type":"System.DateTime, mscorlib","ticks":0}
The overridden WriteJson method of the JsonConverter runs to produce that value.
However, when I try to deserialize the string using the exact same settings with the same converter, the overridden ReadJson method never gets a chance to run and construct a DateTime from the ticks property, because the following errors occurs:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.DateTime' because the type requires a JSON primitive
value (e.g. string, number, boolean, null) to deserialize correctly.
To fix this error either change the JSON to a JSON primitive value
(e.g. string, number, boolean, null) 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.
Path 'ticks', line 1, position 45.
Is this some kind of bug or limitation, which will not allow me to revive a DateTime type because it is a value-type? Or am I missing something?
Here are the serialization settings:
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
settings.ConstructorHandling = ConstructorHandling.Default;
settings.TypeNameHandling = TypeNameHandling.All;
settings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime;
settings.Converters.Add( new AS3DateTimeConverter() );
//settings.Binder = new AS3SerializationBinder();
string s = JsonConvert.SerializeObject( new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc ), settings );
object o = JsonConvert.DeserializeObject( s, settings ); //s = "{\"$type\":\"System.DateTime, mscorlib\",\"ticks\":0}" //ERROR OCCURS HERE
The problem seems to have something to do with deserializing a bare date. When the Date is wrapped in another object, it seems to work. This code works for me:
public class Program
{
public static void Main(string[] args)
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
settings.ConstructorHandling = ConstructorHandling.Default;
settings.TypeNameHandling = TypeNameHandling.All;
settings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime;
settings.Converters.Add(new AS3DateTimeConverter());
TestObject obj = new TestObject { Date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) };
string s = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine(s);
object o = JsonConvert.DeserializeObject(s, settings);
Console.WriteLine(((TestObject)o).Date.ToString());
}
}
public class TestObject
{
public DateTime Date { get; set; }
}
public class AS3DateTimeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject jo = new JObject();
jo.Add("$type", "System.DateTime, mscorlib");
jo.Add("ticks", ((DateTime)value).Ticks);
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
return new DateTime(jo["ticks"].Value<long>());
}
}
Output:
{"$id":"1","$type":"Q20224027.TestObject, JsonTest","Date":{"$type":"System.DateTime, mscorlib","ticks":621355968000000000}}
1/1/1970 12:00:00 AM
UPDATE
To test the theory of whether converters get called for custom top level objects with embedded type information, I made a converter for the date wrapper object and serialized that instead. This worked, but only if I gave it a hint by using DeserializeObject<T> instead of DeserializeObject. Here is the code:
namespace Q20224027
{
public class Program
{
public static void Main(string[] args)
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
settings.PreserveReferencesHandling = PreserveReferencesHandling.All;
settings.ObjectCreationHandling = ObjectCreationHandling.Replace;
settings.ConstructorHandling = ConstructorHandling.Default;
settings.TypeNameHandling = TypeNameHandling.All;
settings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
settings.DateParseHandling = DateParseHandling.DateTime;
settings.Converters.Add(new DateWrapperConverter());
DateWrapper obj = new DateWrapper { Date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) };
string s = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine(s);
object o = JsonConvert.DeserializeObject<DateWrapper>(s, settings);
Console.WriteLine(((DateWrapper)o).Date.ToString());
}
}
public class DateWrapper
{
public DateTime Date { get; set; }
}
public class DateWrapperConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateWrapper);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DateWrapper obj = (DateWrapper)value;
JObject jo = new JObject();
jo.Add("$type", typeof(DateWrapper).AssemblyQualifiedName);
jo.Add("ticks", obj.Date.Ticks);
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
return new DateWrapper { Date = new DateTime(jo["ticks"].Value<long>()) };
}
}
}
Output:
{"$type":"Q20224027.DateWrapper, JsonTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","ticks":621355968000000000}
1/1/1970 12:00:00 AM
Workaround I found.
If the object is wrapped in a list before being serialized, then it works ok, but only if you decorate the class with a JsonConverter attribute specifying the converter. Adding the converter to the list of converters for the serializers settings is insufficient.
For example, if you have a "Node" class which has a "Child" Node member (i.e. the type has members of it's own type), and you nest some nodes, then what I've found is that the converter is not called during serialization for anything but the top node when you only add the converter to the list of converters. On the other hand, if you explicitly decorate the class with the converter, then all the child nodes are run through the converter's WriteJson method as expected. So this basically renders the "Converters" collection of the serializer's settings non-functional.
When the objects are members of an array and their type is decorated with an explicit converter, then their converter's ReadJson and WriteJson methods are called when the types are encountered during serialization and deserialization.
When receiving a JSON string from a client, there are only two options to get it to work. Either you manually wrap the string in an object including a generic List "$type" and embed the received value as the sole value in the "$values" array, or you must just avoid all this and hard-code the expected recieved object type by calling typed DeserializeObject<T> method. What a mess.
The only reason I can fathom any of this making sense is if the DeserializeObject (non-generic) method was explicitly intended to NOT call converters for the top-level object, presumably so that it could be used in custom converter's WriteJson method without causing recursive calls to the converter. If that's the case, the design is terrible, because it leads to all the problems I've discussed.

mvvmcrosscore valueconverters not invoked

I had written these two converters but they are not' invoked... Do I need to add extra piece of code in minisetup.cs file for them to work
public class BooleanNegationValueConverter : IMvxValueConverter
{
#region IMvxValueConverter implementation
public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (!(Boolean)(value));
}
public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException ();
}
#endregion
I am using this in the usual way
set.Bind(toolbar.hidden).To(vm => vm.toolbarstate).WithConversion("BooleanNegation");
I am using MvvmcrossCore
Figured it out on my own..
//Register the converters
IMvxValueConverterRegistry converterRegistery = ioc.Resolve<IMvxValueConverterRegistry>();
converterRegistery.AddOrOverwrite ("BooleanNegationConverter", new BooleanNegationValueConverter ());
converterRegistery.AddOrOverwrite ("ExchangeRatetoStringValueConverter", new ExchangeRatetoStringValueConverter ());

MySqlDataReader.Read() throws ArgumentOutOfRangeException

I'm working with mysql .net connector 6.4.4 at win7 x64 platform. While reading data from MySqlDataReader Object, it throws exception after 18th row. But in another application I could take 40 rows without errors.
The error is just here:
MySqlDataReader.Read()
Any helps would be very appreciated.
Exception details:
System.ArgumentOutOfRangeException was unhandled
Message=Non-negative number required.
Parameter name: count
Source=mscorlib
ParamName=count
StackTrace:
at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at MySql.Data.MySqlClient.MySqlPacket.Read(Byte[] byteBuffer, Int32 offset, Int32 count)
at MySql.Data.MySqlClient.MySqlPacket.ReadString(Int64 length)
at MySql.Data.Types.MySqlString.MySql.Data.Types.IMySqlValue.ReadValue(MySqlPacket packet, Int64 length, Boolean nullVal)
at MySql.Data.MySqlClient.NativeDriver.ReadColumnValue(Int32 index, MySqlField field, IMySqlValue valObject)
at MySql.Data.MySqlClient.Driver.ReadColumnValue(Int32 index, MySqlField field, IMySqlValue value)
at MySql.Data.MySqlClient.ResultSet.ReadColumnData(Boolean outputParms)
at MySql.Data.MySqlClient.ResultSet.NextRow(CommandBehavior behavior)
at MySql.Data.MySqlClient.MySqlDataReader.Read()
at VeriTasima.Form1..ctor() in E:\Projeler\VeriTasima\VeriTasima\Form1.cs:line 42
at VeriTasima.Program.Main() in E:\Projeler\VeriTasima\VeriTasima\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Updated:
// test
string commandString = "SELECT * FROM haber LIMIT 50";
MySqlConnection connection = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MySQL"].ConnectionString);
MySqlCommand command = new MySqlCommand(commandString, connection);
connection.Open();
MySqlDataReader sdr = command.ExecuteReader();
int count = 0;
while (sdr.Read())
{
count++;
}
sdr.Close();
sdr.Dispose();
command.Dispose();
connection.Close();
connection.Dispose();
MessageBox.Show(count.ToString());
Updated:
I fixed this problem by setting target platfrom from x86 to Any CPU. Now works properly.

How to deserialize simple type with json.net?

Json.net is handy to deserialize object, but I don't know how to use it to deserialize some simple type, such as string, int.
Not sure if I did it right, please help, thank you!
WCF return string looks like
{"PingResult":100}
If call
int result = JsonConvert.DeserializeObject<int>(jsonString);
Unity throw
JsonReaderException: Error reading integer. Unexpected token: StartObject. Path '', line 1, position 1.
Newtonsoft.Json.JsonReader.ReadAsInt32Internal ()
Newtonsoft.Json.JsonTextReader.ReadAsInt32 ()
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonContract contract, Boolean hasConverter)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, Boolean checkAdditionalContent)
You are not deserializing an integer, but an object containing an integer property. You need to provide such a class for the deserialization to work, for example:
class Ping
{
public int PingResult {get; set;}
}
and then call
Ping ping = JsonConvert.DeserializeObject<Ping>(jsonString);
int result = ping.PingResult;
Another approach would be to use the JObject api:
string json="{\"PingResult\":100}";
JObject jo = JObject.Parse(json);
JToken jToken = jo["PingResult"];
int result = (int)jToken;
Deserializing a simple type stored as a string (the title of this question) can be done like this:
private static T ParseStringToTypedValue<T>(string value)
{
if (typeof(T) == typeof(string))
{
return JToken.Parse($"\"{value}\"")
.Value<T>();
}
return JToken.Parse(value)
.Value<T>();
}
This should handle all the basic types, floats, ints, strings etc..