Receive JSON in MVC controller - c#

This is my first time using JSON and I'm having a bit of trouble parsing and using it in my controller. I already tried these solutions Unable to successfully receive JSON data to .NET MVC Controller, How to receive JSON as an MVC 5 action method parameter, but none of them made it for me.
I'm retrieving some data from my html and sending the arrays through ajax to the controller in the following code:
JQuery:
var values = $('ul#values li').map(function() {
return this.textContent;
}).get()
var lines = $('ul#lines li').map(function() {
return {
Column: this.textContent,
Table: this.getAttribute("name")
};
}).get();
var columns = $('ul#lines li').map(function() {
return {
Column: this.textContent,
Table: this.getAttribute("name")
};
}).get();
var filters = $('ul#filters li.panel').map(function () {
var n = this.getAttribute("name");
var c = $(this).children()[1].textContent;
var r = $(this).find("li input:checked").map(function() {
return this.parentNode.textContent;
}).get();
if (r.length === 0)
return null;
else
return { table: n, name:c, vals: r };
}).get();
$.ajax({
type: "POST",
url: "/Home/PivotTable",
dataType: "json",
traditional: true,
data: {
indicators: values,
lines: JSON.stringify(lines) ,
columns: JSON.stringify(columns),
filters: JSON.stringify(filters)
},
success: function (data) {
alert(data.s, data.l);
}
});
And this is the form data being posted:
indicators: Taxa Mensal de inflação
lines:[{"Column":" Base","Table":"D_Base"}]
columns:[{"col":" Trimestre","table":"D_Calendario"}]
filters:[{"table":"D_PF_ClasseProdutos","name":" Código","vals":[" 22"," 23"]}]
And receiving the data in the controller where I need to access the data:
public JsonResult PivotTable(string[] indicators, Lines[] lines, object[] columns, object[] filters)
{
string sa = indicators[0];
var l = lines;
var col = columns;
var fil = filters;
var result = new { s = sa, l=l[0].Column};
return Json(result, JsonRequestBehavior.AllowGet);
}
public class Lines
{
public string Column { get; set; }
public string Table { get; set; }
}
I tried binding lines to an object, like the solution in one of the links, but got
NullRefrenceException was unhandled by usercode
While the other parameters receive the appropriate
data, but i can´t access the properties of the object.
What am I doing wrong, and how can i parse the data or bind it to an object?

You can try to use Json.NET library which allows you to serialize and deserialize.
Pass your params as string and do the following:
Lines[] m = JsonConvert.DeserializeObject<Lines>(lines);

Related

IActionResult not returning the view

So, i call trhough Ajax an IActionResult to go to another view and the IActionResult executes entirely except that it doesn't return the view.
Here is the code of the action result, it just take some products and search for their prices on the database and then sums them. And it executes perfectly. I changed the code a little to some lines to show me the values of each variable in the console and it works fine. The only problem is that when it suppose to show the view in the browser, nothing happens
[HttpPost]
public IActionResult Cart(List<int[]> carrito){
var productsToBuy = selectProductsByID(carrito);
var detallesOrden = new List<OrderDetailModel>();
int sumaTotal = 0;
for(int i = 0; i<carrito.Count; i++){
var detalle = new OrderDetailModel{
idProduct = carrito[i][0],
cantidad = carrito[i][1],
subTotal = productsToBuy[i].precio * carrito[i][1]
};
sumaTotal += detalle.subTotal;
}
var orden = new OrderModel{
estado = 0,
sumaTotal = sumaTotal
};
ViewBag.ProductsToBuy = productsToBuy;
ViewBag.DetallesOrden = detallesOrden;
ViewBag.Orden = orden;
return View();
}
This is the function which i use to call the actionresult it sends an array with the products id and their quantities
function goToCart(){
showCart();
var target = '#Url.Action("Cart", "Home")';
$.ajax({
type: 'POST',
data:{
carrito: carrito
},
url: target,
success: function(result){
},
error: function(result){
alert('error');
}
});
}
What am i doing wrong? I'll appreciate any kind of help.
Sorry for the combinnation of english and spanish.

JQuery loop slowing Google Chart performance

I have a google chart, that generally is very slow (over 5 minutes) and sometimes just crashes depending on the number of series I need to show. If I have one series it takes around 10 seconds, but if I add say 20 series, it will take several minutes any more than that and the browser dies.
Each series has around 8,000 rows from the JSON. I have checked and tested the code and the loop in the chart code is killing it.
My chart code is as follows:
function drawMultiLineChart() {
var section = $('#LocationNameDdl :selected').val();
var uid = '#guid';
var from = $('#dateFrom').val();
var to = $('#dateTo').val();
var parsedData = "";
var dName = "";
var colIndex = "";
var result = "";
var rowIndex = "";
$.ajax({
url: 'ProjectCharts/GetChartDataBySection',
datatype: 'json',
type: 'get',
async: false,
data: { section: section, uid: uid, from: from, to: to },
contentType: 'application/json; charset=utf-8',
success: function (d) {
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
parsedData = $.parseJSON(d);
dName = new google.visualization.DataTable();
dName.addColumn('date', 'Date');
$.each(parsedData, function (key, value) {
colIndex = dName.addColumn('number', 'Serial: ' + key);
result = $.parseJSON(value);
$.each(result, function (k, v) {
rowIndex = dName.addRow();
dName.setValue(rowIndex, 0, new Date(v.ReadingDate));
dName.setValue(rowIndex, colIndex, Number(v.ReadingValue));
});
});
var options = multiLineChartOptions();
var chart = new google.visualization.LineChart(document.getElementById('chart'));
chart.draw(dName, options);
});
},
error: function () {
alert("Error");
}
});
};
I call the JSON from the following code, this is fine and performs very quickly:
public async Task<JsonResult> GetJsonChartData(string serial, string uid, string from, string to)
{
var dateFrom = Convert.ToDateTime(from).ToString("yyyy-MM-dd HH:mm:ss");
var dateTo = Convert.ToDateTime(to).ToString("yyyy-MM-dd HH:mm:ss");
var g = new GetChartData(_configuration);
List<ChartDataModel> items = await Task.Run(() => g.GetChartDataFromSqlServer(serial, uid, dateFrom, dateTo));
return Json(JsonConvert.SerializeObject(items, Formatting.Indented));
}
The JSON:
[{"LoggerId":"1000651443","ReadingDate":"2018-12-05 00:03:03, "ReadingValue":"12.6", "Tooltip":"Someinfo"},
{"LoggerId":"1000651447","ReadingDate":"2018-12-05 00:04:03, "ReadingValue":"12.7", "Tooltip":"Someinfo"}]
[{"LoggerId":"1000651444","ReadingDate":"2018-12-05 00:03:05, "ReadingValue":"12.9", "Tooltip":"Someinfo"},
{"LoggerId":"1000651445","ReadingDate":"2018-12-05 00:03:07, "ReadingValue":"14.9", "Tooltip":"Someinfo"}]
[{"LoggerId":"1000651446","ReadingDate":"2018-12-05 00:03:17, "ReadingValue":"13.6", "Tooltip":"Someinfo"},
{"LoggerId":"1000651446","ReadingDate":"2018-12-05 00:04:17, "ReadingValue":"43.6", "Tooltip":"Someinfo"}]
How can I improve not only the performance but the load time?
Should I be using a different charting tool?
Can I process the data server side that will allow for increased performance?

WebMethod is returning name of variable, not the array

This is driving me crazy... as part of another issue I've been working on ajax transfers to my mvc4 web app.
I've been working with this as an example: http://www.codeproject.com/Articles/692793/Introduction-to-Knockout-js-and-CRUD-Operations-in
The model is as follows:
public class ColorList
{
public int? ID;
public string ColorName;
}
The controller function is as follows:
[WebMethod]
public ColorList[] GetAssignedColors(string szUserRecID)
{
int Rec = Convert.ToInt32(szUserRecID);
var query = (from t in db.tblColors
join c in db.tblUser on t.fkColorID equals c.pkColorID
where t.fkRecID == Rec
select new ViewModels.ColorList()
{
ColorName = c.szColorName,
ID = t.ColorID
}).OrderBy(c => c.ColorName);
//var q = query.ToArray(); // if I break and view q, the array exists
return query.ToArray();
}
Not sure this matters but here's my Ajax method:
$.ajax({
type: "POST",
url: '#Url.Action("GetAssignedColors", "EditColors")',
data: { szUserRecID: RecID },
success: function (results) {
var colors = $.map(results.d, function (item) {
return new Color(item)
});
self.CurrentColors(colors);
},
error: function (err) {
alert(err.status + " : " + err.statusText);
}
})
if I watch fiddler the response my code provides is (in text view):
"MyApps.ViewModels.ColorList[]"
Not the array of colors as I am expecting.
Why is the function returning the variable name as an array instead of the array itself?
I've played around with this, but my ajax call doesn't seem to interpret the json response... However, the data shows in this instance but get a 200/ok with seemingly unusable data in my web page.
[HttpPost]
public JsonResult GetAssignedColors(string szUserRecID)
{
int Rec = Convert.ToInt32(szUserRecID);
var query = (from t in db.tblColors
join c in db.tblUser on t.fkColorID equals c.pkColorID
where t.fkRecID == Rec
select new ViewModels.ColorList()
{
ColorName = c.szColorName,
ID = t.ColorID
}).OrderBy(c => c.ColorName);
//var q = query.ToArray(); // if I break and view q, the array exists
return Json(query.ToArray(), JsonRequestBehavior.AllowGet);
}
Since formatting didn't work in the comments this is what worked; results didn't have the data necessary but "data" did.
success: function (data) {
var colors = $.map(data, function (item) {
return new Color(item)
});
The webpage I was working off of had:
success: function (result) {
var colors = $.map(result.d, function (item) {
return new Color(item)
});
The actual working method was:
success: function (data) {
var colors = $.map(data, function (item) {
return new Color(item)
});
I did not use the [webmethod] per Robert's wisdom and used the json response.
The final / working function was:
[HttpPost]
public JsonResult GetAssignedColors(string szUserRecID)
{
int Rec = Convert.ToInt32(szUserRecID);
var query = (from t in db.tblColors
join c in db.tblUser on t.fkColorID equals c.pkColorID
where t.fkRecID == Rec
select new ViewModels.ColorList()
{
ColorName = c.szColorName,
ID = t.ColorID
}).OrderBy(c => c.ColorName);
//var q = query.ToArray(); // if I break and view q, the array exists
return Json(query.ToArray());
}
Note the removal of JsonRequestBehavior.AllowGet
thanks Robert!

Returning multiple values to be used in jQuery from a WebMethod

I have jquery using ajax/json to grab an elements ID and then hits:
[System.Web.Services.WebMethod]
public static string EditPage(string nodeID)
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(Global.conString))
using (SqlCommand cmd = new SqlCommand("contentPageGetDetail", con))
{
cmd.Parameters.Add("#ID", SqlDbType.UniqueIdentifier).Value = Global.SafeSqlLiteral(nodeID, 1);
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
if (dt.Count > 0)
{
string pageTitle = dt.Rows[0]["Title"].toString();
string contentID = dt.Rows[0]["ContentID"].toString();
return pageTitle, contentID, nodeID;
}
else
{
return "Failed";
}
}
When it's time to return I want to grab all content returned from the stored procedure back to the jquery method in the success section and set a hiddenfield, dropdown value, and a title in a textfield.
In the jQuery I tried using "pageTitle" but it came up undefined. What do I need to do jQuery side to grab whats being returned and populate fields in my Web Form before showing the form?
You'll need to create a struct or class to return:
public struct TheStruct
{
public string pageTitle;
public int contentID,
public int nodeID;
}
[System.Web.Services.WebMethod]
public static TheStruct EditPage(string nodeID)
{
<your code here>
var result = new TheStruct();
result.pageTitle = "Test";
result.contentID = 1;
return result;
}
If you pass:
contentType: "application/json; charset=utf-8",
in the AJAX call, you'll get a JSON reply, which you can parse like:
var obj = jQuery.parseJSON(webserviceReply);
alert(obj.pageTitle);
public class stuff {
string pagetitle;
string contentID;
string nodeID;
}
[System.Web.Services.WebMethod]
public static stuff EditPage(string nodeID) {
... get the stuff
stuff returnme = new stuff();
returnme.pagetitle = ...
returnme.contentid = ...
return returnme;
}
==== jquery side:
Assuming you're using the AJAX call of jquery do something like this:
.ajax({ type: "GET", url: "./return.asmx", async: true, dataType: "xml",
success: function (respons, status) {
$(respons).find("WebServiceCallName stuff pagetitle").text();
}});
You'll need to look at the webservice output directly (just navigate to it as if it were a webpage) to make sure your jQuery selector is correct.
If you want to use the string you return from jquery try:
success: function(msg) {
alert(msg.d);
}
msg.d will hold the string you return from your webservice call. If you want to return multiple strings, try to add a predefined string between them and split them in your jquery success function. like:
yourfirststring||##||yoursecondstring||##||yourthirdstring
var strings = msg.d.split("||##||");

C# (.NET) handling Javascript Array/Serialization

I'm using tableDnD to re-order table rows, and then serialize them using "$.tableDnD.serialize()"
I want to send this to C# for processing, what's the best of doing so?
The below is an example of the serialization
pages[]=&pages[]=21&pages[]=23&pages[]=34&pages[]=37&pages[]=40&pages[]=43&pages[]=46&pages[]=49&pages[]=31&pages[]=50&pages[]=51&pages[]=52&pages[]=53&pages[]=54&pages[]=55&pages[]=56&pages[]=57&pages[]=58&pages[]=61&pages[]=65&pages[]=70&pages[]=74&pages[]=77&pages[]=78&pages[]=79&pages[]=82&pages[]=85&pages[]=88&pages[]=91&pages[]=94&pages[]=97&pages[]=100&pages[]=103&pages[]=106&pages[]=109&pages[]=112&pages[]=115&pages[]=119&pages[]=122&pages[]=123
Important Information
I tagged this as MVC but forgot to mention it. I'm using ASP.NET MVC
You can send that as-is using one of jQuery's ajax methods. I would prefer to turn it into a smaller, neater CSV string before sending it to the server as follows:
var str = 'pages[]=&pages[]=21&pages[]=23&pages[]=34&pages[]=37&pages[]=40&pages[]=43&pages[]=46&pages[]=49&pages[]=31&pages[]=50&pages[]=51&pages[]=52&pages[]=53&pages[]=54&pages[]=55&pages[]=56&pages[]=57&pages[]=58&pages[]=61&pages[]=65&pages[]=70&pages[]=74&pages[]=77&pages[]=78&pages[]=79&pages[]=82&pages[]=85&pages[]=88&pages[]=91&pages[]=94&pages[]=97&pages[]=100&pages[]=103&pages[]=106&pages[]=109&pages[]=112&pages[]=115&pages[]=119&pages[]=122&pages[]=123';
var tmpArr = str.split('&');
var pagesArr = [];
for(var i = 0;i < tmpArr.length; i++) {
var paramArr = tmpArr[i].split('=');
if(paramArr[1] != null && paramArr[1] != '') {
pagesArr.push(paramArr[1]);
}
}
alert(pagesArr); //now much prettier
//turn it into a CSV string
var pagesCsv = pagesArr.join(',');
$.ajax({
type: "POST",
url: "some.aspx",
data: pagesCsv,
success: function(msg){
alert( "Data Saved: " + msg );
}
});
Based on the example of karim79 :
var str = 'pages[]=&pages[]=21&pages[]=23&pages[]=34&pages[]=37&pages[]=40&pages[]=43&pages[]=46&pages[]=49&pages[]=31&pages[]=50&pages[]=51&pages[]=52&pages[]=53&pages[]=54&pages[]=55&pages[]=56&pages[]=57&pages[]=58&pages[]=61&pages[]=65&pages[]=70&pages[]=74&pages[]=77&pages[]=78&pages[]=79&pages[]=82&pages[]=85&pages[]=88&pages[]=91&pages[]=94&pages[]=97&pages[]=100&pages[]=103&pages[]=106&pages[]=109&pages[]=112&pages[]=115&pages[]=119&pages[]=122&pages[]=123';
var pos = null;
var index = 0;
while ((pos=str.indexOf("[]"))>-1)
{
str = str.substr(0, pos-1) + "_" + (index) + str.substr(pos+2);
index++;
}
alert(str);
$.ajax({
type: "POST",
url: "some.aspx",
data: str,
success: function(msg){
alert( "Data Saved: " + msg );
}
});
In C#
string[] keys = Request.QueryString.AllKeys;
Array.Sort(keys);
StringBuilder sb = new StringBuilder();
foreach (string key in keys)
{
if (key.IndexOf("pages_")!=-1)
{
sb.Append(Request.QueryString[key]);
}
}
// sb container the all values
You can also put everything in to one object like this:
var prm = { pages=[...], someOtherPages=[], additionalParam="", integer=1324 }
jQuery.ajax({
url: "someurl.aspx",
type: "POST",
data: {prm: JSON.stringify(prm)},
});
and parse prm on C# side by using this JSON Parser:
JObject json = JObject.Parse(Request.Form["prm"]);
JArray items = json["pages"] as JArray;
foreach (JToken item in items)
{
int i = item["type"].Value<int>(); // take an item as int
string s = item["type"].Value<string>(); // take an item as string
JArray ar = item["complex"] as JArray; // that an item as an array
}
much simplier and flexible

Categories