I have a list of type Facility, class below.
I want to take that list which contains objects with parameters and serialize that data into json.
The problem with my current implementation is I get back a list that looks like: [],[],[],[],[] ....but my object has the data in it that I can access like so: _facility[0].FacilityName OR _facility[0].FacilityId. But when I serialize this I am not getting those values.
How do I drill down to get this data and serialize it?
Facility.cs
public class Facility : List<Facility>
{
[Required]
[Display(Name = "Facility")]
public string FacilityName { get; set; }
public string FacilityIdSource { get; set; }
public Facility()
{
// Default Constructor
}
public Facility(string facilityName, string facilityIdSource)
{
this.FacilityName = facilityName;
this.FacilityIdSource = facilityIdSource;
}
}
Code that is called to populate the Facility class
public async Task<string> FacilitiesAsync()
{
ViewBag.SyncOrAsync = "Asynchronous";
var service = new FacilitiesService();
this._facilities = new List<Facility>();
_facilities = await service.GetFacilitiesBySourceDbAsync("param");
string json = "";
for (int i = 0; i < _facilities.Count; i++)
{
json += JsonConvert.SerializeObject(_facilities[i].FacilityName);
}
return json;
}
Now I see the json in my alert box from the complete function in my jQuery. How do I assign this the the array for availableTags?
<script type="text/javascript">
$(function() {
var result = null;
$.ajax({
beforeSend: function () {
alert("Testing");
},
url: "FacilitiesAsync",
success: function (data) {
result = data;
},
complete: function () {
alert(result);
}
});
});
$(function () {
var availableTags = [
// Place results from JSON here
];
$("#tags").autocomplete({
source: availableTags
});
</script>
The default serializer will not serialize properties on objects that implement ICollection.
From the article introducing XML Serialization:
http://msdn.microsoft.com/en-us/library/182eeyhh(v=vs.110).aspx
Items That Can Be Serialized
The following items can be serialized using the XmLSerializer class:
Public read/write properties and fields of public classes.
Classes that implement ICollection or IEnumerable.
Note: Only collections are serialized, not public properties.
XmlElement objects.
XmlNode objects.
DataSet objects.
The DataContractSerializer should handle this correctly.
Related
I've been trying to send an array of objects to a controller method using AJAX, but even after trying various methods I still won't get my desired result. This is my current code:
View
function SaveGame() {
if ('#Session["Username"]' == '#Model.Player1.Username') {
p1 = true;
}
else {
p1 = false;
}
var characters = document.getElementsByClassName("char");
var chardata = [];
for (var i = 0; i < characters.length; i++) {
var id = characters[i].id;
var state = characters[i].classList[1];
chardata.push(id, state);
}
console.log(chardata);
$.ajax({
url: '#Url.Action("SaveGame", "Game")',
type: 'GET',
data: JSON.stringify({ 'character': chardata }),
cache: false,
contentType: 'application/JSON',
success: function (result) {
alert("Game Saved");
}
});
}
Gamecontroller/SaveGame
public bool SaveGame(JsonDecode character)
{
ViewGame game = (ViewGame)TempData["game"];
TempData["game"] = game;
return true;
//return charLayer.SaveCharacters(game.Id, ids, states, isPlayer1);
}
character will just be null
JsonDecode
public class JsonDecode
{
public object[] chardata { get; set; }
}
Your current code is using GET as the type for the $.ajax call. jQuery ajax will issue a GET request to the endpoint with the data appended to the querystring of the URL it is making the call to. When you want to send simple values, it is fine, but when you want to send a complex object like what you want to send, you should use POST type.
Also, for model binding to work, the structure of the data should be similar to your view model structure and property names. Based on the data you want to send, looks like you need a view model like this.
public class GameStateVm
{
public int Id { set;get;}
public string State { set;get;}
}
public class SaveGameVm
{
public GameStateVm[] Character { set;get;}
public bool PFlag { set;get;}
}
which you can use as the parameter of your HttpPost action method.
[HttpPost]
public ActionResult SaveGame(SaveGameVm characters)
{
// I am simply returning the posted data as it is, for testing
// You may return a boolean value if you want that.
return Json(characters);
}
and now in your client side code, make sure your JS object has similar strucutre and property names.
// JS object with same structure as our SaveGameVm
var d = { PFlag: false, character:[]};
d.PFlag = true; // to do : Set the value based on your condition
// dummy code to add 2 items to the array.
// to do : replace with your code to populate the array
for (var i = 0; i < 2; i++) {
var id =i; // to do : replace hard coded values
var state = 'active';
d.character.push({ id: id, state: state});
}
$.ajax({
url: '#Url.Action("SaveGame", "Game")',
type: 'POST',
data: JSON.stringify(d),
contentType: 'application/JSON',
success: function (result) {
console.log(result);
}
});
I'm trying to accomplish the following Tasks:
Create a visual expression/ query builder for ASP.NET-MVC.
Pass the resulting query to DataTables.
This question is about Task 1 as that's where I'm stuck. I have posted Task 2 to provide more background information.
To achieve Task 1 I'm using the jQuery QueryBuilder - a jQuery plugin to create user friendly queries. On the QueryBuilder website there is a listing for .NET under the Backends section (https://querybuilder.js.org/#backends). They recommend to use the dynamic-linq-query-builder by Castle-it (https://github.com/castle-it/dynamic-linq-query-builder).
Here is my issue:
The dynamic-linq-query-builder all seems to be built with static classes. I want to retrieve the data from my database but from my research online I'm not able to initiate a dbcontext within a static class.
Dynamic-linq-query provides a PersonBuilder class to deserialize a JSON data and they include a TestData string:
public static class PersonBuilder
{
public static List<PersonRecord> GetPeople()
{
var result = new List<PersonRecord>();
var testData = TestData;
var personRecords = JsonConvert.DeserializeObject<List<PersonRecord>>(testData);
return personRecords;
}
private static string TestData
{
get
{
return #"
[
{
""FirstName"": ""Jane"",
""LastName"": ""Hansen"",
""Birthday"": ""1969-12-31T16:00:00-08:00"",
""Address"": ""P.O. Box 492, 4607 Tempus, Rd."",
""City"": ""Polatlı"",
""State"": ""Ankara"",
...
...
...
Then in the HomeController they are using the following to filter the query:
[HttpPost]
public JsonResult Index(FilterRule obj)
{
var jsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var people = PersonBuilder.GetPeople().BuildQuery(obj).ToList();
return Json(people);
}
And here is their QueryBuilder implementation and jQuery logic to read out the results.
<script type="text/javascript">
$(function() {
// Handler for .ready() called.
var tableData = [];
var filterDefinition = #Html.Raw(ViewBag.FilterDefinition);
var customFilters = {
condition: 'AND',
rules: []
};
var jqueryQueryBuilder = $('#jquery-query-builder');
var jqueryQueryBuilderDom = jqueryQueryBuilder.queryBuilder({
plugins: ['bt-tooltip-errors', 'filter-description'],
//allow_groups: 0,
allow_empty: true,
filters: filterDefinition,
rules: customFilters,
icons: {
add_group: 'fa fa-plus-square',
add_rule: 'fa fa-plus-circle',
remove_group: 'fa fa-minus-square',
remove_rule: 'fa fa-minus-circle',
error: 'fa fa-exclamation-triangle',
sortable: 'fa fa-exclamation-triangle'
}
});
var convertArraysToCommaDelimited = function(obj) {
if (obj != null) {
if (obj.hasOwnProperty("value")) {
if( Object.prototype.toString.call( obj.value ) === '[object Array]' ) {
obj.value = obj.value.join(", ");
}
}
if (obj.hasOwnProperty("rules") && obj.rules != null) {
for (var i = 0; i < obj.rules.length; i++) {
convertArraysToCommaDelimited(obj.rules[i]);
}
}
}
}
var getRules = function() {
try {
var res = jqueryQueryBuilder.queryBuilder('getRules');
convertArraysToCommaDelimited(res);
return res;
} catch (ex) {
//console.log(ex);
return null;
}
}
var buildTable;
var filterData = function() {
$.ajax({
type: 'POST',
url: "../Home/Index",
data: JSON.stringify(getRules()),
success: function (returnPayload) {
tableData = returnPayload;
buildTable();
console && console.log ("request succeeded");
},
error: function (xhr, ajaxOptions, thrownError) {
console && console.log ("request failed");
},
dataType: "json",
contentType: "application/json",
processData: false,
async: true
});
}
$('#applyFilter').on('click', function() {
filterData();
});
buildTable = function() {
var tbody = $('#data-table tbody'),
props = ["FirstName", "LastName", "Birthday", "Age", "Address", "City", "State", "ZipCode"];
tbody.empty();
$.each(tableData, function(i, reservation) {
var tr = $('<tr>');
$.each(props, function(i, prop) {
$('<td>').html(reservation[prop]).appendTo(tr);
});
tbody.append(tr);
});
};
filterData();
});
</script>
You'll notice that they've created a buildTable function. Later I would like to replace this with a DataTable implementation.
What I've tried:
I have tried to initiate a dbcontext with LINQ in the PersonBuilder class. The issue is that this class was static. I simply removed the static definition of the PersonBuilder class. Here is my implementation:
public List<PersonRecord> GetPeople()
{
IQueryable<PersonRecord> query = DbContext.PersonRecord;
var data = query.Select(asset => new Asset
{
data1 = PersonRecord.data1,
data2 = PersonRecord.data2,
...
...
}).ToList();
return data;
}
The issue I'm experiencing is that the HomeController is now throwing the following error:
CS0120: An object reference is required for the nonstatic field,
method, or property 'member'
At the following line:
var people = PersonBuilder.GetPeople().BuildQuery(obj).ToList();
Not quite sure how to get around this since it seems the entire library is built with static classes?
What do you guys think?
The main problem is that you're defining GetPeople() as non-static method inside PersonBuilder class which marked as static. As noted in MSDN documentation, static classes must contain only static members, including static methods (see the reason here).
The CS0120 error indicates that you should use either static class with static method, or non-static class' instantiated constructor as object. If you want to use non-static method, the class should not marked as static, also the class constructor must be instantiated first before the method can be accessed:
public class PersonBuilder
{
public List<PersonRecord> GetPeople()
{
IQueryable<PersonRecord> query = DbContext.PersonRecord;
var data = query.Select(asset => new Asset
{
data1 = PersonRecord.data1,
data2 = PersonRecord.data2,
// other stuff
}).ToList();
return data;
}
}
Usage
[HttpPost]
public JsonResult Index(FilterRule obj)
{
var jsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var personBuilder = new PersonBuilder(); // add constructor initialization first
var people = personBuilder.GetPeople().BuildQuery(obj).ToList();
return Json(people);
}
Related issue:
How shouldi avoid the CS0120 error in my code?
I have a datatable that I'm converting into a List, serializing it and passing it to my view using a viewmodel.
My viewmodel looks like this:
public class AddressModel
{
public string Addresses { get; set; }
}
My controller action looks like the following:
AddressModel lAddressGeocodeModel = new AddressGeocodeModel();
List<string[]> lAddresses = new List<string[]>();
string lSQL = " select Address1, CityName, StateCode, ZipCode " +
" from AddressTable ";
// Convert the data to a List to be serialized into a Javascript array.
//{
...data retrieval code goes here...
//}
foreach (DataRow row in AddressTable.Rows)
{
string[] lAddress = new string[5];
lAddress[1] = row["Address1"].ToString();
lAddress[2] = row["CityName"].ToString();
lAddress[3] = row["StateCode"].ToString();
lAddress[4] = row["ZipCode"].ToString();
lAddresses.Add(lAddress);
}
lAddressGeocodeModel.UnitCount = lAddresses.Count().ToString();
// Here I'm using the Newtonsoft JSON library to serialize my List
lAddressGeocodeModel.Addresses = JsonConvert.SerializeObject(lAddresses);
return View(lAddressModel);
Then in my view I get the following string of addresses:
[["123 Street St.","City","CA","12345"],["456 Street St.","City","UT","12345"],["789 Street St.","City","OR","12345"]]
How am I supposed to get this serialized string residing in a razor model into a javascript array?
You could directly inject the values into JavaScript:
//View.cshtml
<script type="text/javascript">
var arrayOfArrays = JSON.parse('#Html.Raw(Model.Addresses)');
</script>
See JSON.parse, Html.Raw
Alternatively you can get the values via Ajax:
public ActionResult GetValues()
{
// logic
// Edit you don't need to serialize it just return the object
return Json(new { Addresses: lAddressGeocodeModel });
}
<script type="text/javascript">
$(function() {
$.ajax({
type: 'POST',
url: '#Url.Action("GetValues")',
success: function(result) {
// do something with result
}
});
});
</script>
See jQuery.ajax
Many way to Json Parse but i have found most effective way to
#model List<string[]>
<script>
function DataParse() {
var model = '#Html.Raw(Json.Encode(Model))';
var data = JSON.parse(model);
for (i = 0; i < data.length; i++) {
......
}
}
</script>
This worked for me in ASP.NET Core MVC.
<script type="text/javascript">
var ar = #Html.Raw(Json.Serialize(Model.Addresses));
</script>
Many of these answers do work, but I have found the easiest way by far is to send data through ViewData or ViewBag and let JSON.Net serialize it.
I use this technique when Javascript is needed for HTML generation before the page load or when AJAX overhead needs to be avoided:
In the controller:
public ActionResult MyController()
{
var addresses = myAddressesGetter();
ViewData["addresses"] = addresses ;
return View();
}
In the view:
#section scripts {
<script type="text/javascript">
var MyjavascriptAddresses: #Html.Raw(JsonConvert.SerializeObject(ViewData["addresses"])),
</script>
}
You can always rely on JSON.NET whereas some browsers have poor JSON deserialization support.
Another benefit over some methods in that you can see the Javascript using your browser's View --> Source, since it is simply text generated server-side.
Note that In most situations, Web API a more elegant way to get JSON to the client.
For those trying to do it without using JSON, the following is how I did it:
<script>
var originalLabels = [ '#Html.Raw(string.Join("', '", Model.labels))'];
</script>
I would say it's more a problem of the way you're modeling your data. Instead of using string arrays for addresses, it would be much cleaner and easier to do something like this:
Create a class to represent your addresses, like this:
public class Address
{
public string Address1 { get; set; }
public string CityName { get; set; }
public string StateCode { get; set; }
public string ZipCode { get; set; }
}
Then in your view model, you can populate those addresses like this:
public class ViewModel
{
public IList<Address> Addresses = new List<Address>();
public void PopulateAddresses()
{
foreach(DataRow row in AddressTable.Rows)
{
Address address = new Address
{
Address1 = row["Address1"].ToString(),
CityName = row["CityName"].ToString(),
StateCode = row["StateCode"].ToString(),
ZipCode = row["ZipCode"].ToString()
};
Addresses.Add(address);
}
lAddressGeocodeModel.Addresses = JsonConvert.SerializeObject(Addresses);
}
}
Which will give you JSON that looks like this:
[{"Address1" : "123 Easy Street", "CityName": "New York", "StateCode": "NY", "ZipCode": "12345"}]
Here's how you accomplish that:
//View.cshtml
<script type="text/javascript">
var arrayOfArrays = JSON.parse('#Html.Raw(Json.Encode(Model.Addresses))');
</script>
For one dimension array
Controller:
using Newtonsoft.Json;
var listOfIds = _dbContext.Countries.Where(x => x.Id == Country.USA).First().Cities.Where(x => x.IsCoveredByCompany).Select(x => x.Id).ToList();
string strArrayForJS = JsonConvert.SerializeObject(listOfIds); // [1,2,6,7,8,18,25,61,129]
//Now pass it to the view through the model or ViewBag
View:
<script>
$(function () {
var myArray = #HTML.Raw(Model.strArrayForJS);
console.log(myArray); // [1, 2, 6, 7, 8, 18, 25, 61, 129]
console.log(typeof (myArray)); //object
});
</script>
JSON is valid JavaScript Object anyway, while you are printing JavaScript itself, you don't need to encode/decode JSON further once it is converted to JSON.
<script type="text/javascript">
var addresses = #Html.Raw(Model.Addresses);
</script>
Following will be printed, and it is valid JavaScript Expression.
<script type="text/javascript">
var addresses = [["123 Street St.","City","CA","12345"],["456 Street St.","City","UT","12345"],["789 Street St.","City","OR","12345"]];
</script>
You can directly use the Json.Serialize of the C#
<script type="text/javascript">
var addresses = #Json.Serialize(Model.Addresses);
</script>
i would like to convert each object from my class to observablearray,
My model is something like this :
public class Project
{
public string Soid { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string ProjectTitle { get; set; }
private List<SelectedMembersForTestimonialsModel> _selectedMembersForProject;
public List<SelectedMembersForTestimonialsModel> SelectedMembersForProject
{
internal set { _selectedMembersForProject = value; }
get { return _selectedMembersForProject ?? (_selectedMembersForProject = new List<SelectedMembersForTestimonialsModel>()); }
}
}
TO convert whole class to observablearray,, i tried like this :
var RatingAndTestimonials = function () {
//Make the self as 'this' reference
var self = this;
self.projects = ko.observableArray([]);
Load Data from server to self.projects
//Function to Read All Modules datas
function GetRatingandTestimonialsData(module) {
$.ajax({
type: "POST",
url: "Home.aspx/GetRatingandTestimonialsInfos",
data: "{module : '" + module + "'}",
dataType: "json",
contentType: "application/json",
success: function (response) {
self.PageLoading = ko.observable("none");
$.each(response.d, function (i, data) {
self.projects(data.Projects);
});
}
});
}
to convert each of property from project to observablearry, (specially nested list called :SelectedMembersForProject)
i wrote following things using ko.mapping
var rt = new RatingAndTestimonials();
ko.applyBindings(ko.mapping.fromJS(rt));
but it is not working, can anyone solve my problem?
For a screen I'm working on I pass the model to my .cshtml view first, so:
#model Your.Namespace.Project
Then, in the <script> on the .cshtml view
// serialize model to json
var data = #Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model));
// "Project" being the name of the knockout VM
var vm = new Project(data);
ko.applyBindings(vm);
// definition of project knockout VM
function Project(data) {
// Data
var self = this;
ko.mapping.fromJS(data, {}, self);
}
Now all of your properties are observables, and your lists are observable arrays
Whilst you haven't said what exactly is wrong, you are not adding each project to your view model's array, you are setting the property to that project. You need to use push to add each project to the array:
$.each(response.d, function (i, data) {
self.projects.push(data.Projects);
});
Hi I have this as one of my controllers:
[HttpPost]
public JsonResult GetPinPoints(string Id)
{
Frames rslt = null;
string connString = ConfigurationManager.ConnectionStrings["MongoConnStringNew"].ToString();
MongoUrl murl = new MongoUrl(connString);
MongoServer mgconf = new MongoServer(murl);
try
{
mgconf.Connect();
MongoDatabase frmlydb = mgconf.GetDatabase("framely");
MongoCollection<Frames> collection = frmlydb.GetCollection<Frames>("Frames");
ObjectId oid = new ObjectId(Id);
Frames frms = collection.FindOne(Query.EQ("_id", oid));
if (frms != null)
{
rslt = frms;
}
}
catch (Exception ex)
{
}
finally
{
mgconf.Disconnect();
}
return Json(rslt.CoordinatesObj.ToJson());
}
The mongo object looks like this:
{"MetaTagsObj":{"Meta1":"my fam","Meta2":"lololo","Meta3":"lulz"},"PictureID":"http://framely.s3.amazonaws.com/0b7a9a72-c61b-4dec-a814-40b003072e31.jpg","UserID":"1","CoordinatesObj":[{"Position":1,"Top":182,"Left":20,"Height":73,"Width":90},{"Position":2,"Top":69,"Left":103,"Height":98,"Width":1...
I use an ajax jquery function to call the controller that looks like this:
$("#mybutton").click(function(){
$.ajax({
url: '/Member/GetPinPoints',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(data) {
alert(data);
},
error: function() {
alert("error");
}
});
return false;
});
I dont think I am doing this right, I think it has to do with the way I return the json object. I keep getting this error:
{"Object reference not set to an instance of an object."}
right where I am returning the Json object.
The return Json(myObject) statement should take an object that'll be serialised to JSON then returned to the browser as a string, but by calling ToJson() the rslt.CoordinatesObj object will be serialised twice.
It's also possible CoordinatesObj isn't being deserislised properly, so it's throwing an exception because ToJson() is called on a null object.
The Frames class should look something like this to handle deserialising the CoordinatesObj array:
public class Frames
{
IEnumerable<Coordinate> CoordinatesObj { get; set; }
public class Coordinate
{
int Position { get; set; }
int Top { get; set; }
int Left { get; set; }
int Height { get; set; }
int Width { get; set; }
}
}
If FindOne doesn't find a matching document it returns null, so in your code sample it is entirely possible for the "rslt" variable to be null.
Also:
no need to call Connect, the driver connects automatically
dont' call Disconnect, it interferes
with connection pooling