I am working on an app that saves information about individual runs (Name, date, distance, time, type) into an ObservableCollection.
I've got a viewmodel set up to display this information in a LongListSelector. I've got no problem getting the data into the model, and no problems (at least no errors) saving that information -- for as long as the app is running. I get an exception when restarting the app and attempting to load that information by deserializing it with newtonsoft.json
I am getting the error when trying to the data that was previously serialized and saved to IsolatedStorageSettings.ApplicationSettings
The error message is: 'System.Reflection.TargetInvocationException' in mscorlib.ni.dll
Edit responding to comment seeking more info I'll work on getting the rest of that. I'm new to heavy debugging. The error description is:
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'Run_Ranger.ViewModels.RunSaveMain' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. iCollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path", line1, position1. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract)
at...
and more I can't see. for some reason, I can catch the exception and display it in a messagebox on the emulator (from which I typed that, above, but it's truncated) but when I use debug.writeline, I'm not getting anything in the output window (debug) more than: Exception thrown: 'Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.DLL
It occurs at this line in my code.
private RunSaveMain GetSavedRunsFromMemory() // is this all I need to stick data into the model?
{
//ClearAll();
RunSaveMain data;
string dataFromAppSettings;
if (IsolatedStorageSettings.ApplicationSettings.TryGetValue(SaveRunsKey, out dataFromAppSettings))
{
data = JsonConvert.DeserializeObject<RunSaveMain>(dataFromAppSettings); //<--- ERROR HERE
}
else
{
data = new RunSaveMain();
data.Title = AppResources.SavedRuns;
}
return data;
}
I seem to have no trouble serializing and saving the data to storage. When I debug, I can see it in there, the value looking like this example:
[{"RunName":"Steamtown Marathon 2015","RunType":"real","RunDistMiles":26.2,"RunDate":"2015-10-18T00:00:00","RunTimeTotalSecs":10241.0},{"RunName":"Marine Corps Marathon 2015","RunType":"real","RunDistMiles":26.2,"RunDate":"2015-10-25T00:00:00","RunTimeTotalSecs":10500.0}]
I serialize and save it right after each addition of an item, like so:
private void RunNameCompleted(object sender, string runName, string runType)
{
// name string has already been checked
// create a rundata object
// put in as much info as we want
RunSaveItem RunToSave = new RunSaveItem();
RunToSave.RunName = runName; // various values passed in
RunToSave.RunDate = CurrentPaceMath.Rundate;
RunToSave.RunType = runType;
RunToSave.RunTimeTotalSecs = CurrentPaceMath.TimeTotalSecsIn;
RunToSave.RunDistMiles = CurrentPaceMath.MilesIn;
App.RunSaveItemView.Items.Add(RunToSave); // // add the rundata to app.viewmodels.runmodel
// save the list of runs to isolatedstorage.applicationSettings
var data = JsonConvert.SerializeObject(App.RunSaveItemView.Items);
IsolatedStorageSettings.ApplicationSettings[RunSaveMain.SaveRunsKey] = data;
IsolatedStorageSettings.ApplicationSettings.Save();
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.RelativeOrAbsolute));
}
I wondered if there might be an issue converting the datetime values, so I ran it again without those, and it still crashed at the same line.
The class is set up like this:
public class RunSaveItem : INotifyPropertyChanged
{
private string _runName;
/// <summary>
/// Name of the run
/// </summary>
public string RunName
{
get
{
return _runName;
}
set
{
if (value != _runName)
{
_runName = value;
NotifyPropertyChanged("RunName");
}
}
}
private string _runType;
/// <summary>
/// Type of run
/// </summary>
public string RunType
{
get
{
return _runType;
}
set
{
if (value != _runType)
{
_runType = value;
NotifyPropertyChanged("RunType");
}
}
}
private double _runDistMiles;
/// <summary>
/// Run distance in miles
/// </summary>
public double RunDistMiles
{
get
{
return _runDistMiles;
}
set
{
if (value != _runDistMiles)
{
_runDistMiles = value;
NotifyPropertyChanged("RunDistMiles");
}
}
}
private DateTime _runDate;
/// <summary>
/// Date of the run. There will be no time, or rather, time = 00:00:00 as it's selected with a datepicker.
/// </summary>
public DateTime RunDate
{
get
{
return _runDate;
}
set
{
if (value != _runDate)
{
_runDate = value;
NotifyPropertyChanged("RunDate");
}
}
}
private double _runTimeTotalSecs;
/// <summary>
/// Duration of the run expressed in seconds
/// </summary>
public double RunTimeTotalSecs
{
get
{
return _runTimeTotalSecs;
}
set
{
if (value != _runTimeTotalSecs)
{
_runTimeTotalSecs = value;
NotifyPropertyChanged("RunTimeTotalSecs");
}
}
}
I did a bunch of searching and the only comparable errors I could find seemed to stem from trying to deserialize outside data into the wrong data types. Since I'm using JSON to serialize the right data types directly from the model in the first place, I don't think that's my issue, but I'm stuck for what it might be.
Anyone seen this before?
ToString()output of the exception including the message, exception type, stack trace and inner exception?TargetInvocationExceptionshould have an inner exception. You cancatchthe exception and then see it in the debugger or log it withDebug.WriteLine(ex);