Pass argument to webapi having a List property - c#

I have a web api which accepts a class as argument (MyClass). In which a property is of type list. How shall i pass the argument so that the web api receives a list in that property field.
When i pass Id=1&Name=ABC&MyList=[{AnotherClassName : "The Name"}] in the POST body using REST client, i am getting the values only in Id and Name field. How shall i send the params in POST body, so that i receives a List of "AnotherClass" in the "MyList"
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public List<AnotherClass> MyList { get; set; }
}
public class AnotherClass
{
public int AnotherClassName { get; set; }
}
Thanks

You need to pass the JSON like this
{"Id":1,"Name":"abc","MyList":[{"AnotherClassName":1}]}
actually you mase a mistake in MyList object. The property AnotherClassName data type is int and you are passing it to string value and also enclose are your JSON to braces {....}.
The better way you should use NewtonSoft.JSON to convert your object to json before sending.
MyClass mc = new MyClass();
mc.Id = 1;
mc.Name = "abc";
List<AnotherClass> acl = new List<AnotherClass>();
acl.Add(new AnotherClass { AnotherClassName = 1 });
mc.MyList = acl;
var serializedData = JsonConvert.SerializeObject(mc);

Related

AutoMapper: mapping many properties into one

The scenario is the following: I receive a message containing a lot of variables, several hundreds. I need to write this to Azure Table storage where the partition key is the name of the individual variables and the value gets mapped to e.g. Value.
Let’s say the payload looks like the following:
public class Payload
{
public long DeviceId { get; set; }
public string Name { get; set; }
public double Foo { get; set; }
public double Rpm { get; set; }
public double Temp { get; set; }
public string Status { get; set; }
public DateTime Timestamp { get; set; }
}
And my TableEntry like this:
public class Table : TableEntity
{
public Table(string partitionKey, string rowKey)
{
this.PartitionKey = partitionKey;
this.RowKey = rowKey;
}
public Table() {}
public long DeviceId { get; set; }
public string Name { get; set; }
public double Value { get; set; }
public string Signal { get; set; }
public string Status { get; set; }
}
In order to write that to Table storage, I need to
var table = new Table(primaryKey, payload.Timestamp.ToString(TimestampFormat))
{
DeviceId = payload.DeviceId,
Name = payload.Name,
Status = payload.Status,
Value = value (payload.Foo or payload.Rpm or payload.Temp),
Signal = primarykey/Name of variable ("foo" or "rmp" or "temp"),
Timestamp = payload.Timestamp
};
var insertOperation = TableOperation.Insert(table);
await this.cloudTable.ExecuteAsync(insertOperation);
I don’t want to copy this 900 times (or how many variables there happen to be in the payload message; this is a fixed number).
I could make a method to create the table, but I will still have to call this 900 times.
I thought maybe AutoMapper could help out.
Are they always the same variables? A different approach could be to use DynamicTableEntity in which you basically have a TableEntity where you can fill out all additional fields after the RowKey/PartitionKey Duo:
var tableEntity = new DynamicTableEntity();
tableEntity.PartitionKey = "partitionkey";
tableEntity.RowKey = "rowkey";
dynamic json = JsonConvert.DeserializeObject("{bunch:'of',stuff:'here'}");
foreach(var item in json)
{
tableEntity.Properties.Add(item.displayName, item.value);
}
// Save etc
The problem is to map these properties, it is right?
Value = value (payload.Foo or payload.Rpm or payload.Temp),
Signal = primarykey/Name of variable ("foo" or "rmp" or "temp"),
This conditional mapping can be done via Reflection:
object payload = new A { Id = 1 };
object value = TryGetPropertyValue(payload, "Id", "Name"); //returns 1
payload = new B { Name = "foo" };
value = TryGetPropertyValue(payload, "Id", "Name"); //returns "foo"
.
public object TryGetPropertyValue(object obj, params string[] propertyNames)
{
foreach (var name in propertyNames)
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(name);
if (propertyInfo != null) return propertyInfo.GetValue(obj);
}
throw new ArgumentException();
}
You may map rest of properties (which have equal names in source and destination) with AutoMapper.Mapper.DynamicMap call instead of AutoMapper.Mapper.Map to avoid creation of hundreds configuration maps. Or just cast your payload to dynamic and map it manually.
You can create a DynamicTableEntity from your Payload objects with 1-2 lines of code using TableEntity.Flatten method in the SDK or use the ObjectFlattenerRecomposer Nuget package if you are also worried about ICollection type properties. Assign it PK/RK and write the flattened Payload object into the table as a DynamicTableEntity. When you read it back, read it as DynamicTableEntity and you can use TableEntity.ConvertBack method to recreate the original object. Dont even need that intermediate Table class.

Deserialize JSON string into a list for dropdownlist in C#

I have a windows form application and would like to deserialize a JSON string that I'm getting from a web address so that I can get just two values from it, how would I go about doing this?
Below is the code I have to get the JSON string, and if you go to the URL that it's getting, you can also see the JSON string. I want to just get the item name, and current price of it. Which you can see the price under the current key.
private void GrabPrices()
{
using (WebClient webClient = new System.Net.WebClient())
{
WebClient n = new WebClient();
var json = n.DownloadString("http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item=1513");
string valueOriginal = Convert.ToString(json);
Console.WriteLine(json);
}
}
It's also going to be iterating through a SQLite database and getting the same data for multiple items based on the item ID, which I'll be able to do myself.
EDIT I'd like to use JSON.Net if possible, I've been trying to use it and it seems easy enough, but I'm still having trouble.
Okay so first of all you need to know your JSON structure, sample:
[{
name: "Micheal",
age: 20
},
{
name: "Bob",
age: 24
}]
With this information you can derive a C# object
public class Person
{
public string Name {get;set;}
public int Age {get;set;}
}
Now you can use JSON.NET to deserialize your JSON into C#:
var people = JsonConvert.DeserializeObject<List<Person>>(jsonString);
If you look at the original JSON it is an array of objects, to deal with this I have used List<T>.
Key things to remember, you need to have the C# object mirror in properties that of the JSON object. If you don't have a list, then you don't need List<T>.
If your JSON objects have camel casing, and you want this converted to the C# conventions, then use this:
var people = JsonConvert.DeserializeObject<List<Person>>(
jsonString,
new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
First of all you need to create a class structure for the JSON
public class Wrapper
{
public Item item;
}
public class Item
{
public string icon { get; set; }
public string icon_large { get; set; }
public int id { get; set; }
public string type { get; set; }
public string typeIcon { get; set; }
public string name { get; set; }
public string description { get; set; }
public GrandExchange current { get; set; }
public GrandExchange today { get; set; }
public bool members { get; set; }
public GrandExchange day30 { get; set; }
public GrandExchange day90 { get; set; }
public GrandExchange day180 { get; set; }
}
public class GrandExchange
{
public string trend { get; set; }
public string price { get; set; }
}
Then you need to serialize the current item into a Wrapper class
var wrapper = JsonConvert.DeserializeObject<Wrapper>(json);
Then if you want multiple items in a list, you can do so with this code :
// Items to find
int[] itemIds = {1513, 1514, 1515, 1516, 1517};
// Create blank list
List<Item> items = new List<Item>();
foreach (int id in itemIds)
{
var n = new WebClient();
// Get JSON
var json = n.DownloadString(String.Format("http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item={0}", id));
// Parse to Item object
var wrapper = JsonConvert.DeserializeObject<Wrapper>(json);
// Append to list
items.Add(wrapper.item);
}
// Do something with list
It is also worth noting that Jagex limit how many times this API can be called from a certain IP within a time frame, going over that limit will block your IP for a certain amount of time. (Will try and find a reference for this)

deserialize json in C# with illegal variable characters

I'm writing a .NET library (using Newtonsoft) that interacts with a REST service, and I have a service that's returning json, but the json id field is called '$id'. So I can't just create a corresponding $id property in my C# data class. I tried to use something like
[JsonObject(MemberSerialization.OptOut)]
public class DocData
{
[JsonProperty("$id")]
public string id { get; set; }
public string Name { get; set; }
}
but while Name gets assigned, the id property does not. Anyone know how to map this json key to .NET?
Thanks
It looks like this is a bug in JSON.NET, and I think you should report it. It works fine in LINQPad for any property name except $id.
void Main()
{
var s = JsonConvert.SerializeObject(new DocData{id = "hi", Name = "world"}).Dump();
JsonConvert.DeserializeObject<DocData>(s).Dump();
}
public class DocData
{
// [JsonProperty("i$d")] // this would work
// [JsonProperty("_id")] // as would this
// [JsonProperty("$name")] // and even this
[JsonProperty("$id")] // but this fails
public string id { get; set; }
public string Name { get; set; }
}
Evidently Json.NET uses $id as a reserved word to help it deal with object references.
var dd = new DocData{id = "hi", Name = "world"};
JsonConvert.SerializeObject(new[]{dd, dd}, new JsonSerializerSettings{PreserveReferencesHandling = PreserveReferencesHandling.Objects}).Dump();
// Output: [{"$id":"1","$id":"hi","Name":"world"},{"$ref":"1"}]
Still, it seems like it should let you capture the $id property if you're not using reference handling.
As a workaround, you can parse it into a JObject, and pull the property out directly:
var id = JObject.Parse(s)["$id"];
var obj = JsonConvert.DeserializeObject<DocData>(s);
obj.id = id;

JSON Object to properties

I want to store the results from JSON in properties, but I don't know how. I'm using ASP.NET with MVC 4/Razor.
My model's constructor is:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(url);
JObject _naturalUserObject = (JObject)JsonConvert.DeserializeObject(response);
}
And I have the follow properties:
[Key]
public int Id { get; set; }
public int DisplayName { get; set; }
public int Avatar { get; set; }
To access a simple value from my JSON:
_naturalUserObject["users"][0]["name"];
The final question is: how can I store each value from my JObject in my model's properties and finally display it into my view?
Thanks in advance.
/EDIT/
My model now is:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(String.Format("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={0}&steamids={1}", ConfigurationManager.AppSettings["SteamApiKey"].ToString(), HttpContext.Current.Request.Cookies["SteamIdCookie"].Value));
string _naturalUserObject = JsonConvert.DeserializeObject<string>(response);
}
And one of my property is:
private string _avatar;
public string Avatar
{
get { return _avatar; }
set { _avatar = _naturalUserObject["response"]["players"][0]["avatar"]; }
}
But without success. =(
Lets say you have the following Json
string yourJsonString = "{\"FIRST_NAME\":\"Foo\",\"LAST_NAME\":\"Bar\"}";
You could model this Json as:
public class JsonModel
{
[JsonProperty("FIRST_NAME")]
public string FirstName {get; set;}
[JsonProperty("LAST_NAME")]
public string LastName {get; set;}
}
Note that you can use JsonPropertyAttribute to tell Json.Net what the property's corresponding json field is.
Now, that you have your model set up, can use JsonConvert.DeserializeObject<T>(...) to get a strongly typed instance of your json model.
JsonModel jsonModel = JsonConvert.DeserializeObject<JsonModel>(yourJsonString);
string firstName = jsonModel.FirstName; // Foo
string lastName = jsonModel.LastName; // Bar
As someone had mentioned, if you do it this way, you won't have to deal with JObject and moreover, it will force you to actually understand the structure of the json being returned.
Specifically in your example, you could store an object of type JsonModel and in your model's constructor initialize it using JsonConvert.DeserializeObject<T>. Your public properties could then just call into that JsonModel instance and get the appropriate values.
Here's a more detailed example. Assume you are getting back the json I had provided above and are using the same model we created before. Let's say you have a private field in your class of type JsonModel
private JsonModel jsonModel;
You can initialize it in your constructor:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(url);
jsonModel = JsonConvert.DeserializeObject<JsonModel>(response);
}
Now, your public properties can simply call into this JsonModel object.
public string FirstName
{
get { return jsonModel.FirstName; }
set { jsonModel.FirstName = value; }
}
I recommend ServiceStack.Text (available as a standalone NuGet package install, without the rest of the framework if you don't need it).
This adds two nice extension methods:
public class MyPOCO
{
public string Name {get; set; }
public int Age {get; set; }
}
And later:
string json = myPocoInstance.ToJson();
and:
MyPOCO instance = jsonString.FromJson<MyPOCO>();
Very fast too!
If you use Json.net you can deserialize directly into a clr object (which could be your viewmodel or model), you won't have to deal with JObject.
JsonConvert.DeserializeObject<myviewmodelormodel>(myjsondata);
If you get the object back as a string in JSON format. You can use the JSON de-serializer like this:
Put this into a static class this will become an extension method to all strings
public static T Deserialize<T>(this string json)
{
var obj = Activator.CreateInstance<T>();
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = (T) serializer.ReadObject(ms);
}
return obj;
}
EX:
this calls a url getting the result set in a string, then calls the
extension method to return an object.
the url returns MyPOCO
var stringValue = HttpGet(url);//how you get the value from a web service call
var myUserModel = stringValue.Deserialize<MyPOCO>();

servicestack.text deserializing array to object

I have a REST-Service build with ServicStack and in one call the user can send different types of values. So I made the property in C# of type object.
The JSON that is sent looks like this:
{"name":"ffff","params":[{"pId":1,"value":[624,625]},{"pId":2,"value":"xxx"}]}
The part "value":[624,625] results in a string object filled with "[624,625]". I was hoping to get an int-array or at least a string array, but it is plain string.
I set JsConfig.TryToParsePrimitiveTypeValues = true, but that doesn't seem to have any effect.
I tried the latest sources from github.
Can this be done with any combination of switches or must I parse this myself?
Thanks
EDIT:
Here is some testcode:
[TestMethod]
public void JsonTest()
{
string json = "{\"name\":\"ffff\",\"params\":[{\"pId\":1,\"value\":[624,625]},{\"pId\":2,\"value\":\"xxx\"}]}";
var x = JsonSerializer.DeserializeFromString<xy>(json);
Assert.AreEqual(x.Params[0].Value.GetType(), typeof(int[]));
}
public class xy
{
public string Name { get; set; }
public List<Param> Params { get; set; }
}
public class Param
{
public int PId { get; set; }
public object Value { get; set; }
}
If you change the type of "Value" to int array as follows, then ServiceStack will serialize to array of int.
public class Param
{
public int PId { get; set; }
public int[] Value { get; set; }
}
The following unit test passes:
[TestMethod]
public void JsonTest()
{
string json = "{\"name\":\"ffff\",\"params\":[{\"pId\":1,\"value\":[624,625]},{\"pId\":2,\"value\":\"xxx\"}]}";
var x = JsonSerializer.DeserializeFromString<xy>(json);
Assert.AreEqual(x.Params[0].Value.GetType(), typeof(int[]));
// Show that we have some integers
Assert.IsTrue(x.Params[0].Value.Count()>0);
}
If you cannot change the type of Value for any reason, then you can use ServiceStack.Text to serialize the string into an array as needed.

Categories