I want to add a property to the List in C#, then I want to create a JObject to set the value and sum some values after, then I need to convert my List <Object> to a JArray, then to I want To add my jsonObject to JArray, then to return my JArray in Json form for display on screen or to go througt the JsonArray to show each result on a javascript table, but at the end the only thing I get is this error:
"Uncaught TypeError: Cannot use 'in' operator to search for 'length'
in [{"client":{"id":1001,"debtJanuary":500000"....
double total = 0;
JArray jsonarray = null;
JObject jsonobject = null;
List<ClientAccount> list = null;
try
{
list = ClientBussinesLayer.getListClientCash(id);
for(ClientAccount item in list)
{
total += item.debtJanuary + item.debtFebruary + item.debtMarch;
}
jsonobject = new JObject();
jsonobject.Add("totalDebt", total);
jsonobject.Add("statusList", "success");
jsonarray = JArray.FromObject(list);
jsonarray.Add(jsonObject);
}catch(Exception ex)
{
error
}
return JsonConvert.SerializeObject(jsonarray);
fnSuccessList: function (data) {
var strHtml = '';
var list = jQuery.parseJSON(data); //also i tried with data.d but dont work
$.each(list, function (index, item) {
strHtml += '<tr>';
strHtml += ' <td>' + item.debtJanuary + '</td>';
strHtml += ' <td>' + item.debtFebruary + '</td>';
strHtml += ' <td>' + item.debtMarch + '</td>';
strHtml += '</tr>'
});
$("#table").append(strHtml);
}
You should use foreach loop instead for:
foreach(var item in list)
{
total += item.debtJanuary+item.debtFebruary + item.debtMarch;
}
Related
Can somebody help me to get the custom JSON string from datatable using C#.
I need something like below.I am able to achive this by using for each loop.
[
{"message": {"alert": "Address Updated"},"target": {"userIds": ["BKAC7759"]}},
{"message": {"alert": "Payment Processed"},"target": {"userIds": ["BKAC7759"]}},
{"message": {"alert": "Notice Sent"},"target": {"userIds": ["BKAC7759"]}}
]
But is there any way i can make it in simple way. My datatable contains values for "alert" and "userIds"
private string GetJsonData(int numberofRecords)
{
// OleDbConnection conn = new OleDbConnection(connectionString);
try
{
DataTable Test = new DataTable("A");
Test.Columns.Add("alert");
Test.Columns.Add("userIds");
Test.Rows.Add("Address Updated", "BKAC7759");
Test.Rows.Add("Payment Made", "BKAC7759");
//Test.Rows.Add("Check Processed", "MAND1884");
//Test.Rows.Add("Notice Mailed", "JAID3869");
//Test.Rows.Add("DL Suspended", "AOQU4798");
string jo = string.Empty;
string com = ",";
int i = 0;
int count = Test.Rows.Count;
string bracketright = "]";
string bracketleft = "[";
foreach (DataRow row in Test.Rows)
{
if (i == 0)
{
jo = jo + bracketleft;
}
jo = jo + "{\"message\":{\"alert\":\"" + row[0].ToString() + "\"},\"target\":{\"userIds\":[\"" + row[1].ToString() + "\"]}}";
if (i != count - 1)
{
jo = jo + com;
}
else
{
jo = jo + bracketright;
}
i++;
}
return jo;
}
catch (Exception ex)
{
Logger.Error("GetJsonData(int numberofRecords): " + ex.Message);
return string.Empty;
}
finally
{
// always close the connection.
// conn.Close();
}
}
You can use Linq + DataTableExtensions (in namespace System.Data and system DLL System.Data.DataSetExtensions.dll) to transform your table into an enumerable of anonymous types, then serialize that to JSON with json.net.
I notice your "userIds" property is a JSON array. Do you want all the user userIds for a given alert to be combined? If so, you can use ToLookup to combine them:
var root = dataTable.AsEnumerable()
.ToLookup(r => r["alert"].ToString(), r => r["userIds"].ToString())
.Select(g => new { message = new { alert = g.Key }, target = new { userIds = g } });
var json = JsonConvert.SerializeObject(root);
If not, do:
var root = dataTable.AsEnumerable()
.Select(r => new { message = new { alert = r["alert"].ToString() }, target = new { userIds = new [] { r["userIds"].ToString() } } });
var json = JsonConvert.SerializeObject(root);
For the following table:
var dataTable = new DataTable("A");
dataTable.Columns.Add("alert");
dataTable.Columns.Add("userIds");
dataTable.Rows.Add("Address Updated", "BKAC7759");
dataTable.Rows.Add("Payment Made", "BKAC7759");
dataTable.Rows.Add("Address Updated", "MAND1884");
dataTable.Rows.Add("Payment Made", "MAND1884");
The first produces the following JSON:
[
{"message":{"alert":"Address Updated"},"target":{"userIds":["BKAC7759","MAND1884"]}},
{"message":{"alert":"Payment Made"},"target":{"userIds":["BKAC7759","MAND1884"]}}
]
And the second produces the following:
[
{"message":{"alert":"Address Updated"},"target":{"userIds":["BKAC7759"]}},
{"message":{"alert":"Payment Made"},"target":{"userIds":["BKAC7759"]}},
{"message":{"alert":"Address Updated"},"target":{"userIds":["MAND1884"]}},
{"message":{"alert":"Payment Made"},"target":{"userIds":["MAND1884"]}}
]
i hope you can give me a hint for my problem i have with my code.
I have a DataGridView which got its Data from an Excelfile.
Now to get structure in it, i want to make groups (keyword in dsdslls) and add valueNames (value of dsdslls and keyword in dslls) to that groups and add that content (value of dslls) to valueNames as KeyValuePair.
My Problem is not to add all that stuff, but to get it back.
here is the code (add stuff):
internal Dictionary<String, Dictionary<String, LinkedList<String>>> BuildList(DataGridView dgv)
{
//create the main Dictionary
Dictionary<String, Dictionary<String, LinkedList<String>>> dsdslls = new Dictionary<String, Dictionary<String, LinkedList<String>>>();
String groupName = "Project data", value = "", valueName = "", text = "";
//run through the whole list
for (int i = 0; i < dgv.RowCount - 1; i++)
{
//create new Dictionary for the Content
Dictionary<String, LinkedList<String>> dslls = new Dictionary<String, LinkedList<String>>();
//check if the String at i is a groupName, if so add it to groupName
if (isGroupName(dgv, i))
{
groupName = dgv.Rows[i].Cells[0].Value.ToString();
text = "Adding in group: " + groupName + " to value: ";
}
//now go forward in the list until you next Cell is empty or the list ended
do
{
//check if the String at i is a valueName, if so add it to valueName
if (isValueName(dgv, i))
{
//create the LinkedList for units and values
LinkedList<String> lls = new LinkedList<String>();
valueName = dgv.Rows[i].Cells[0].Value.ToString();
//check if group and valuename are NOT the same
if (isNotSame(valueName, groupName))
{
//now run the colums for units and values and add them to the List until you reach the end of used columns
int j = 0;
do
{
value = dgv.Rows[i].Cells[1 + j].Value.ToString();
lls.AddLast(value);
if (j == 0)
{
text += "\n" + valueName + " in (" + lls.First.Value.ToString() + "): ";
}
else
{
text += lls.Last.Value.ToString();
}
j++;
} while (j < dgv.Rows[i].Cells.Count - 1);
//add the valueName and List as new keyvaluepair to the dictionary.
dslls.Add(valueName, lls);
}
}
i++;
} while (!isStringEmpty(dgv.Rows[i].Cells[0].Value.ToString()) && i < dgv.RowCount - 1);
//show added content
MessageBox.Show(text);
//check if main dictionary contains the latest groupname, if not add the groupName and the last dictionary to the main dictionary
if (!dsdslls.ContainsKey(groupName))
{
dsdslls.Add(groupName, dslls);
}
}
MessageBox.Show("Building successfully finished.");
return dsdslls;
}
I'm not getting the right content back to the specified groupName... for example:" groupName = "Project Data" i got back the content of the group:" Electrical Network" which is the next keyword in the maindictionary
now the code to get the Data:
internal void /*Dictionary<String, LinkedList<String>>*/ GetGroupContent(Dictionary<String, Dictionary<String, LinkedList<String>>> dsdslls, String groupName)
{
//Dictionary<String, LinkedList<String>> dslls = new Dictionary<String, LinkedList<String>>();
String groupN = "", text = "";
//Check if Dictionary contains groupName
if (dsdslls.ContainsKey(groupName))
{
//run through the dictionary
foreach (var s in dsdslls)
{
//give back the keyword (just for the MessageBox)
if (s.Key == groupName)
{
groupN = s.Key;
}
else
{
//run throught the little dictionary to get the keywords from it.
foreach (var t in s.Value)
{
text += t.Key + "\n";
}
}
}
MessageBox.Show("Content of Group " + groupN + ": \n" + text);
text = "";
}
//return dslls;
}
Kind regards
Mirko
It is hard to understand what you expect from this code as the main problem is not well described.
Anyway, it seems that there might be problem in your data retrieval logic.
If you want to get data of group with matching name, then you have to move else part of your if statement. You need to do text concatenation only when group with correct name is found.
...
//give back the keyword (just for the MessageBox)
if (s.Key == groupName)
{
groupN = s.Key;
//run throught the little dictionary to get the keywords from it.
foreach (var t in s.Value)
{
text += t.Key + "\n";
}
}
...
I have an autocompleteextender which works very fine when i set its innerHtml to text received from the webservice a i can catch the selected value of that text on selectedItem function . but when i set some HTML elements inside innerHtml of the childnode i loss the value of that node on selectedItem function (to keep on mind that i can see set value on OnClientPopulated function !).
here is OnClientPopulated
function PopulateDataForAce_Locations(sender) {
$("#tbxLocation").css("background-image", "none");
var comletionList = $find("aceYer").get_completionList();
for (var i = 0; i < comletionList.childNodes.length; i++) {
var data = JSON.parse(comletionList.childNodes[i].innerText);
var image = data[0];
var imageClass = "";
var textClass = "";
if (data[1].indexOf("##") > -1 || comletionList.childNodes[i]._value == "0000") {
imageClass = "imageStyleIlce";
textClass = "textStyleIlce";
}
else {
imageClass = "imageStyleIl";
textClass = "textStyleIl";
}
var text = data[1].replace("##", "");
var text2 = data[2];
// comletionList.childNodes[i].innerHTML = "<font class=\"" + textClass + "\">" + text + "</font>";
comletionList.childNodes[i].innerHTML = text;
}
}
when i use the comment line i lose the value of the node.
any help is appreciated
the only way that i found to get the value on selected item function was
function aceLocation_itemSelected(sender, e) {
var index = $find("aceYer")._selectIndex;
var _item = $find("aceYer").get_completionList().childNodes[index];
var hfYer = $get('<%= hfYer.ClientID %>');
hfYer.value = _item._value;
}
while e.get_value() did not work with html item.
I have a C# List that I want to create a comma separate string. I've found other answers on SO that deal with this, but my particular case I want to only use a portion of the values in the List to create the string.
If my List contained these values:
"Foo"
"Bar"
"Car"
and I wanted to create a string
Foo, Bar and Car.
I could use this code:
string.Format("{0} and {1}.",
string.Join(", ", myList.Take(myList.Count - 1)),
myList.Last());
However, my list is actual formed of jSON values like so
{ Name = "Foo" }
{ Name = "Bar" }
{ Name = "Car" }
So the above code results in:
{ Name = "Foo" }, { Name = "Bar" } and { Name = "Car" }.
How would I construct the string such that I only use the Foo, Bar and Car values in the list?
Update
Thanks to #StevePy, this is what I ended up with:
string.Format("{0} and {1}.",
string.Join(", ", myList.Select(x => x.Name).ToList().Take(myList.Count - 1)),
myList.Select(x => x.Name).ToList().Last());
If you need to operate with strings, just grab the necessary part of each string with, for example, String.IndexOf and String.LastIndexOf methods:
List<string> myList = new List<string> {
"{ Name = \"Foo\" }",
"{ Name = \"Bar\" }",
"{ Name = \"Car\" }"
};
var temp = myList.Select(x =>
{
int index = x.IndexOf("\"") + 1;
return x.Substring(index, x.LastIndexOf("\"") - index);
})
.ToList();
string result = string.Format("{0} and {1}.",
string.Join(", ", temp.Take(myList.Count - 1)),
temp.Last());
Linq should help.
var nameList = myList.Select(x=>x.Name).ToList();
you can use JsonConvert.toString to get the value of your list item, or if you used a json serialization, you could use the JsonConvert.Deserialization
I built a method that will do this for you:
static string ConvertToMyStyle(List<string> input)
{
string result = "";
foreach(string item in input)
{
if(input.IndexOf(item) != input.ToArray().Length-1)
result += item + ", ";
else
result += "and " + item + ".";
}
return result;
}
this handles the single item case
protected string FormatWithOxfordCommas(List<string> reasons)
{
string result = "";
if (reasons.Count == 1)
result += reasons[0];
else
{
foreach (string item in reasons)
{
if (reasons.IndexOf(item) != reasons.Count - 1)
result += item + ", ";
else
result += "and " + item + ".";
}
}
return result;
}
On my GetBusiness.aspx page i have create a test list
List<string> l = new List<string>();
l.Add("one");
l.Add("two");
l.Add("three");
l.Add("four");
l.Add("five");
// B.
string[] s = l.ToArray();
Response.Write(s);
No on my second page(default aspx page) I have some jQuery to load this array and show the results:
$.get('GetBusiness.aspx', function (returndata) {
// for each address in returndata
alert(returndata);
but the result is : System.String[]
If I iterate , he iterate the string "System.String[]"
$.each(returndata, function (index, value) {
alert(index + ': ' + value);
};
How can I show the results from the string array?
Change Response.Write(s) to :
JavaScriptSerializer objSerializer = new JavaScriptSerializer();
Response.Write(objSerializer.Serialize(s));
Reference: JavaScriptSerializer
In your GetBusiness page, you are outputting the .ToString() property of the array, which is "System.String[]". You need to iterate the list and output each element separatly in some usable format, like JSON and then parse appropriately.
Example (untested):
string reponse = "";
response += "{ \"Output\":[";
for(int i = 0; i < s.Length; i++) {
response += s[i];
if (i < s.Length - 1) response += ", "
}
response += "] }";
Response.Write(response);
List<string> l = new List<string>();
l.Add("one");
l.Add("two");
l.Add("three");
l.Add("four");
l.Add("five");
// B.
string[] s = l.ToArray();
Response.Write(string.Join(",", s));
javascript:
$.get('GetBusiness.aspx', function(returndata) {
var arr = returndata.split(',');
$.each(arr, function(index, value) {
alert(index + ': ' + value);
});
});