JavaScriptSerializer deserialize object "collection" as property in object failing - javascript

I have a js object structured like:
object.property1 = "some string";
object.property2 = "some string";
object.property3.property1 = "some string";
object.property3.property2 = "some string";
object.property3.property2 = "some string";
i'm using JSON.stringify(object) to pass this with ajax request. When i try to deserialize this using JavaScriptSerializer.Deserialize as a Dictionary i get the following error:
No parameterless constructor defined for type of 'System.String'.
This exact same process is working for regular object with non "collection" properties.. thanks for any help!

It's because the deserializer doesn't know how to handle the sub-object. What you have in JS is this:
var x = {
'property1' : 'string',
'property2' : 'string',
'property3' : { p1: 'string', p2: 'string', p3: 'string' },
};
which doesn't have a map to something valid in C#:
HashTable h = new HashTable();
h.Add("property1", "string");
h.Add("property2", "string");
h.Add("property3", ???);
The ??? is because there's no type defined here, so how would the deserializer know what the anonymous object in your JS represents?
Edit
There is no way to do what you're trying to accomplish here. You'll need to make your object typed. For example, defining your class like this:
class Foo{
string property1 { get; set; }
string property2 { get; set; }
Bar property3 { get; set; } // "Bar" would describe your sub-object
}
class Bar{
string p1 { get; set; }
string p2 { get; set; }
string p3 { get; set; }
}
...or something to that effect.

As a more general answer, in my case I had objects that looked like:
{ "field1" : "value", "data" : { "foo" : "bar" } }
I originally had the data field as a string when it should've been a Dictionary<string, string> as specified on MSDN for objects that use dictionary syntax.
public class Message
{
public string field1 { get; set; }
public Dictionary<string, string> data { get; set; }
}

Related

Pass an Object from Angularjs to MVC controller and map to Class Object

I have an object in angularjs which I want to pass and map it to custom c# class in mvc controller. but whenever I am doing this class object is null completely.
$scope.Get = function () {
var EService = [{
id: $scope.Id,
servicename: $scope.ServiceName,
servicetype: $scope.ServiceType,
monthlyrental: $scope.MonthlyRental,
serviceremarks: $scope.ServiceRemarks,
servicestatus: $scope.status,
activationdate: $scope.ActivationDate,
deactivationdate: $scope.DeActivationDate
}];
$http.post('/TS/API/Insert', Service).then(function (res) {
debugger;
})
MVC Controller and Class:
[HttpPost]
public string Insert(ServicesMaster Service)
{
GIBCADBEntities gfientity = new GIBCADBEntities();
var record = "Sent"
return Json(record, JsonRequestBehavior.AllowGet);
} public class ServicesMaster
{
public string id { set; get; }
public string servicename { set; get; }
public string servicetype { set; get; }
public int? monthlyrental { set; get; }
public string serviceremarks { set; get; }
public byte servicestatus { set; get; }
public DateTime? activationdate { set; get; }
public DateTime? deactivationdate { set; get; }
}
The javascript variable/object "EService" is ok here, and when passing only the ServicesMaster object is created with null values and no data is mapped to it. I can send single string or any value from here but when sending a complete object its behaving like this.
You are passing an array from front end and fetching object from server end. just remove the "[" and "]" brace while set value to EService . Like :
$scope.Get = function () {
var Service = {};
Service = {
id: $scope.Id,
servicename: $scope.ServiceName,
servicetype: $scope.ServiceType,
monthlyrental: $scope.MonthlyRental,
serviceremarks: $scope.ServiceRemarks,
servicestatus: $scope.status,
activationdate: $scope.ActivationDate,
deactivationdate: $scope.DeActivationDate
};
$http.post('/TS/API/Insert', Service).then(function (res) {
debugger;
});
};
It should work now. :)

Passing complex object to WebAPI from AngularJS

I am trying to post a JavaScript item to a C# WebAPI call using AngularJS. Below is what I am trying to do.
Objects
class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address address { get; set; }
}
My C# Controller function
[Route("Update/")]
public void Update(Person person)
{
_service.Update(person);
}
AngularJS call
this.update = function (person) {
$http.post("api/Person/Update/", person);
}
When I receive the object in the WebAPI controller the address is null. Why is this data not being received?
Edit
I was wrong in my original question the Person object looked like this
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public IAddress address { get; set; }
}
When I changed address from IAddress to Address everything worked as expected.
Your post would be in json format which will assign person object to person, Address object must be well formed object as it contain sub properties.
Code
$scope.person = {
'Street': '',
'LastName': '',
'Address': {
'Street': '',
'City': '',
'State': '',
},
}
this.update = function (person) {
$http.post("api/Person/Update/", { person : $scope.person});
}
This approach allows to send complex objects with arrays and sub objects through HTTP GET:
Angular:
$http({
url: '/myApiUrl',
method: 'GET',
params: { personStr: angular.toJson(person, false) }
})
C#:
[HttpGet]
public string Get(string personStr)
{
Person obj = new JavaScriptSerializer().Deserialize<Person>(personStr);
...
}
What you want to do is not possible, but this solution allows you to use your complex object on the .NET side. There is no body in a GET request, so you have to add your object into the URI.
Change your web api method to:
[Route("Update/")]
public void Update([FromUri]Person person)
{
_service.Update(person);
}
Change your angular code to:
this.update = function (person) {
$http.post("api/Person/Update?FirstName=John&LastName=Doe&Address%5BStreet%5D=123%20Main%20St&Address%5BCity%5D=Knoxville&Address%5BState%5D=Tennessee");
}

JSON serialization - how to unquote a property value?

Given a class A ...
public class A {
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
string jsonString = JsonConvert.SerializeObject(
new A() {
Prop1 = "ABC",
Prop2 = "$.jqplot.DateAxisRenderer" }
);
jsonString contains...
"{
\"Prop1\":\"ABC\",
\"Prop2\":\"$.jqplot.DateAxisRenderer\"
}";
Question:
How can I unquote Prop2?
i.e. I want jsonString to contain...
"{
\"Prop1\":\"ABC\",
\"Prop2\":$.jqplot.DateAxisRenderer
}";
so that Prop2 is evaluated (on the client) as a reference and not a string
If you want to remove the quotes from Prop2, you can write a JSON.NET JsonConverter for the type and output the property value as 'raw'.
However (and this is important), your output will no longer be valid JSON.
If you're happy with this hybrid solution, some example code is as follows (assuming you've already referenced JSON.NET in your project):
namespace JsonRawTest
{
public class AConverter : JsonConverter
{
public override bool CanRead { get { return false; } }
public override bool CanWrite { get { return true; } }
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
A obj = value as A;
writer.WriteStartObject();
writer.WritePropertyName("Prop1");
writer.WriteValue(obj.Prop1);
writer.WritePropertyName("Prop2");
writer.WriteRawValue(obj.Prop2);
writer.WriteEndObject();
}
public override bool CanConvert(Type objectType)
{
return typeof(A).IsAssignableFrom(objectType);
}
}
public class A
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var a = new A
{
Prop1 = "Some first value",
Prop2 = "$.jqplot.DateAxisRenderer"
};
string json = JsonConvert.SerializeObject(a,
new JsonConverter[] { new AConverter() });
...
}
}
}
You can pass it to the client as a string and then use the eval() function to parse the string like so:
var str = "alert('hello')";
eval(str); //This will execute the alert method.
var str2 = "(function() { return true; })()";
var returned = eval(str2); //Holds value of true

deserialize nested json object in c#

I have json object in javascript as
{"CategoryID":"1","CountryID":"1","CountryName":"United Arab Emirates",
"BillerID":"23","AccountNo":"1234567890",
"Authenticators":"{\"ConsumerNumber\":\"1234567890\",\"LastBillDate\":\"14-10-2014\",\"LastBillDueDate\":\"24-11-2014\"}",
"ShortName":"0000000001"}
I have similar c# class as
[Serializable]
public class UserContext
{
public string CategoryID { get; set; }
public string BillerID { get; set; }
public string AccountNo { get; set; }
public string Authenticators { get; set; }
public string ShortName { get; set; }
public string CountryID { get; set; }
public string CountryName { get; set; }
}
I can get each element value in c# as
UserContext obj1 = Deserialize<UserContext>(context);
But as Authenticators is nested json object i want something like this in C#
[Serializable]
public class Authenticators
{
public string ConsumerNumber { get; set; }
public string LastBillDate { get; set; }
public string LastBillDueDate { get; set; }
}
So that i can get each value of each Authenticators element like
string value = obj.ConsumerNumber;
I want to populate two classes with values. How can i achieve the same ?
Your UserContext class has a string field Authenticators, while the json structure suggests it's an object.
Change
public string Authenticators { get; set; }
to
public Authenticators Authenticators { get; set; }
Then you can deserialize the UserContext object along with the nested object Authenticators
UserContext obj1 = Deserialize<UserContext>(context);
var consumerNumber = obj1.Authenticators.ConsumerNumber;
UPDATE:
You probably need to fix javascript code, bacause now it stores already serialized json string as a string field inside UserContext object.
What you have now, is something similar to:
var data =
{
CategoryID:"1",
Authenticators: JSON.stringify({ConsumerNumber:"1234567890"})
};
var json = JSON.stringify(data);
It should be like:
var data =
{
CategoryID:"1",
Authenticators:{ConsumerNumber:"1234567890"}
};
var json = JSON.stringify(data);
just change
public string Authenticators { get; set; }
to
public Authenticators Authenticators { get; set; }
then you can access the properties of the inner object simply by
var number = obj1.Authenticators.ConsumerNumber;
but i noticed that your JSON had some problems when deserializing using Newtonsoft, i had to change the value of Authenticators in the JSON string to
'Authenticators':{'ConsumerNumber':'1234567890','LastBillDate':'14-10-2014','LastBillDueDate':'24-11-2014'},
just remove the backslash
Once you've deserialized the outer object, you can run another deserialize on the Authenticators JSON string, which is now a property on obj1.
This is required because your Authenticators is a string, it is escaped and thus can't be deserialized until the outer object is deserialized.
Authenticators obj2 = Deserialize<Authenticators>(obj1.Authenticators);
string value = obj2.ConsumerNumber;

How to create nested list of objects in javascript

I am trying to create Product instance in Javascript and than to pass it to the server using [webmethod].
[WebMethod]
public static void SetProduct(Product product)
{
// i want a product instance
}
Following is Product class that i'm trying to create:
public class Product
{
public Type Type { get; set; }
public Foo Foo { get; set; }
public List<Bar> Bars { get; set; }
}
public class Type
{
public string ID { get; set; }
}
public class Foo
{
public string ID { get; set; }
public string Color { get; set; }
}
public class Bar
{
public string Name { get; set; }
}
I am being able to create Type and Foo but not List<Bar> in Javascript: (see my comments in the code for more details)
Javascript
function setProduct() {
var product = {};
product.Type = {};
product.Foo = {};
product.Type.ID = 'typeID';
product.Foo.ID = 'fooID';
product.Foo.Color = 'fooColor';
//here is my question how can create List<Bar> Bars and add it to product item???
$.ajax({
type: "POST",
url: "Default.aspx/SetProduct",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
data: "{product:" + JSON.stringify(product) + "}",
});
}
JavaScript doesn't know what a List<T> is. It only knows how to make arrays. So you'll have to construct an array of Bars and pass that in the JSON.
Fortunately, it's an easy fix:
product.Bars = [
{ Name: "bar 1" },
{ Name: "bar 2" },
{ Name: "bar 3" },
];
The above is probably all you need. I'm pretty sure ASP.NET will be smart enough to convert that Bar[] into a List<Bar> automagically, but just in case it isn't:
public class Product
{
public Type Type { get; set; }
public Foo Foo { get; set; }
public IEnumerable<Bar> Bars { get; set; }
}
Then if you still want List<T> functionality, just convert the array to a List in your WebMethod:
[WebMethod]
public static void SetProduct(Product product)
{
var list = product.Bars.ToList();
product.Bars = list;
return product;
}
Now you can still access those nice List<T> methods:
((List<Bar>)product).Add(new Bar() { Name = "bar 4" });
// create an array
product.Bars = [];
// add an element to the array
product.Bars.push({
Name: "Foo"
});
alternatively you can initialize the array with elements as well:
// create and initialize array
product.Bars = [{Name:"Foo"}, {Name:"Bar"}];
Use an array, and add the items to the array with array.push. Eg :
product.Bars = [];
product.Bars.push({ Name: "foo" });

Categories

Resources