I try to save fields by action controller action method which return different view. But failed to do this: My Jquery code is:
$("#btnAdd").click(function () {
var Product = {
name: $("#txtProductName").val(),
color: $("#ddlColor option:selected").val(),
gage: $("#ddlGage option:selected").val(),
rate: $("#txtrate").val()
};
$.ajax({
});
$.post("ProductTable", { Pro: JSON.stringify(Product) }, function (data) {
$("#RightDiv").html(data);
alert(data);
});
});
and my controller action method on the same controller which return different view:
public ActionResult ProductTable()
{
Product product = new Product();
JavaScriptSerializer serializer = new JavaScriptSerializer();
product = serializer.Deserialize<Product>(Request.Form["Pro"]);
productDB.addProduct(product);
productManager.productTable = productDB.getAllProducts();
return View(productManager);
}
Browser give me error:
HTTP500: SERVER ERROR - The server encountered an unexpected condition that prevented it from fulfilling the request.
(XHR)POST - http://localhost:59008/Product/ProductTable
If you're using MVC, it should handle the serialization/deserialization for you. You just need to make sure the object sent over matches the object you declare in MVC controller action parameter.
Client-side
// Suggestions:
// * use camelCase for javascript variables and functions
// * jQuery .val() on selects should give you the selected value
// * always use fully qualified Url generated by Html.Helper
$("#btnAdd").click(function () {
var product = {
name: $("#txtProductName").val(),
color: $("#ddlColor").val(),
gage: $("#ddlGage").val(),
rate: $("#txtrate").val()
};
var createUrl = '#Url.Action("create", "product", new { area = "" })';
$.post(createUrl, product, function (response) {
$("#RightDiv").html(response);
alert(response);
});
});
Server-side
// Suggestions:
// * NEVER send your domain model back to the page! You should create
// a ViewModel to just include what you want to show the users
[HttpPost]
public ActionResult Create(CreateProductViewModel model)
{
...
productDB.addProduct(new Product {
Name = model.Name,
Color = model.Color,
Gage = model.Gage,
Rate = model.Rate,
// And other stuff like
// CreatedBy = User.Identity.Name
});
// This looks weird to me too!
productManager.productTable = productDB.getAllProducts();
return View(productManager);
}
The ViewModel
public class CreateProductViewModel
{
public string Name { get; set; }
public int Color { get; set; }
public int Gage { get; set; }
public double Rate { get; set; }
}
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 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; }
}
}
I post data with jQuery but I have a problem with array data. The values supplied to the MVC controller are always null.
This is my JavaScript code:
var FilterCategory = $('input:checkbox:checked').map(function () {
return this.value;
}).get();
var posting = $.post(url, { cursorid: lastid, CatFilter: FilterCategory });
The form data from the network:
cursorid:5434cdc84ba4dd0c40396851
Filter[]:1
Filter[]:3
Filter[]:4
Here's the C# side:
public ActionResult GetDataTweets(string cursorid,string[] CatFilter)
{
bla bla
}
cursorid has a value, but CatFilter is null.
What do I need to do to have the correct value supplied to CatFilter?
This code here:
var posting = $.post(url, { cursorid: lastid, CatFilter: FilterCategory });
From MVC's perspective it's sending a class, so you need a reciprocal C# class to package the data.
Create a class to handle that data, for example:
I am assuming your CatFilter array is a string array:
public class Data{
public string cursorid { get; set;}
public string[] CatFilter {get; set;}
}
Then change your controller:
public ActionResult GetDataTweets(Data data)
{
var s1 = data.cursorid;
var s2 = data.CatFilter[0];
}
if CatFilter is a class then you'd need to create a CatFilter class to map to the javascript version.
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;