I am working on serializing a viewmodel with MVC5 with JsonConvert.SerializeObject and the result is coming up with is an array for each record (e.g. [{PropertyName: Value,...},{PropertyName: Value,...}]. I am trying to fill a slick grid to get the property names dynamically and I have seen others have arrays that have the Property names in one array and then the data rows in another. How can I create [{Column Names},{DataRowValues}] so i can get the property names from this array. I will be deserializing this data as well. I was using this link as a reference, but I am using a List and had trouble making it work Formatting output of Newtonsoft.Json.JsonConvert.SerializeObject(dataSet). Thanks.
[HttpGet]
public JsonResult GeneratePlans()
{
//code here to create and populate view model
return Json(JsonConvert.SerializeObject(viewModel, Formatting.Indented, new JsonSerializerSettings { }), JsonRequestBehavior.AllowGet);
}
On the server, if you need dynamic property resolution, you can use reflection to enumerate the properties and values of your view model.
Since you wish to have your JSON split into an array for property names and an array for property values, we need a class to hold that result. I've left this class deliberately simple since it will just be used for holding values for JSON serialization.
class ObjectPropertyNamesAndValues
{
public List<string> Names { get; set; }
public List<object> Values { get; set; }
}
Here is a function that will populate an instance of ObjectPropertyNamesAndValues given a viewModel instance of any type.
ObjectPropertyNamesAndValues GetObjectPropertyNamesAndValues(object viewModel)
{
if (viewModel == null)
return null;
var result = new JsonObjectPropertyValues();
result.Names = new List<string>();
result.Values = new List<object>();
var propertyInfo = viewModel.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var property in propertyInfo)
{
if (!propertyInfo.CanRead)
continue;
// you can add other checks here, too, such as whether or not
// the property has a certain custom attribute or not
result.Names.Add(propertyInfo.Name);
result.Values.Add(property.GetValue(viewModel));
}
return result;
}
Now you can implement your function like this:
[HttpGet]
public JsonResult GeneratePlans()
{
//code here to create and populate view model
// get the object properties and values for transport as JSON
Debug.Assert(viewModel != null);
var objectPropertyNamesAndValues = GetObjectPropertyNamesAndValues(viewModel);
return Json(JsonConvert.SerializeObject(objectPropertyNamesAndValues, Formatting.Indented, new JsonSerializerSettings { }), JsonRequestBehavior.AllowGet);
}
Related
In the table column (of type nvarchar) I store an array of string values (List <string>). To get a data model I use Entity Framework.
Model:
namespace Project.Models.Atm
{
public class MyObject
{
[JsonIgnore]
public string _Parameters { get; set; }
[NotMapped]
[JsonProperty("parameters")]
public List<string> Parameters
{
get
{
return JsonConvert.DeserializeObject<List<string>>(string.IsNullOrEmpty(_Parameters) ? "" : _Parameters);
}
set
{
_Parameters = JsonConvert.SerializeObject(value);
}
}
}
}
If a new list of string values is assigned to the field of the myObject.parameters object, then I will do everything well.
MyObject myObject = new MyObject();
List<string> parameters = new List<string>();
parameters.Add("value");
myObject.parameters = parameters;
But if you try to add a value to the list of objects one by one, they are not added.
MyObject myObject = new MyObject();
myObject.parameters.Add("value"); <-- The value will not be added and there will be no errors.
What could be the problem?
While executing:
myObject.parameters.Add("value");
you call:
get
{
return JsonConvert.DeserializeObject<List<string>>(string.IsNullOrEmpty(_Parameters) ? "" : _Parameters);
}
and this code is creating new list for you and you are adding to it not to the string that is actually stored in the database.
To avoid temptation of adding to this list change your property to return IEnumerable<string> instead and always assign new list to the property.
I have a list that I prepare in a ViewModel to take values from database table. The list assigned into a model class:
public class DType
{
public string DTName { get; set; }
}
And it get updated by the following method:
public static List<DType> GetDocTypesString(Entity DB, int RKey)
{
return DB.Database.SqlQuery<DType>(#"SELECT * FROM Names
WHERE NK = {0}", RKey).ToList();
}
And then I return the list (model) to the view to list the names into a select menu as the following:
The actual returned model to the view:
public List<DType> ihName { get; set; }
it gets populated by using the method above:
ihName = GetDocTypesString(DB, RKey);
And then, in the view, I use the below:
#Html.Partial("GettingNamesPartial", new ProjName.ViewModels.UploadingPartialViewModel
{
DropdownIHDocType = new SelectList(Model.ihEditorInstanceName)
})
The results are always like this:
Instead to displaying the actual names, the list (select) display:
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
ProjName.ViewModels.DType
The only thing that matches is the number of items is the same as the names on the database table.
Important Note:
Before trying to pull the names from the database, the list worked just fine by hard coding the names like the following:
DropdownIHDocType = new SelectList(new string[] { "Morgan", "Sam", "Shawn" })
ihName = GetDocTypesString(DB, RKey);
is your culprit. your getting a list of document types, not the variable name from each of those documents. basically your showing the class not its content. you need to get access to the actual document, then find the variable you need and assign that to ihName
so you're grabbing DType not DType.DTname which is what i assume your trying to list
I am trying to create a json formatted string using c# in UWP without JSON.Net, but I am just not understanding how to get there. Let's say I wanted to create the following json dynamically:
[{"id":130},{"id":131},{"id":132},{"id":133},{"id":134}]
From everything I have read, it would seem that I need a class that defines the content of my json. For example:
class accountTypes
{
public int id { get; set; }
public string type { get; set; }
}
From there, it would seem that I only need to create a list of type "accountTypes" and then add each "id" to the list.
List<accountTypes> jsonList = new List<accountTypes>();
int numOfChildren = AccountTypesList.Children.Count;
for (int i = 0; i < numOfChildren; i++)
{
if (((CheckBox)AccountTypesList.Children[i]).IsChecked == true)
{
jsonList.Add(new accountTypes() { id = (int)(double)((CheckBox)AccountTypesList.Children[i]).Tag });
}
}
While I am 99% sure that the above code is very flawed, it does not crash on me, so that is a start at least. What I am struggling with now though is how I would serialize the list "jsonList". Everything I have read thus far either points to JSON.net or the JavaScriptSerializer Class, and not Windows.Data.Json. If I could see a simple example on how to serialize json using Windows.Data.Json, then I could at least visualize what is going on with my list and could correct it accordingly. That being said, how do I serialize an array or a list using Windows.Data.Json?
First of all, there's no built-in JSON-serializer that handles all the mapping for you. This is exactly what JSON.NET is doing for you. Therefore, you have to take the manual and long way.
To create exactly this result:
[{"id":130},{"id":131},{"id":132},{"id":133},{"id":134}]
You have to use the JsonArray class. For example, pass your jsonList object to a method like this:
public string ToJson(List<accountTypes> objectList)
{
var jArray = new JsonArray();
foreach (var at in objectList)
{
jArray.Add(ToJson(at));
}
return jArray.ToString();
}
Whereas you use this method to create a JsonObject for your class object itself (as manual step as well):
public JsonObject ToJson(accountTypes at)
{
var jObj = new JsonObject();
jObj.SetNamedValue("id", JsonValue.CreateNumberValue(at.id));
return jObj;
}
I have a list of StudentViewModel object. I am binding this list with a DataGridView, and the column generatation is set to automatic according to the bound model's properties.
public async Task LoadGridView()
{
Tuple<List<StudentViewModel>, int> result = await App.StudentService.SearchAsync(studentRequestModel);
dataGridView1.DataSource = null;
dataGridView1.DataSource = result.Item1;
}
In the StudentViewModel, I have decorated some of the properties with a custom attribute IsViewable.
[AttributeUsage(AttributeTargets.Property)]
public class IsViewable: Attribute
{
public bool Value { get; set; }
}
usage:
[IsViewable(Value = true)]
public string Name { get; set; }
Idea is, just before binding with the UI Control, I want to filter the list and make a new list of anonymous object so that my grid will be populated with only selected properties.
Note: I don't want to create separate view models specific to Grids. I will refactor it if it creates performance issues.
The catch is, I serialized the dynamic list and then deserialized. Then I bind that dynamic list with the datagridview and it worked like a charm.
The whole project can be found here foyzulkarim/GenericComponents
Caller / Usage:
Type type = typeof(StudentViewModel);
PropertyInfo[] properties = type.GetProperties();
var infos = properties.Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(IsViewable))).ToList();
List<StudentViewModel> models = result.Item1;
List<dynamic> list = models.Select(x => GetValue(x, infos)).ToList();
string serializeObject = JsonConvert.SerializeObject(list);
var deserializeObject = JsonConvert.DeserializeObject<List<dynamic>>(serializeObject);
dataGridView1.DataSource = deserializeObject;
I have a JSON object with numerous properties that I am submitting to a C# web service via jQuery.ajax() - it looks something like this:
var obj = {};
obj.LanguageCode = 1031;
obj.Gender = { 'Geschlecht': 'Mann' };
obj.City = { 'Stadt': 'Berlin' };
...
Some properties, like Gender and City, store a localized/translated prompt and response that I want to map to a KeyValuePair. I've tried formatting the Javascript in different ways, but the data only comes through when the datatype is Dictionary - when the datatype is KeyValuePair it doesn't work. For example:
private Dictionary Gender { get; set; } // works: Gender[0] == {[Geschlecht,Mann]}
private KeyValuePair City { get; set; } // doesn't work: City == {[,]}
I can use Dictionary if necessary since it works, but it seems like KeyValuePair is more appropriate and cleaner to use. Can you map Javascript objects to KeyValuePairs, or am I stuck with using Dictionary?
Looks like you need a collection of KeyValuePair objects, not a single one (even though your collection would only have one item) - that's all a Dictionary is, a collection with a few helpers around it.
But personally, I'd recommend building an actual class to represent your values, to organize it a little better - a little more verbose, but I think it's worth it.
// C#
public class LocalAndTranslated {
public string Localized { get;set; }
public string Translated { get;set; }
}
// JS
obj.Gender = { Localized: "Geschlecht", Translated: "Man" };
If you wanted to, you can even go so far as to define a "class" in javascript:
var LocalAndTranslated = (function() {
function LocalAndTranslated(localized, translated) {
this.Localized = localized;
this.Translated = translated;
}
return LocalAndTranslated;
})();
obj.Gender = new LocalAndTranslated("Geschlecht", "Man");