C# POST request with Json containing an array - c#

I have been using some simple requests in past to send JSON and they have been working fine. I basically take simple string, convert it to UTF-8 using
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
and send this using HttpWebRequest.
Now I have received a task to send a new POST request which will have an array of Ids and be of type
{
"GroupID": "Named_ID",
"ChildIds": [
"76197272-24E4-4DD2-90B8-46FDDCC0D6CA",
"D2B3A1AC-ACF6-EA11-A815-000D3A49E4F3",
"ED53D968-00F4-EA11-A815-000D3A49E4F3"
]
}
The ChildIds are available in a List(String []) with me. I could loop through the records and create a similar long string and then convert to byteArray in UTF8 but I feel this can be done in a simpler way. Examples that I have seen on the forum of using array in JSON always appear to use JsonConvert.SerializeObject but I am not clear if I should use this and if I do then do I convert the serialised object to UTF8 like I did earlier and is it then ok to use in the HttpWebRequest.
Can someone please advice on the approach I should take.

Create a class structure to match your json,
public class Data
{
public string GroupId {get;set;}
public List<string> ChildIds {get;set;}
}
serialize the data with JsonConvert or any other.
var json = JsonConvert.SerializeObject<Data>(str) ;
Post the serialized data with httpclient assuming you have it injected in your class already.
var data = new StringContent(json, Encoding.UTF8, "application/json");
var post = await client.PostAsync(url, data);

Related

Can you serialize ByteArrayContent in a JSON that translates to C# object?

I have written a C# Web API in VS Studio and have created numerous DTO's that get serialized into JSON entities which any client can consume. One of my API calls is to return a PDF file, so after some online research, I set up one of the DTO's is set up in the following format. I read somewhere you can do this, but not 100% sure:
public class MyCustomResult
{
public bool Success;
public DateTime? LastRunDate;
public string ErrorCode;
public string Message;
public ByteArrayContent ReportBody;
}
I do not get any errors when return the object as an IHttpActionResult:
return Ok(result);
I can see on the server that the ByteSize of the report byte[] is approx 700K. However, when I retrieve the object on the client, the JSON entity is approx 400B and no byte content in the ByteContentStream. When I run the query in Postman, I get an empty Header, so it appears that the ByteContentStream can't be serialized by Newtonsoft JSON.
Are there any options I should consider?
Here is a scenario where you'd use ByteArrayContent:
using(var req = new HttpRequestMessage(HttpMethod.Post, new Uri("https://example.com"))
{
req.Content = new ByteArrayContent(...);
using(var resp = await _client.SendAsync(req))
{
var data = await resp.Content.ReadAsAsync<object>();
}
}
What you'd want to do is this:
public class MyCustomResult
{
public bool Success;
public DateTime? LastRunDate;
public string ErrorCode;
public string Message;
public byte[] ReportBody; // <-- change this to byte[]
}
var dataToSend = new MyCustomResult(); // fill this in
using(var req = new HttpRequestMessage(HttpMethod.Post, new Uri("https://example.com"))
{
req.Content = new StringContent(
JsonConvert.SerializeObject(dataToSend, Encoding.UTF8, "application/json"));
using(var resp = await _client.SendAsync(req))
{
var data = await resp.Content.ReadAsAsync<object>();
}
}
(note: this code is not tested)
So what will happen is SerializeObject will convert that byte array into a Base64 string then send it.
The consumer would then have to decode that Base64 string. If it's another Newtonsoft.Json client and the model definitions match, then it will automatically decode it for you.
I understand you are doing an API endpoint. The above examples are to show the use of ByteArrayContent and why it exists in .NET. How you are returning data is correct: return Ok(response); as long as you fix your model.
So to sum it up:
ByteArrayContent is an implementation of HttpContent which is supposed to be used as a response body only. It's not to be used in conjunction with a JSON response.

How to include Json string in uri c# 6

I have a c# object: a list with objects (objects have ID and Name)
Now I need to include the list of objects (it should be json string as far as I understand) in URL as parameter. How is it possible to do it?
If I understand you correctly, you need this.
var client = new WebClient();
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
string response = client.UploadString("http://mysite", "json string");

API Controller unable to read Json from POST body

Background
I'm sending JSON in my body to my API controller but keep getting the following error.
{"":["Unexpected character encountered while parsing value: {. Path
'', line 1, position 1."]}
My HTTP request
HttpClient client = new HttpClient();
HttpRequest httpRequest;
HttpResponseMessage httpResponse = null;
httpRequest = new HttpRequest("", HostnameTb.Text, null);
var values = new Dictionary<string, string>
{
{ "APIKey", APIKeyTb.Text }
};
string json = JsonConvert.SerializeObject(values);
StringContent content = new StringContent(json.ToString(), Encoding.UTF8, "application/json");
httpResponse = client.PostAsync(HostnameTb.Text, content).Result;
var responseString = await httpResponse.Content.ReadAsStringAsync();
My Controller looks like this.
[HttpPost]
public void Post([FromBody] string value)
{
//Never gets here.
}
The Json in the body.
{"APIKey":"1283f0f8..."}
Question
I would prefer to use the .Net Core [From Body] functionality, rather than getting the content manually.
I would expect the JSON string to be available in the string Value parameter.
What am I missing?
ASP.NET Core tries to deserialize {"APIKey":"1283f0f8..."} from JSON into a string value, and fails, because it expects the input to be a valid JSON string.
In other words, if your body was "{\"APIKey\":\"1283f0f8...\"}" you would have the JSON string in the input variable as you expect.
In order to get the APIKey value without changing the HTTP request, create an input type:
public class Input
{
public string ApiKey { get; set; }
}
and use that as the input of your controller action:
[HttpPost]
public void Post([FromBody] Input input)
{
var apiKey = input.ApiKey;
// etc
}
Alternatively, change your HTTP request to send a string:
// ...
var content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");
// ...
Note the use of JsonConvert.SerializeObject() instead of ToString(); "foo".ToString() is still just "foo", while you want "\"foo\"".
That's not how this works. [FromBody] invokes a serializer to deserialize the request body. Then, the modelbinder attempts to bind that to the param. Here, it cannot do that because you're binding to a string, and the request body is a dictionary. Essentially what's happening under the hood (pseudo-code) is:
value = JsonConvert.DeserializeObject<string>(dictionaryAsJson);
You're getting a deserialization error from JSON.NET because it can't parse the JSON into a string.
If you want the value as a string, then you should post is as something like text/plain instead of application/json. Otherwise, you'll need to bind to a type that actually represents the JSON object coming in, which would be a Dictionary<string, string> here.
I had the same issue with ASP.NET Core 3.1. I was POSTing a JSON to my API controller that looked like:
public JsonResult Save([FromBody]MainDetails obj){ ... }
The problem in my case was that a property ChildDetails.StartDate of my MainDetails object was of type DateTime, and I was sending a null value in JSON. This was causing the deserialization to fail at the controller. I changed the property type to DateTime? from DateTime to make it work.
Basically, one needs to check and ensure that the JSON that you POST is valid for the target object to which you are deserializing it. If you have non-nullable properties for which the value sent in JSON is null, then your deserialization will fail (without telling you why).
Hope this helps.

My webservice wont work because HttpContentHeaders does not implement Add(System.Object)

I'm new to this one so please be gentle.
I am adding a method to a webservice so that it can recieve POSTs from another.
The POST contains a JSON object in the body with parameters I need in the receiving solution.
I am using HttpClient's PostAsync method to send the data (as FormUrlEncodedContent) and I'm trying to recieve it as HttpRequestMessage.
When i try to compile and build I get this error in my recieving service
To be XML serializable, types which inherit from IEnumerable must have
an implementation of Add(System.Object) at all levels of their
inheritance hierarchy. System.Net.Http.Headers.HttpContentHeaders does
not implement Add(System.Object).
The odd thing is that I use these both of these in the POSTing webservice (I use ajax on a page to test it) and don't get this problem.
This is the sender:
string url = *url*;
HttpClient client = new HttpClient();
Dictionary<string, string> parameters;
parameters = new Dictionary<string, string>
{
{ "*variablename1", *string* },
{ "variablename2", *string* },
{ "variablename3", *string* },
{ "variablename4", *string* }
};
var content = new FormUrlEncodedContent(parameters);
HttpResponseMessage response = client.PostAsync(url, content).Result;
And this is what is supposed to be receiving it...
public void Receive(HttpRequestMessage request)
{
string data = request.Content.ReadAsStringAsync().Result;
*Database object* = new *Database object*();
string decodedString = HttpUtility.UrlDecode(data);
*Stuff that processes decodedString into a dictionary and puts it in database*
What I'd like is to know how I can get this to work, so an alternative to HttpRequestMessage that doesn't depend on HttpContentheaders having an add method, or another way of sending the post that doesn't require them on the recieving end.
Apologies for vague bits of code, I've only been a programmer for three months and my company works with a lot of confidential data, I'm just covering my back.

Using the contents of a JsonObject on aspx web page

I am trying to use a HTTP request to return the contents of a json string from google shopping api. What I have so far seems to be working but I would like to know how I can use the contents of the object to display the data on a page.
public string HttpGet(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
try
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream);
return reader.ReadToEnd();
}
}
finally
{
response.Close();
}
}
protected void submit_Click(object sender, EventArgs e)
{
string json = HttpGet("https://www.googleapis.com/shopping/search/v1/public/products?key={KEY}4&country=UK&q=BX80637153570K&rankBy=price:ascending&maxResults=1&alt=json");
dynamic obj = JsonObject.Parse(json);
}
Ok looking at the responses it looks as though I need a C# class for the data returned in json. I have created a classes using json2csharp.com. This is the data I need to return from the Json and display on the page. Maybe it will help explain my problem better.
https://www.googleapis.com/shopping/search/v1/public/products?key=AIzaSyCC0j59RBeGNtf2W2ft6avhfoTdJ1FQ2c4&country=UK&q=BX80637153570K&rankBy=price:ascending&maxResults=1&alt=json
Can anyone advise how I can use this information on my website. I am a little lost now as I'm new to all this and have tried several different methods.I don't need all of the returned data if that makes a difference? Just price and link.
Supposing dynamic obj is rightly filled you can use it's content in web page
For examples, if json is:
{
"error" : {
"code": 400,
"message": "Bad Request"
}
}
You can access object properties with code like this:
Response.Write("Error code is" + obj.error.code);
Of course Response.Write is only a sample on how you can send retrieved data to the page.
Edit 1:
It seems json converter used in question is not working or not working right.
In many cases, it's overkill to create a concrete class only to parse a json, expecially since C# 4 that can use ExpandoObject
This is a sample on how you can deserialize in a dynamic object without the need to create a concrete object
var url = "http://www.google.com/ig/calculator?hl=en&q=100USD=?EUR";
string json = HttpGet(url);
//this is json string:
//{lhs: "100 U.S. dollars",rhs: "78.1799703 Euros",error: "",icc: true}
//now convert in a dynamic object
var jss = new DynamicJsonConverter();
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
dynamic obj = serializer.Deserialize(json, typeof(object));
//now you have access to json content
string text1 = obj.lhs;
string text2 = obj.rhs;
DynamicJsonConverter class can be created using code you can find here:
Deserialize JSON into C# dynamic object?
I think you need to deserialize the response
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
You will need to create a class with the property resulted by the response.
Say test class
class Test
{
//define a similar property here
// which you suppose it will be return in the response
}
Then
Test routes_list = (Test)json_serializer.DeserializeObject(yourjson);
Edit 1
Or you can go through this link
How to Convert JSON object to Custom C# object?

Categories