WebAPI - Posting to dictionary with json - c#

I have a web api method that looks like this:
[HttpPost]
[Route("messages")]
public IHttpActionResult Post(IEnumerable<Email> email)
{
AddToQueue(email);
return Ok("message added to queue");
}
My Email class looks like this currently:
public string Body { get; set; }
public string From { get; set; }
public string Template { get; set; }
public string To { get; set; }
public string Type { get; set; }
And I'm posting to my Post method using fiddler, like this:
User-Agent: Fiddler
Host: localhost:3994
Content-Length: 215
Content-Type: application/json; charset=utf-8
[
{"Body":"body","From":"from","To":"to","Template":"template"},
{"Body":"body1","From":"from1","To":"to1","Template":"template1"},
{"Body":"body2","From":"from2","To":"to2","Template":"template2"}
]
This works fine. However, I want to be able to add a Dictionary to my Email class, so it will look like this:
public string Body { get; set; }
public string From { get; set; }
public string Template { get; set; }
public string To { get; set; }
public string Type { get; set; }
public Dictionary<string, string> HandleBars { get; set; }
And I changed my request to look like this:
[{
"Body": "body",
"From": "from",
"To": "to",
"Template": "template",
"HandleBars": [{
"something": "value"
}]
},
{
"Body": "body1",
"From": "from1",
"To": "to1",
"Template": "template1"
},
{
"Body": "body2",
"From": "from2",
"To": "to2",
"Template": "template2"
}]
However, when the Post method receives this, all the Email fields are populated, except for the HandleBars dictionary. What do I have to do in order to pass it in correctly? Is my json structured incorrectly?

The default JsonFormatter is unable to bind Dictionary from Javascript Array because it doesn't define a key to each item.
You need to use an Object instead:
"HandleBars": {
"something": "value"
}

You should have
{
"Body": "body",
"From": "from",
"To": "to",
"Template": "template",
"HandleBars": [
{ key: 'key1', value: 'something'}
]
}

Related

How to deserialize a JSON

I am attempt to use an API that use the follow example structure for their returned json:
[{
"name":"Firs",
"id":"0",
"data": {"scale":"1","size":"500"}
},
{
"name":"Second",
"id":"1",
"data":"222"
}]
Upade "[ ]"
But I can not figure out how to get it to be happy with the provided structure.
Using Newtonsoft I am able to Serialize and Deserialize a model shown below:
List<RequestJson> requestJson = JsonConvert.DeserializeObject<List<RequestJson>>(json);
public class GetData
{
public int Scale { get; set; }
public int Size { get; set; }
}
public class RequestJson
{
public string Name { get; set; }
//Problem is here
public GetData Data { get; set; }
}
Your JSON is not valid. The Data property does not match the object type.
Correct JSON:
[{
"name":"Firs",
"id":"0",
"data": {"scale":"1","size":"500"}
},
{
"name":"Second",
"id":"1",
"data": {"scale":"2","size":"600"}
}]

WebApi Not Deserializing Correctly

I'm at my wit's end here. I think I just need another set of eyes.
Method Signature:
public async Task<IHttpActionResult> Post(ApiRequest request)
Model:
[SuppressMessage("ReSharper", "CollectionNeverUpdated.Global")]
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global")]
public class ApiRequest
{
[JsonProperty("allowLoadingToDataWarehouse")]
public bool AllowLoadingToDataWarehouse { get; set; }
[JsonProperty("initialDelay")]
public string InitialDelay { get; set; }
[JsonProperty("reportIds")]
public IEnumerable<string> ReportIds { get; set; }
[JsonProperty("reportTypeDelay")]
public string ReportTypeDelay { get; set; }
[JsonProperty("runType")]
[JsonConverter(typeof(StringEnumConverter))]
public ReportRunType RunType { get; set; }
[JsonProperty("userId")]
public string UserId { get; set; }
[JsonProperty("wwDelay")]
public string WWDelay { get; set; }
[JsonProperty("weeks")]
public IEnumerable<string> Weeks { get; set; }
}
Javascript:
var submitReportRequest = {
userId: userid,
reportIds: reportids,
runType: 'Custom',
weeks: selectedweeks,
initialDelay: $('#InitialDelay').val(),
reportTypeDelay: $('#ReportTypeDelay').val(),
wwDelay: $('#WWDelay').val(),
allowLoadingToDataWarehouse: $('#AllowLoadingToDataWarehouse').val()
};
$.post("/api/SubmitReport", JSON.stringify(submitReportRequest), function (data) {
alert('success');
});
Serialized Json From JavaScript Post:
{
"userId": "30",
"reportIds": [
"59",
"60",
"61",
"62",
"63",
"64"
],
"runType": "Custom",
"weeks": [
"201409",
"201410",
"201411",
"201412"
],
"initialDelay": "00:00:00",
"reportTypeDelay": "00:00:00",
"wwDelay": "00:00:00"
}
Quickwatch of Deserialized Object
Initially I had int and TimeSpan for the Ids and Delays, respectively, and those were not deserializing correctly. So I changed them all to strings, and they're still not deserializing correctly.
What am I doing wrong or missing?
Edit: After trying every combination of attributes, I finally decided to stick it into the Fiddler Composer. And it works. So something must be off with my JavaScript.
Turns out that shorthand JQuery post() method was setting the Content-Type attribute on the Request to application/x-www-form-urlencoded; charset=UTF-8 when it needed to be set to application/json; charset=UTF-8
I found by watching the Network traffic in Chrome, and by changing my javascript to this
answer.

C# Deserialize list in JSON

Suppose I have JSON like this, how can I model my class for deserialization?
I have no problems to model class for standard attribute like "dummy" or normal arrays, but in this case, my "links" array is a list of items with different name ("addons", "conditions", "conversion", etc.).
"dummy": "1",
"links": {
"addons": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/addons",
"method": "GET"
},
"conditions": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/conditions",
"method": "GET"
},
"conversions": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/conversions",
"method": "GET"
},
"list_prices": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/list-prices",
"method": "GET"
},
"mutual_exclusion": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/mutually-exclusive-offers",
"method": "GET"
},
"prerequisites": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/offers/031C9E47-4802-4248-838E-778FB1D2CC05/prerequisites",
"method": "GET"
},
"product": {
"href": "/16071d9f-efec-4282-a42e-a495eea76ae0/products/f245ecc8-75af-4f8e-b61f-27d8114de5f3",
"method": "GET"
}
},
Assuming you are specifically looking for the set of LinkTypes if you will, in your JSON, could you use something like the following, and execute the Deserialize on the RootObject?
Working dotNet Fiddle: https://dotnetfiddle.net/ZWSlK4
Check out the output on the Console pane on the fiddle page.
public class Link
{
public string Href { get; set; }
public string Method { get; set; }
}
public class Links
{
[JsonProperty("addons")]
public Link Addons { get; set; }
[JsonProperty("conditions")]
public Link Conditions { get; set; }
[JsonProperty("conversions")]
public Link Conversions { get; set; }
[JsonProperty("list_prices")]
public Link ListPrices { get; set; }
[JsonProperty("mutual_exclusion")]
public Link MutualExclusion { get; set; }
[JsonProperty("prerequisites")]
public Link Prerequisites { get; set; }
[JsonProperty("product")]
public Link Product { get; set; }
}
public class RootObject
{
public string dummy { get; set; }
public Links links { get; set; }
}
and then execute the Deserializer like so.
var myDummyLinksList = JsonConvert.DeserializeObject<RootObject>(jsonText);
where jsonText contains the json string you have listed in your example:
However, if you List of links objects is dynamic and the number of objects inside varies and you need to capture all of them, then you might have to write a custom Converter that inherits from the JsonConverter object. then use the answer that #mfarouk has posted.
I forked my dotNet Fiddle and implemented his solution and it works like a boss for the dynamic case!
Working dotNet Fiddle (dynamic case): https://dotnetfiddle.net/7bFcNM
Hope this helps!
the links attribute could be parsed as key, value dictionary , the class can be like
public class JSONClass
{
public string dummy { get; set; }
public Dictionary<string, Link> links;
public class Link
{
public string Href { get; set; }
public string Method { get; set; }
}
}
then de-serialized as
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JSONClass>(JSON);

Deserialize JSON String with multiple possible object name in one class

I'm doing a server request of 3 different users from a game.
I got this JSON String as a result:
{
"d4r1o": {
"id": 1040806,
"name": "D4R1O",
"profileIconId": 596,
"revisionDate": 1399366400000,
"summonerLevel": 30
},
"snnovox": {
"id": 65728,
"name": "SN Novox",
"profileIconId": 548,
"revisionDate": 1399369344000,
"summonerLevel": 30
},
"gmbecken": {
"id": 421545,
"name": "GM Becken",
"profileIconId": 26,
"revisionDate": 1399160360000,
"summonerLevel": 30
}
}
So in order to deserialize this string I have these classes
public class RootObject
{
public SummonerDto d4r1o { get; set; }
public SummonerDto snnovox { get; set; }
public SummonerDto gmbecken { get; set; }
}
public class SummonerDto
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public long revisionDate { get; set; }
public int summonerLevel { get; set; }
}
This works just fine, but what if the user wants to make a request about his own username, for example: snyucax
{"snyucax": {
"id": 48985,
"name": "SN YucaX",
"profileIconId": 504,
"revisionDate": 1399257043000,
"summonerLevel": 30
}}
Is there a way to make only one object in the RootObject Class that let me take any username without having to especify that name as an object?
It looks like your data is better modeled as a dictionary. Use
JsonConvert.DeserializeObject<Dictionary<string, SummonerDto>>(myJson)
You should use a dictionary for this. If you're using JSON.NET, then the code would look like:
var users = JsonConvert.DeserializeObject<Dictionary<string, SummonerDto>>(jsonDataString);
Then you could get the user by going:
var user = users["d4r1o"];
e: Seems Tim S just beat me to the punch, haha.
I think you should not hardwire your objects. Instead use a dictionary or send the username and form a json object based on the user and deserialize it at the client's browser o app

MVC 4 Web API How to prepare JSON body for Request

Hi I have a function that will expose to the RestAPI. I need to pass in a JSON string to be a defined class. I use the following class for JSON format:
public class Registrant : Guest
{
public int RegistrantID { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public int EventID { get; set; }
public bool IsPrimary { get; set; }
}
And I have the following function in my controller:
public HttpResponseMessage Create(string id, [FromBody]Registrant registrant)
However When I pass in the JSON string the same structure, it could not deserialize correctly.
Is there anything wrong with it?
PS: my JSON string in request body:
{
"RegistrantID":"0",
"Email": "abc#abc.com",
"Phone": "123456789",
"EventID": "8",
"IsPrimary": "true",
"CustomerId": "12345678",
"FirstName": "abc",
"LastName": "def"
}
Update:
The problem is resolved by choosing Content-Type as Application/Json
Also, I took out the quotes on int and bool params it works fine.
Finally the api call look like this in project:
public HttpResponseMessage Create([FromUri]string id, [FromBody]Registrant registrant)

Categories

Resources