Extracting data from response.Content.ReadStringASync - c#

I am currently trying to extract data from my Web Service. I managed to get success response from the Web Service using HTTPClient. However, I am unable to extract specific values. For instance, my JSON document read as
{"d":[{"__type":"Info:#website.Model","infoClosingHours":"06:00:00 PM","infoID":1,"infoOpeningDays":"Monday","infoOpeningHours":"09:00:00 AM","infoStatus":"Open"}]}
I want to get the infoOpeningDays, however, I am unable to do it.
I tried using
dynamicObject.GetType().GetProperty("infoOpeningDays").GetValue(dynamicObject, null);
dynamicObject["infoOpeningDays"];
But it kept giving me null.
Here's my code
private async void GetData(object sender, EventArgs e)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("ip");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try{
HttpResponseMessage response = client.GetAsync("WebServices/information.svc/GetInformationJSON").Result;
if (response.IsSuccessStatusCode)
{
string jsonString = await response.Content.ReadAsStringAsync();
dynamic dynamicObject = JsonConvert.DeserializeObject(jsonString);
//string abc = dynamicObject.IEnumerator.[0].IEnumerator.[0].IEnumerator.[0].IEnumerator.[5].Name;
string abc = dynamicObject.GetType().GetProperty("infoOpeningDays").GetValue(dynamicObject, null);
}
}
catch
{
}
}

You should access the properties directly from your dynamic object like this:
dynamic dynamicObject = JsonConvert.DeserializeObject(json);
string infoClosingHours = dynamicObject.d[0].infoClosingHours;
Or this is the same
string infoClosingHours = dynamicObject.d[0]["infoClosingHours"];

Related

The PostAsync in HttpClient doesn't send data to my webapi

I've created a HttpClient instance to invoke an API with post method.
using (var client = new HttpClient())
{
var person = new Stu();
person.ApplicantId = "48751889-D86E-487B-9508-000EAB65F11F";
var json = JsonConvert.SerializeObject(person);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var url = "http://localhost:52085/api/CollegeService/IsCoolegeStudent";
// var client = new HttpClient();
var response = await client.PostAsync(url, data);
string result = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(result);
}
public class Stu
{
public string ApplicantId { get; set; }
}
When I check my API out , I receive ApplicantId of my object is Null.
I cant not figure out why ApplicantId is Null.
Finally I've changed my [FromForm] to[FromBody] in my API and it worked correctly but it stuck on this line var response = await client.PostAsync(url, data);and doesn't go on.
the await keyboard make my app stuck ,I've changed it this way
var response = await client.PostAsync(url, data).ConfigureAwait(false);
but I didn't figure it out why it cause this problem.
If you using FromForm attribute, you should use FormUrlEncodedContent instead of StringContent as content type when you send POST message. If you still want send json - change FromForm at IsCoolegeStudent method to FromBody.

How do i call an API in c# with a api key

So i´ve recently tried working with an api for the first time and i really don´t know what to do with the this api: https://skinbaron.de/misc/apidoc/ .I have already looked tutorials on how to call an api in c# but i still don´t really get what i have to do in my specific case.
I´ve tried this: How do I make calls to a REST api using C#?
This question might seem stupid to people that know how to work with stuff like this but i have no expierence with api´s so far.
The exact code i´ve tried:
private const string URL = "https://api.skinbaron.de/";
private static string urlParameters = "?api_key=123"; // I have replaced the "123" with my apikey
static void Main(string[] args)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync(urlParameters).Result;
if (response.IsSuccessStatusCode)
{
// do something
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
client.Dispose();
}
You can use Rest sharp. Its really easy to use. This is an third party library used in c# to manage API's. No need to bother with any of the other details used to call API's.
var client = new RestClient("https://api.skinbaron.de/GetBalance");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Accept", "application/json");
request.AddParameter("apikey", "123");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
//Rest of the stuff
It looks like they're expecting you to POST rather than GET, and to pass a JSON object in the body of your POST, with "apikey" as a property on the JSON object.
Normally, in C# you would create a model class that you would then serialize for your post, but if all you have to post is the apikey I would just serialize a Dictionary object with your apikey as the only member of the collection.
For instance, I think this code might do what you want.
private const string URL = "https://api.skinbaron.de/";
private static string urlParameters = "?api_key=123"; // I have replaced the "123" with my apikey
private static string apiKey = "";
static void Main(string[] args)
{
using (var webClient = new WebClient()) {
webClient.Headers.Add(HttpRequestHeader.Accept, "application/json");
webClient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
var postDictionary = new Dictionary<string, string>() {
{"apikey", apiKey}
};
var responseBody = webClient.UploadString(URL, JsonConvert.SerializeObject(postDictionary));
}
}

Custom header in HttpClient POST request not working

I am trying to send a POST request when using HttpClient. When I run the code I am getting an unauthorized response. But I am able to get it to work in PostMan. Below is my current code snippet and pictures of what I am trying to perform. I'd like to add I am trying to send a json string in my body.
using (HttpClient client = new HttpClient())
{
var connectionUrl = "https://api.accusoft.com/prizmdoc/ViewingSession";
var content = new Dictionary<string, string> { { "type", "upload" }, { "displayName", "testdoc" } };
// Serialize our concrete class into a JSON String
var stringPayload = JsonConvert.SerializeObject(content);
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
//client.DefaultRequestHeaders.Add("Acs-Api-Key", "aPsmKCmvkZHf9VakCmfHB8COmzRxXY5FDhj8F1FU1IGmQlOkfjiKESKxfm38lhey");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Acs-Api-Key", "aPsmKCmvkZHf9VakCmfHB8COmzRxXY5FDhj8F1FU1IGmQlOkfjiKESKxfm38lhey");
// Do the actual request and await the response
var httpResponse = httpClient.PostAsync(connectionUrl, httpContent).Result;
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
// Do something with response. Example get content:
var connectionContent = httpResponse.Content.ReadAsStringAsync().Result;
}
else
{
// Handle a bad response
return;
}
}
}
You're using two HttpClients when you only need to use one.
using (HttpClient client = new HttpClient())
and
using (var httpClient = new HttpClient())
The second one (httpClient) is doing the post but the authentication header has been added to client. Just remove the second one (httpClient) and make sure you use client.PostAsync(...) to send the request.
I'd also consider using await, rather than .Result (see why here) when sending the request:
var httpResponse = await client.PostAsync(connectionUrl, httpContent);
In addition to haldo's answer,
In your code, you are adding your Acs-Api-Key header as and Authorization header, meaning it ends up looking like Authorization: Acs-Api-Key (key) rather than Acs-Api-Key: (key) which is what you have in PostMan.
Instead of adding it as an Authorization header, just add it as a regular header.
client.DefaultRequestHeaders.Add("Acs-Api-Key","(key)");
Also something else that may cause issues is that you aren't wrapping your content in the "source" object like you are in PostMan. There are a couple ways of doing this
The first would be to simply wrap it in it's string format:
stringPayload = $"\"source\":{{{stringPayload}}}"
Or you can do it before you serialize by making your own object instead of having a Dictionary
var content = new PayloadObject(new Source("upload", "testdoc"));
var stringPayload = JsonConvert.SerializeObject(content);
// Send the request
class PayloadObject{
Source source {get; set;}
PayloadObject(Source source){
this.source = source;
}
}
class Source{
string type {get; set;}
string displayName {get; set;}
Source(string type, string displayName){
this.type = type;
this.displayName = displayName;
}
}

Why is my HTTP POST Body content received/processed as NULL?

I want to be able to receive the Body content of a POST request inside the POST function definition in the REST API.
I have a client code that converts a C# object into JSON and then wraps it in a HTTP StringContent. This payload is then sent via a HTTP Post request to the URL. However the Post method in API always returns NULL when I try returning the received string.
Client:
public async void Register_Clicked(object sender, EventArgs e) // When user enters the Register button
{
Sjson = JsonConvert.SerializeObject(signup);
var httpContent = new StringContent(Sjson);
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://apiname.azurewebsites.net");
var response = await client.PostAsync("api/values", httpContent);
var responseContent = await response.Content.ReadAsStringAsync();
StatusLabel.Text = responseContent; //To display response in client
}
}
API POST Definition:
[SwaggerOperation("Create")]
[SwaggerResponse(HttpStatusCode.Created)]
public string Post([FromBody]string signup)
{
return signup;
}
I want the clients input back as a response to be displayed in the client (StatusLabel.Text). However all I receive is NULL. Kindly guide me in the right direction.
I have prepared a simple example on how you can retrieve your Result from your Task:
async Task<string> GetResponseString(SigupModel signup)
{
Sjson = JsonConvert.SerializeObject(signup);
var httpContent = new StringContent(Sjson);
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://apiname.azurewebsites.net");
var response = await client.PostAsync("api/values", httpContent);
var responseContent = await response.Content.ReadAsStringAsync();
}
return responseContent;
}
And you can call this as:
Task<string> result = GetResponseString(signup);
var finalResult = result.Result;
StatusLabel.Text = finalResult; //To display response in client
If you are not using async keyword, then you can call get your Result as:
var responseContent = response.Content.ReadAsStringAsync().Result;
EDIT
Basically you would have to POST your signup model to your API Controller. Use SigupModel signup as a parameter if you would like. Then whatever processing you are doing in the API, the final result in a string. Now this string can either be a null, empty or have a value. When you get this value in your client, you would have do the following:
var responseContent = await response.Content.ReadAsStringAsync();
var message = JsonConvert.DeserializeObject<string>(responseContent);
Here you will get your message a string and then you can set it as: StatusLabel.Text = message ;

Is it possible to read results of the XmlSerializer being sent by HTTPClient?

I am using an extension method to post xml using the HTTPClient which works great.
My question: Is it possible to read, log, or display the results of the XmlSerializer data that is being sent/posted ?
public static class HttpExtensions {
public static Task<HttpResponseMessage> PostAsXmlWithSerializerAsync<T>(this HttpClient client, string requestUri, T value)
{
return client.PostAsync(requestUri
, value
, new XmlMediaTypeFormatter { UseXmlSerializer = true }
);
}
}
PostAsync hides the actually sent HttpRequestMessage from you, though you can retrieve it from the response, too so you can trace both the request and response contents:
var response = await client.PostAsync(uri, value, formatter);
Log(response);
If you really want to log the request only, create the request manually:
var request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StreamContent(myXmlStream);
Log(request);
var response = await client.SendAsync(request);
Log(response);
And now you can create one or two Log overloads. I show it for the response, which includes both the request and response log. This is independent from the format, works for both XML and json content.
protected virtual void Log(HttpResponseMessage response)
{
// Use any log/trace engine here, this example uses Debug
Debug.WriteLine($"Response of the API Call [{response.RequestMessage.Method}] {response.RequestMessage.RequestUri}: {response.StatusCode} {FormatResponse(response)}");
}
private static string FormatResponse(HttpResponseMessage response)
{
var result = new StringBuilder();
result.AppendLine();
result.AppendLine("Original request:");
result.AppendLine(FormatHttpMessage(response.RequestMessage.Headers, response.RequestMessage.Content));
result.AppendLine();
result.AppendLine("Obtained response:");
result.AppendLine(FormatHttpMessage(response.Headers, response.Content));
}
private static string FormatHttpMessage(HttpHeaders headers, HttpContent content)
{
var result = new StringBuilder();
var headersString = headers.ToString();
if (!string.IsNullOrWhiteSpace(headersString))
{
result.AppendLine("Headers:");
result.AppendLine(headersString);
result.AppendLine();
}
if (content != null)
{
result.AppendLine("Content:");
result.AppendLine(content.ReadAsStringAsync().Result);
}
return result.ToString();
}
Yes, you can.
Download and install Fiddler , then filter your requestUri , you can monitor all transferring data such you serialized xml.

Categories

Resources