I created a dashboard with widgets awhile ago and I'm now revisiting how to persist the the widgets per user to the database. I thought I was on the right track, but I'm very new to JSON and I'm unable to accomplish what I need. I've researched this and tried multiple things but nothing has worked out so far. Here is my code..
javascript that creates item for update
function updateWidgetData() {
var items = [];
$('.column').each(function () {
var columnId = $(this).attr('id');
$('.dragbox', this).each(function (i) {
var collapsed = 0;
if ($(this).find('.dragbox-content').css('display') == "none")
collapsed = 1;
//Create Item object for current panel
var item = {
id: $(this).attr('id'),
collapsed: collapsed,
order: i,
column: columnId
};
//Push item object into items array
items.push(item);
});
});
//Assign items array to sortorder JSON variable
var sortorder = { items: items };
Now my goal is to pass the sortorder to be saved to the database... but I have this for testing..
var testData = '{ "Column1": "test1", "Column2": "test2"}'
$.ajax ({
url: "/Handlers/SaveWidgets.ashx",
type: "POST",
contentType: "application/json; charset=uft-8",
dataType: "json",
data: testData,
success: function (response) {
alert("Passed json");
},
error: function (error) {
alert("Failed passing json.");
}
});
Then in my handler..
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
string column1 = (string)context.Request.Form["Column1"];
string column2 = (string)context.Request.Form["Column2"];
using (SqlConnection connCao = new SqlConnection(ConfigurationManager.ConnectionStrings["dboCao"].ConnectionString))
{
using(SqlCommand cmdWidget = new SqlCommand("INSERT INTO TestTable (Column1, Column2) VALUES (#column1, #column2)", connCao))
{
cmdWidget.Parameters.AddWithValue("#column1", column1);
cmdWidget.Parameters.AddWithValue("#column2", column2);
connCao.Open();
cmdWidget.ExecuteNonQuery();
connCao.Close();
}
}
}
but I'm getting that it's expecting parameters #column1, and #column2 which were never supplied. So clearly I'm missing how to do something and I'm unable to find what I'm missing on the google machine.
I have used this link here but this doesn't explain the greatest and a few things confused me.
I also found other links but nothing that explains what I'm trying to accomplish. Any help is greatly appreciated!
I would start by creating a class to represent the data you are posting to the handler.
using System;
using System.Runtime.Serialization;
[DataContract]
public class YourDataModel
{
public YourDataModel() { }
// When a property in your model doesn't
// match up exactly you can manually
// specify the name
[DataMember(Name = "Column1")]
public String Col1 { get; set; }
// If things match up exactly (including case)
// you don't need to manually map the Name
[DataMember]
public String Column2 { get; set; }
}
Then modify your handler to create an instance of that class from posted JSON data.
using System;
using System.IO;
using System.Web;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
public class SaveWidgets : IHttpHandler {
public void ProcessRequest (HttpContext context)
{
String json = String.Empty;
// you have sent JSON to the server
// read it into a string via the input stream
using (StreamReader rd = new StreamReader(context.Request.InputStream))
{
json = rd.ReadToEnd();
}
// create an instance of YourDataModel from the
// json sent to this handler
YourDataModel data = null;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(YourDataModel));
using (MemoryStream ms = new MemoryStream())
{
byte[] utf8Bytes = Encoding.UTF8.GetBytes(json);
ms.Write(utf8Bytes, 0, utf8Bytes.Length);
ms.Position = 0;
data = serializer.ReadObject(ms) as YourDataModel;
}
// update the DB and
// send back a JSON response
int rowsUpdated = 0;
using (SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["dboCao"].ConnectionString))
{
c.Open();
String sql = #"
INSERT INTO TestTable
(Column1, Column2)
VALUES
(#column1, #column2);";
using (SqlCommand cmd = new SqlCommand(sql, c))
{
cmd.Parameters.Add("#column1", SqlDbType.VarChar, 50).Value = data.Col1;
cmd.Parameters.Add("#column2", SqlDbType.VarChar, 50).Value = data.Column2;
rowsUpdated = cmd.ExecuteNonQuery();
}
}
context.Response.ContentType = "application/json";
context.Response.Write("{ \"rows_updated\": " + rowsUpdated + " }");
}
public bool IsReusable {
get { return false; }
}
}
Related
This has been giving me some trouble for the past few days. I'm going to try to be as detailed as possible with what I want and the issue I'm having. I tried to simplify my controllers, models, etc as much as I can for the sake of the question.
Here's the flow of sequences I'm trying to get to work.
Give user a view with inputs for List<MyObject> in the main ViewModel
User can hit a button to add another row to add another object to that List of objects to post later
Hitting the button POSTs the object (in same container) through AJAX from the currently displayed list in order to repeat most of the inputs for the new row (MyObject)
Controller takes passed MyObject and maps some of the prior values to the new object
Controller passes back new MyObject and ajax appends the result html to my table
The Problem
The Ajax is passing the on-page MyObject as null (or C# doesn't know how to interpret) to my controller (step 4 above). I can't seem to get the object passed to the controller through the Ajax call.
What I've got
Models:
public class MyViewModel
{
// irrelevant properties
public List<MyObject> MyObjects { get; set; } = new List<MyObject>();
}
public class MyObject
{
public int Id { get; set; }
public string Name { get; set; }
public string AnotherProperty { get; set; }
public decimal AdditionalProperty { get; set; }
public List<MySubObject> MySubObjects { get; set; } = new List<MySubObject>();
}
public class MySubObject
{
public bool IsChecked { get; set; }
public bool Name { get; set; }
}
Controller GET:
public ActionResult Edit(int? id)
{
var viewModel = new MyViewModel();
// for list of checkboxes
var subObjects = new List<MySubObject>();
// get subobjects from db
subObjects.Add(new MySubObject {
Name = "SubObj1", IsChecked = false
});
subObjects.Add(new MySubObject {
Name = "SubObj12",
IsChecked = false
});
// populate viewModel with a blank MyObject
viewModel.MyObjects.Add(new MyObject
{
MySubObjects = subObjects
});
return (viewModel);
}
View (and AJAX call):
<table id="myObjectInputs">
#foreach (var obj in Model.MyObjects)
{
#Html.Partial("~/Areas/Admin/Views/Shared/EditorTemplates/MyObject.cshtml", obj)
}
</table>
<script>
$(document).ready(function () {
$("#myObjectInputs").on("focus", ".make-new-row", function () {
var plusButton = $(this);
var currentArea = plusButton.closest(".myobject-container");
var serializedData = currentArea.find(":input").serialize();
// add new row
$.ajax({
url: this.href,
cache: false,
type: "POST",
data: { "myObject": serializedData },
success: function (html) { $("#myObjectInputs").append(html); }
});
return false;
});
});
</script>
EditorTemplates/MyObject.cshtml:
#using HtmlHelpers.BeginCollectionItem
#model LD.Areas.Admin.Models.MyObject
<tbody class="myobject-container" style="border:solid 1px red;">
#using (Html.BeginCollectionItem("MyObjects"))
{
<tr>
<td>#Html.HiddenFor(x => x.Id)</td>
<td>#Html.EditorFor(x => x.Name)</td>
<td>#Html.EditorFor(x => x.AnotherProperty)</td>
<td>#Html.EditorFor(x => x.AdditionalProperty)</td>
<td>
#foreach (var subObj in Model.MySubObjects)
{
#Html.Partial("~/Areas/Admin/Views/Shared/EditorTemplates/MySubObject.cshtml", subObj)
}
</td>
<td>
<!-- the button that calls the function / AJAX -->
#Html.ActionLink("+", "NewMyObjectSection", null, new { #class = "make-new-row" })
</td>
</tr>
}
</tbody>
EditorTemplates/MySubObject.cshtml
#using HtmlHelpers.BeginCollectionItem
#model LD.Areas.Admin.Models.MySubObject
#using (Html.BeginCollectionItem("MySubObjects"))
{
<label>
#Html.HiddenFor(x => x.Id)
#Html.HiddenFor(x => x.Name)
#Html.EditorFor(x => x.IsChecked)#Html.LabelFor(x => x.IsChecked, Model.Name)
<text> </text>
</label>
}
ActionResult called by AJAX: (this is I'm getting null for MyObject)
public ActionResult NewMyObjectSection(MyObject myObject)
{
// take passed object values and create a new object based on myObject
var newObject = new MyObject();
return PartialView("~/Areas/Admin/Views/Shared/EditorTemplates/MyObject.cshtml", myObject);
}
What I've Tried
Some main things that stick out to me are that BeginCollectionItem attaches a GUID to make the collection items unique, for ex, when my <tablebody class="myobject-container"> is serialized, it looks like this (this is the result from my real object, Rates == MyObjects):
"Rates.index=b589808e-3e99-40f2-827c-58feaa9bebc3&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.OrganismNid=0&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.OrganismName=&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.OrganismUpdateType=New&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.IsPest=false&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.IsPreEmergent=false&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.IsPostEmergent=false&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.IsSafeOn=false&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.HasControl=false&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.HasSuppression=false&ControlTypes.index=bd9d1180-9768-4ca4-8316-fc5cbf62ca97&ControlTypes%5Bbd9d1180-9768-4ca4-8316-fc5cbf62ca97%5D.ControlTypeNid=1&ControlTypes%5Bbd9d1180-9768-4ca4-8316-fc5cbf62ca97%5D.Name=Annual&ControlTypes%5Bbd9d1180-9768-4ca4-8316-fc5cbf62ca97%5D.IsChecked=false&ControlTypes.index=0264b842-5cac-4b1a-8b79-8f9a13a26428&ControlTypes%5B0264b842-5cac-4b1a-8b79-8f9a13a26428%5D.ControlTypeNid=2&ControlTypes%5B0264b842-5cac-4b1a-8b79-8f9a13a26428%5D.Name=Biennial&ControlTypes%5B0264b842-5cac-4b1a-8b79-8f9a13a26428%5D.IsChecked=false&ControlTypes.index=6a344551-add6-4e9b-96e2-59a6fc857327&ControlTypes%5B6a344551-add6-4e9b-96e2-59a6fc857327%5D.ControlTypeNid=3&ControlTypes%5B6a344551-add6-4e9b-96e2-59a6fc857327%5D.Name=Winter%20Annual&ControlTypes%5B6a344551-add6-4e9b-96e2-59a6fc857327%5D.IsChecked=false&ControlTypes.index=91f5c6ff-402e-48ae-8f9c-1131511699a8&ControlTypes%5B91f5c6ff-402e-48ae-8f9c-1131511699a8%5D.ControlTypeNid=4&ControlTypes%5B91f5c6ff-402e-48ae-8f9c-1131511699a8%5D.Name=Perennial&ControlTypes%5B91f5c6ff-402e-48ae-8f9c-1131511699a8%5D.IsChecked=false&ControlTypes.index=3248ec07-09a8-4bf0-b99f-a518807d9636&ControlTypes%5B3248ec07-09a8-4bf0-b99f-a518807d9636%5D.ControlTypeNid=5&ControlTypes%5B3248ec07-09a8-4bf0-b99f-a518807d9636%5D.Name=Top%20Growth%20Control%20Only&ControlTypes%5B3248ec07-09a8-4bf0-b99f-a518807d9636%5D.IsChecked=false&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.BroadcastMin=&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.BroadcastMax=&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.BroadcastChemUnitTypeNid=1&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.BroadcastAreaUnitTypeNid=9&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.SpotMin=&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.SpotMax=&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.SpotChemUnitTypeNid=1&Rates%5Bb589808e-3e99-40f2-827c-58feaa9bebc3%5D.SpotFinalSolutionUnitTypeNid=1"
I'm not sure if my controller understands to bind that to my object.
I've tried other methods of passing it, such as stripping out GUIDs and extra junk from the string, passing it as a string and deserializing in C#, and others:
var serializedArray = currentArea.find(":input").serializeArray();
//https://www.regextester.com/94410
var regex = new RegExp("(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}");
var stripped = serializedData.replace(/(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}/g, '');
stripped = stripped.replace(/%5B/g, '[').replace(/%5D/g, ']');
var strung = JSON.stringify({ "modelData": serializedData });
At this point I'm at a loss. This is for a personal passion project and my lack of AJAX / JSON knowledge is really holding me back. I'm not sure what else to try. Any pointing in the right direction would be appreciated.
public ActionResult NewMyObjectSection([FromBody] MyObject myObject)
{
//myObject should be correctly populated from the request
return PartialView("~/Areas/Admin/Views/Shared/EditorTemplates/MyObject.cshtml", myObject);
}
Id Expect the item to come as a Json Object correctly passed in your request to that your myObject is populated automatically
for the request part:
var dat = {
Id:3,
Name:7,
AnotherProperty:"",
AdditionalProperty:"",
MySubObjects:[
//Create sub objects here
]
};
$.ajax({
type: "POST",
url: "youraction",
data: JSON.stringify(dat),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){alert(data);},
failure: function(errMsg) {
alert(errMsg);
}
});
})
if (saleDetails.length) {
var htmlData;
var paymentStatus = 0;
if ($('#PaymentStatus option:selected').val() != 0) {
paymentStatus = $('#PaymentStatus option:selected').text()
}
var SaleAmount = parseFloat(total + vat).toFixed(2);
var data = {
'AccountID': $('#hdnAccountID').val(),
'QuoteID': $('#hdnQuoteID').val(),
'BranchID': $('#BranchID option:selected').val(),
'PONO': $('#PONO').val(),
'PaymentStatus': $('#PaymentStatus').val(),
'SalesDate': $('#SaleDate').val(),
'PaymentStatus': paymentStatus,
'PaymentTypeID': $('#PaymentType option:selected').val(),
'VAT': vat,
'TotalAmount': invoiceAmount,
'DiscountAmount': $('#discInput').val(),
'AmountPaid': $('#amountPaid').val(),
'SaleDetails': saleDetails
};
var json = JSON.stringify({ 'model': data });
public ActionResult printOrder(Models.DTO.Sales model)
{
return PartialView(model);
//return View(model);
}
I am working on POS , In sales client requirement is that we should give him an option of print , so that if client click on Print button we should open a new tab and show invoice , so client can take out print and if customer pay him then client will save SalesOrder.
The problem I am facing is that I am unable to open new tab from controller . And if I am trying to do this from java script I am unable to pass model to view from java script.
So please help me in this issue as I am not too much expert in MVC.
You can use Html.ActionLink to open the page in new tab from your Razor page as below.
#Html.ActionLink("Print", "Action", new { controller="PrintOrder" }, new { target="_blank" })
Html.ActionLink however does not allow you to pass complex objects. You can use trick as mentioned in this stackoverflow answer to pass your model. From the post:
MODEL: Make static Serialize and Deserialize methods in the class like
public class XYZ {
// Some Fields
public string X { get; set; }
public string Y { get; set; }
public string X { get; set; }
// This will convert the passed XYZ object to JSON string
public static string Serialize(XYZ xyz)
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(xyz);
}
// This will convert the passed JSON string back to XYZ object
public static XYZ Deserialize(string data)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize<XYZ>(data);
}
}
VIEW: Now convert your complex object to JSON string before passing it in
Action View <%= Html.ActionLink(Model.x, "SomeAction", new { modelString = XYZ.Serialize(Model) })%>
CONTROLLER: Get the
object as string in Action method and convert it back to object before
using public ActionResult SomeAction(string modelString) { XYX xyz = XYX.Deserialize(modelString); }
I just used the XmlWriter to create some XML to send back in an HTTP response. How would you create a JSON string. I assume you would just use a stringbuilder to build the JSON string and them format your response as JSON?
Using Newtonsoft.Json makes it really easier:
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string json = JsonConvert.SerializeObject(product);
Documentation: Serializing and Deserializing JSON
You could use the JavaScriptSerializer class, check this article to build an useful extension method.
Code from article:
namespace ExtensionMethods
{
public static class JSONHelper
{
public static string ToJSON(this object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(obj);
}
public static string ToJSON(this object obj, int recursionDepth)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RecursionLimit = recursionDepth;
return serializer.Serialize(obj);
}
}
}
Usage:
using ExtensionMethods;
...
List<Person> people = new List<Person>{
new Person{ID = 1, FirstName = "Scott", LastName = "Gurthie"},
new Person{ID = 2, FirstName = "Bill", LastName = "Gates"}
};
string jsonString = people.ToJSON();
Simlpe use of Newtonsoft.Json and Newtonsoft.Json.Linq libraries.
//Create my object
var myData = new
{
Host = #"sftp.myhost.gr",
UserName = "my_username",
Password = "my_password",
SourceDir = "/export/zip/mypath/",
FileName = "my_file.zip"
};
//Tranform it to Json object
string jsonData = JsonConvert.SerializeObject(myData);
//Print the Json object
Console.WriteLine(jsonData);
//Parse the json object
JObject jsonObject = JObject.Parse(jsonData);
//Print the parsed Json object
Console.WriteLine((string)jsonObject["Host"]);
Console.WriteLine((string)jsonObject["UserName"]);
Console.WriteLine((string)jsonObject["Password"]);
Console.WriteLine((string)jsonObject["SourceDir"]);
Console.WriteLine((string)jsonObject["FileName"]);
This library is very good for JSON from C#
http://james.newtonking.com/pages/json-net.aspx
This code snippet uses the DataContractJsonSerializer from System.Runtime.Serialization.Json in .NET 3.5.
public static string ToJson<T>(/* this */ T value, Encoding encoding)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var stream = new MemoryStream())
{
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(stream, encoding))
{
serializer.WriteObject(writer, value);
}
return encoding.GetString(stream.ToArray());
}
}
If you need complex result (embedded) create your own structure:
class templateRequest
{
public String[] registration_ids;
public Data data;
public class Data
{
public String message;
public String tickerText;
public String contentTitle;
public Data(String message, String tickerText, string contentTitle)
{
this.message = message;
this.tickerText = tickerText;
this.contentTitle = contentTitle;
}
};
}
and then you can obtain JSON string with calling
List<String> ids = new List<string>() { "id1", "id2" };
templateRequest request = new templeteRequest();
request.registration_ids = ids.ToArray();
request.data = new templateRequest.Data("Your message", "Your ticker", "Your content");
string json = new JavaScriptSerializer().Serialize(request);
The result will be like this:
json = "{\"registration_ids\":[\"id1\",\"id2\"],\"data\":{\"message\":\"Your message\",\"tickerText\":\"Your ticket\",\"contentTitle\":\"Your content\"}}"
Hope it helps!
You can also try my ServiceStack JsonSerializer it's the fastest .NET JSON serializer at the moment. It supports serializing DataContracts, any POCO Type, Interfaces, Late-bound objects including anonymous types, etc.
Basic Example
var customer = new Customer { Name="Joe Bloggs", Age=31 };
var json = JsonSerializer.SerializeToString(customer);
var fromJson = JsonSerializer.DeserializeFromString<Customer>(json);
Note: Only use Microsofts JavaScriptSerializer if performance is not important to you as I've had to leave it out of my benchmarks since its up to 40x-100x slower than the other JSON serializers.
Take a look at http://www.codeplex.com/json/ for the json-net.aspx project. Why re-invent the wheel?
If you want to avoid creating a class and create JSON then Create a dynamic Object and Serialize Object.
dynamic data = new ExpandoObject();
data.name = "kushal";
data.isActive = true;
// convert to JSON
string json = Newtonsoft.Json.JsonConvert.SerializeObject(data);
Read the JSON and deserialize like this:
// convert back to Object
dynamic output = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
// read a particular value:
output.name.Value
ExpandoObject is from System.Dynamic namespace.
If you can't or don't want to use the two built-in JSON serializers (JavaScriptSerializer and DataContractJsonSerializer) you can try the JsonExSerializer library - I use it in a number of projects and works quite well.
If you're trying to create a web service to serve data over JSON to a web page, consider using the ASP.NET Ajax toolkit:
http://www.asp.net/learn/ajax/tutorial-05-cs.aspx
It will automatically convert your objects served over a webservice to json, and create the proxy class that you can use to connect to it.
Encode Usage
Simple object to JSON Array EncodeJsObjectArray()
public class dummyObject
{
public string fake { get; set; }
public int id { get; set; }
public dummyObject()
{
fake = "dummy";
id = 5;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append('[');
sb.Append(id);
sb.Append(',');
sb.Append(JSONEncoders.EncodeJsString(fake));
sb.Append(']');
return sb.ToString();
}
}
dummyObject[] dummys = new dummyObject[2];
dummys[0] = new dummyObject();
dummys[1] = new dummyObject();
dummys[0].fake = "mike";
dummys[0].id = 29;
string result = JSONEncoders.EncodeJsObjectArray(dummys);
Result:
[[29,"mike"],[5,"dummy"]]
Pretty Usage
Pretty print JSON Array PrettyPrintJson() string extension method
string input = "[14,4,[14,\"data\"],[[5,\"10.186.122.15\"],[6,\"10.186.122.16\"]]]";
string result = input.PrettyPrintJson();
Results is:
[
14,
4,
[
14,
"data"
],
[
[
5,
"10.186.122.15"
],
[
6,
"10.186.122.16"
]
]
]
The DataContractJSONSerializer will do everything for you with the same easy as the XMLSerializer. Its trivial to use this in a web app. If you are using WCF, you can specify its use with an attribute. The DataContractSerializer family is also very fast.
I've found that you don't need the serializer at all. If you return the object as a List.
Let me use an example.
In our asmx we get the data using the variable we passed along
// return data
[WebMethod(CacheDuration = 180)]
public List<latlon> GetData(int id)
{
var data = from p in db.property
where p.id == id
select new latlon
{
lat = p.lat,
lon = p.lon
};
return data.ToList();
}
public class latlon
{
public string lat { get; set; }
public string lon { get; set; }
}
Then using jquery we access the service, passing along that variable.
// get latlon
function getlatlon(propertyid) {
var mydata;
$.ajax({
url: "getData.asmx/GetLatLon",
type: "POST",
data: "{'id': '" + propertyid + "'}",
async: false,
contentType: "application/json;",
dataType: "json",
success: function (data, textStatus, jqXHR) { //
mydata = data;
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
console.log(xmlHttpRequest.responseText);
console.log(textStatus);
console.log(errorThrown);
}
});
return mydata;
}
// call the function with your data
latlondata = getlatlon(id);
And we get our response.
{"d":[{"__type":"MapData+latlon","lat":"40.7031420","lon":"-80.6047970}]}
Include:
using System.Text.Json;
Then serialize your object_to_serialize like this:
JsonSerializer.Serialize(object_to_serialize)
I'm passing multiple JSON objects from my frontend to a C# backend - how can I deserialize them into C# classes so they can be used later on in my application? Before I go any farther, I am tied to using the JS FormData object, contentType: false, and processData: false, because I also need to pass files via this AJAX call; that is completely unrelated to this question. Here's my code so far:
Frontend - function is called when a submit button is pressed
submitData: function () {
var formCollection = this.appModel.get('formCollection').models;
var formData = new FormData();
var formJson = [];
$.each(formCollection, function (index, form) {
var tempJson = {};
if (form) {
tempJson['id'] = form.get('id');
tempJson['number'] = form.get('number');
tempJson['name'] = form.get('name');
tempJson['attachments'] = form.get('attachments');
formJson.push(tempJson);
}
});
console.log(JSON.stringify(formJson));
formData.append('formJson', JSON.stringify(formJson));
$.ajax({
type: "POST",
url: '/NMISProduct/Test',
contentType: false,
processData: false,
data: formData,
success: function (result) {
console.log(result);
}
});
}
JSON.stringified data that's being passed
[{"id":1,"number":null,"name":"Investment Portfolio Statement","attachments":null},{"id":2,"number":"61-0227","name":"WMC Signature Portfolio Agreement","attachments":null},{"id":3,"number":"61-1126","name":"WMC Signature Choice Agreement","attachments":null},{"id":4,"number":"61-1162","name":"WMC Signature Annuities Agreement","attachments":null},{"id":5,"number":"61-1205","name":"WMC Signature Managed Accounts Client Agreement","attachments":null}]
C# MVC 5 Backend
[HttpPost]
public async Task<JsonResult> Test()
{
Debug.WriteLine(Request.Params["formJson"]);
var forms = JsonConvert.DeserializeObject<Form>(Request.Params["formJson"]);
Debug.WriteLine(forms);
try
{
var srNumber = GetSRNumber();
foreach (string file in Request.Files)
{
var fileContent = Request.Files[file];
Debug.WriteLine(ReadFileInputStream(fileContent));
if (fileContent != null && fileContent.ContentLength > 0)
{
// get a stream
var stream = fileContent.InputStream;
// and optionally write the file to disk
//var fileName = Path.GetFileName(file);
var fileName = fileContent.FileName;
var path = Path.Combine(Server.MapPath("~/App_Data/"), fileName);
using (var fileStream = System.IO.File.Create(path))
{
stream.CopyTo(fileStream);
}
}
}
}
catch (Exception)
{
return Json("Upload failed");
}
return Json("File uploaded successfully");
}
public class Form
{
public int id { get; set; }
public string number { get; set; }
public string name { get; set; }
public Form attachments { get; set; }
public byte[] fileAsBytes { get; set; }
}
I've done my research and found several Stackoverflow questions that show how to serialize one JSON object into one C# class - however, I need to serialize multiple JSON objects into a List<Form>. How can I do this? What am I doing wrong in the posted code?
You're trying to deserialize to a single form here:
var forms = JsonConvert.DeserializeObject<Form>(Request.Params["formJson"]);
Just change it to:
var forms = JsonConvert.DeserializeObject<List<Form>>(Request.Params["formJson"]);
You should then be able to use forms in a normal way - iterating over it, taking a count etc.
[HttpPost]
public async Task<JsonResult> Test(List<Form> forms)
{
// your code here
}
And put your JS code
formJson.push(tempJson);
inside the
if (form)
I'm trying send my client-side custom object (JavaScript) to ASP.net Web Method. I use jQuery Ajax command to perform this operation.
There a example of my object:
function Customer() {
this.Name = "";
this.Surname = "";
this.Addresses = new Array();
}
I load data with this method:
function buildCurrentCustomer() {
var currentCustomer = new Customer();
/** General Info **/
currentCustomer.Name = $("#Name").val();
currentCustomer.Surname = $("#Surname").val();
currentCustomer.Addresses = new Array();
currentCustomer.Addresses["HOME"] = $("#adHome").val();
currentCustomer.Addresses["OFFICE"] = $("#adOffice").val();
return currentCustomer;
}
And finally I send data with this code:
$.ajax({
type: "POST",
url: "../_layouts/CustomerManager/MasterPage.aspx/SetCustomer",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{customer: " + JSON.stringify(currentCustomer) + "}",
cache: false,
success: function (result) {
},
error: function (ex) {
WriteToConsole(ex.responseText);
}
});
My server-side methods is like that:
[WebMethod]
public static bool SetCustomer(CustomerModel Customer)
{
//My code...
}
and my CustomerModel class is like that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Common.Model.JavaScriptModel
{
public class CustomerModel
{
/** General Info **/
public string Name {get;set;}
public string Surname {get;set;}
public Dictionary<string, string> Addresses { get; set; }
}
}
The problem is that when I execute Ajax Call server-side method doesn't execute. If I change signature of server-side method in:
public static bool SetCustomer(List<CustomerModel> Customer)
SetCustomer method is executed but the List is empty.
Why have I this problem? Where can I find documentation about this functionality?
Thanks
first, if you use the data like this
data: "{customer: " + JSON.stringify(currentCustomer) + "}",
on the code behind, you need to take the same parameter customer and not Customer, so this
public static bool SetCustomer(CustomerModel Customer) { ... }
needs to be changed to
public static bool SetCustomer(CustomerModel customer) { ... }
second, your Customer object in the javascript is like this if translated to asp.net
string Name;
string Surname;
List<string> Addresses;
but your class in the code behind for Addresses is using
Dictionary<string, string>
thus causing your data from client side can't be parsed in the server side and return an error to the client side, so you need to change your Addresses class to
public List<string> Addresses { get; set; }
and lastly, your code inside buildCurrentCustomer for the Addresses is being set like this
currentCustomer.Addresses = new Array();
currentCustomer.Addresses["HOME"] = $("#adHome").val();
currentCustomer.Addresses["OFFICE"] = $("#adOffice").val();
this will never add a value to Addresses since it's type is an array, but you set the value to it as if it was an object, so if you want to stick to use an array, you need to change it to
currentCustomer.Addresses = new Array();
currentCustomer.Addresses.push($("#adHome").val());
currentCustomer.Addresses.push($("#adOffice").val());
*Note:
use this if you want to use the Addresses as an array, but if you need the Addresses to be an object that contains HOME and OFFICE, I'll Edit the answer
Edit:
perhaps you can use a javascript object like this
currentCustomer.Addresses = {};
currentCustomer.Addresses["Home"] = $("#adHome").val();
currentCustomer.Addresses["Office"] = $("#adOffice").val();
to make the equivalent for Dictionary<string,string> but if it didn't work you could change your Addresses to class too like this
public List<Address> Addresses { get; set; }
and add class Address
public class Address
{
public string Home {get;set;}
public string Office {get;set;}
}
I myself never used a Dictionary myself, so I don't know if it's the same
You can change your source code like this..
AJAX-
data: JSON.stringify({'customer':currentCustomer});
ASP.net Web Method-
[WebMethod]
public static bool SetCustomer(object customer)
{
CustomerModel CM = new CustomerModel();
_Serializer = new JavaScriptSerializer();
_StringBuilder = new StringBuilder();
_Serializer.Serialize(customer, _StringBuilder);
CM = _Serializer.Deserialize<CustomerModel>(_StringBuilder.ToString());
}
Note that you have to initialize _Serializer and the _StringBuilder properties at the top of the page as global variables...
public static JavaScriptSerializer _Serializer;
public static StringBuilder _StringBuilder;