How to post FormCollection object to HTTP Client - c#

I have used HTTP Client for calling RESTFul services. Now i have requirement where i have to pass the FormCollection object to the API. The API is not a REST API. More information about API, you can see in this link. http://docs.pay4later.com/docs/requests
I thought of using HTTPCLINET to impliment this. with the below code, i was able to get the response.
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://testurl/");
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("Identification[api_key]", "somekey"),
new KeyValuePair<string, string>("Identification[InstallationID]", "installationid"),
new KeyValuePair<string, string>("action", "credit_application_link"),
new KeyValuePair<string, string>("Goods[Description]", "test"),
new KeyValuePair<string, string>("Identification[RetailerUniqueRef]", Guid.NewGuid().ToString()),
new KeyValuePair<string, string>("Goods[Price]", "100000"),
new KeyValuePair<string, string>("Finance[Code]", "PQERTS"),
new KeyValuePair<string, string>("Finance[Deposit]", "92000")
});
var result = client.PostAsync("", content).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
}
The above one works perfectly. However, i wanted to build a model and wanted to send that model using HttpClient. But that was not successful, since the request was going as json object. The model looks like below,
public class CreditApplicationInitializationRequest
{
public string action { get; set; }
public Identification Identification { get; set; }
public Goods Goods { get; set; }
public Finance Finance { get; set; }
}
public class Identification
{
public string api_key { get; set; }
public string RetailerUniqueRef { get; set; }
public string InstallationID { get; set; }
}
I wanted to know, whether this appoach is possible or is there any other standard approach using httpclient to do so.
Thanks for your help.

Looks like you're on the right track; checkout Newtonsoft.Json - it's a NuGet package that provides ways to work with Json. In particular, you can annotate your properties with attributes to control the way the package serialises and de-serialises your objects into Json objects.
An example looks like:
[JsonObject(MemberSerialization.OptIn)]
public class Person
{
// "John Smith"
[JsonProperty]
public string Name { get; set; }
// "2000-12-15T22:11:03"
[JsonProperty]
public DateTime BirthDate { get; set; }
// new Date(976918263055)
[JsonProperty]
[JsonConverter(typeof(JavaScriptDateTimeConverter))]
public DateTime LastModified { get; set; }
// not serialized because mode is opt-in
public string Department { get; set; }
}
You can find more info at http://www.newtonsoft.com/json/help/html/SerializationAttributes.htm.

HttpClient is only concerned with sending/receiving raw content; serializing is left to other libraries. I was going to suggest Flurl, which allows you to form-post an object with its PostUrlEncodedAsync method, but it assumes the object properties are simple types (it just does a ToString with the values). The serialization rules you're working with look fairly custom, so I think you're stuck rolling your own thing.

Related

Unable to deserialize list in a XML Response using ReadAsAsync<T>

[Update: This question is different from the suggested duplicate because this one is about deserialization of XML and the explanation of the problem and solution on this one is clearer as I've included the full source code.]
I'm trying to read and subsequently manipulate a response from a Web API. Its response looks like this:
<MYAPI xsi:noNamespaceSchemaLocation="MYAPI.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MySite Resource="some resource name">
<Name>some name</Name>
<URL>some url</URL>
<SecondName>Describes something</SecondName>
</MySite>
... A lot of these <MySite>...</MySite> are there
<SomeOtherSite Resource="some resource name">
<Name>some name</Name>
<URL>some url</URL>
</SomeOtherSite>
</MYAPI>
SomeOtherSite is not repeating and only one of it appears at the end of the response. But the MySite is the one that is repeating.
I've modeled the class for this XML response as:
public class MYAPI
{
public List<MySite> MySite { get; set; }
public SomeOtherSite SomeOtherSite { get; set; }
}
public class MySite
{
public string Name { get; set; }
public string URL { get; set; }
public string SecondName { get; set; }
}
public class SomeOtherSite
{
public string Name { get; set; }
public string URL { get; set; }
}
And this is my code:
static void Main()
{
var handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential("MyUsername", "MyPassword");
var client = new HttpClient(handler);
client.BaseAddress = new Uri("https://sitename.com:PortNumber/");
var formatters = new List<MediaTypeFormatter>()
{
new XmlMediaTypeFormatter(){ UseXmlSerializer = true }
};
var myApi = new MYAPI();
HttpResponseMessage response = client.GetAsync("/api/mysites").Result;
if (response.IsSuccessStatusCode)
{
myApi = response.Content.ReadAsAsync<MYAPI>(formatters).Result;
}
}
Now the myApi only has object for SomeOtherSite but the list for the MySite is empty.
Would someone please tell me how I should deserialize this response correctly?
Should I be creating custom media formatter? I have no idea of it by the way.
Also would you please tell me how to model that Resource attribute coming in the response?
And I can't change anything in the WebAPI server. I just need to consume the data from it and use it elsewhere.
Thank You so much!
I solved this after some really good direction from: https://stackoverflow.com/users/1124565/amura-cxg Much Thanks!
The solution was to annotate all the properties with XMLAttributes. And it correctly deserialized the response. And as for the Resource attribute, all I needed was [XmlAttribute(AttributeName="Resource")]
The rest of the source code works as is.
[XmlRoot(ElementName="MYAPI")]
public class MYAPI
{
[XmlElement(ElementName="MySite")]
public List<MySite> MySite { get; set; }
[XmlElement(ElementName="SomeOtherSite")]
public SomeOtherSite SomeOtherSite { get; set; }
}
public class MySite
{
[XmlElement(ElementName="Name")]
public string Name { get; set; }
[XmlElement(ElementName="URL")]
public string URL { get; set; }
[XmlElement(ElementName="SecondName")]
public string SecondName { get; set; }
[XmlAttribute(AttributeName="Resource")]
public string Resource { get; set; }
}
Plus, I didn't need any custom media formatter. And from one of the posts by https://stackoverflow.com/users/1855967/elisabeth , I learned that we should not touch the generated file from xsd.exe tool. So I explicitly set to use the XmlSerializer instead of the DataContractSerializer used by default:
var formatters = new List<MediaTypeFormatter>()
{
new XmlMediaTypeFormatter(){ UseXmlSerializer = true }
};

Unable to use JSON data with Newtonsoft.Json in WPF

I am retrieving data from office365 api. The response is in JSON format. I want to get data like Id, DisplayName etc. into variables but not getting the right way to do it. Following this link. I'm new to API and JSON. Will Appreciate pointers as well towards best learning links.Sample JSON below for listing sub folders of Inbox folder.
Response JSON data.
{"#odata.context":"https://outlook.office365.com/api/v1.0/$metadata#Me/Folders('Inbox')/ChildFolders","value":
[
{"#odata.id":"https://outlook.office365.com/api/v1.0/Users('sample.user#demosite.com')/Folders('AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1iMjllLTJmsdfsdfdDSFSDFDFDF=')",
"Id":"AAMkADBjMdfgdfgDFGDFGDFGdfGDFGDFGDFGGDzrACAAB4xqMmAAA=",
"DisplayName":"SampleFolder","ParentFolderId":"AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1sdsDFSDFSDFSDFSDFSDFDFDFrACAAAAAAEMAAA=","ChildFolderCount":0,"UnreadItemCount":8,"TotalItemCount":94},
{"#odata.id":"https://outlook.office365.com/api/v1.0/Users('sample.user#demosite.com')/Folders('AAMkADBjMGZiZGFlLTE4ZmEasdasdasdASDASDASDASDSADDASDASDAB4xqMnAAA=')",
"Id":"AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1iMjllLTJmOGZkNGRhZmIzNQAuAasdASDASDASDASEDASDASDxSEHjzrACAAB4xqMnAAA=",
"DisplayName":"AnotherSampleFolder","ParentFolderId":"AAMkADBjMGZiZGFlLTE4ZmEtNGRlOS1sdsDFSDFSDFSDFSDFSDFDFDFrACAAAAAAEMAAA=","ChildFolderCount":0,"UnreadItemCount":21,"TotalItemCount":75}
]
}
The C# code using to parse JSON and find the required data.
HttpResponseMessage response = httpClient.SendAsync(request).Result;
if (!response.IsSuccessStatusCode)
throw new WebException(response.StatusCode.ToString() + ": " + response.ReasonPhrase);
string content = response.Content.ReadAsStringAsync().Result;
JObject jResult = JObject.Parse(content);
if (jResult["odata.error"] != null)
throw new Exception((string)jResult["odata.error"]["message"]["value"]);
//Attempt one - using dynamic [NOT WORKING - getting NULL values in the variables]
dynamic results = JsonConvert.DeserializeObject<dynamic>(content);
var folderName = results.Id;
var folderId = results.Name;
//Attempt two - [Not working - Throwing exception -
//Object reference not set to an instance of an object.]
var folderID = (string)jResult["odata.context"]["odata.id"][0]["Id"];
First create a class for your json object
public class RootObject
{
[JsonProperty(PropertyName = "#odata.context")]
public string context { get; set; }
public List<Value> value { get; set; }
}
public class Value
{
[JsonProperty(PropertyName = "#odata.id")]
public string dataId { get; set; }
public string Id { get; set; }
public string DisplayName { get; set; }
public string ParentFolderId { get; set; }
public int ChildFolderCount { get; set; }
public int UnreadItemCount { get; set; }
public int TotalItemCount { get; set; }
}
Then Json Convert the Json string to your RootObject if your are using Newtonsoft Json then Deserilaze by using
RootObject shortiee = JsonConvert.DeserializeObject<RootObject>("Your Json String");
private List<string> GetDisplayNames(JObject content)
{
var obj = Json.Parse(content);
var values = obj["value"].ToList();
var displayNames = new List<string>();
foreach (var value in values)
{
displayNames .Add(system["DisplayName"].ToString());
}
return displayNames;
}
This would return the names, for example, and you could do this for each value you need to retrieve. However, this does not require you to serialize/deserialize the json object before using it. It works, but is most likely not best practice.
if (jResult["odata.error"] != null)
throw new Exception((string)jResult["odata.error"]["message"]["value"]);
//Attempt one - using dynamic [NOT WORKING - getting NULL values in the variables]
dynamic results = JsonConvert.DeserializeObject<dynamic>(content);
Side note: There is no key called "odata.error" in your JSON data. So you're effectively calling something which will return null.
One of the ways to deserialise JSON is to create model classes for the objects you want to process and deserialise into them directly, eg. JsonConvert.DeserializeObject<Folder>(content). As you are talking to an Office365 API, you find documentation and examples here on how they are defined.
Taken your folder response as an example, your model for a single Folder could look like this:
public class Folder
{
[JsonProperty(PropertyName = "#odata.id")]
public string OdataId { get; set; }
public string Id { get; set; }
public string DisplayName { get; set; }
public string ParentFolderId { get; set; }
public int ChildFolderCount { get; set; }
public int UnreadItemCount { get; set; }
public int TotalItemCount { get; set; }
}
Note1: in your example, you get a response with list of folders, so have to adjust this accordingly.
Note2: you can use JsonProperty to define a mapping between a JSON property/key and a C# property as shwon for #odata.id.
However, you can also use the Outlook Client Library which would make it mostly unnecessary to deal with JSON data directly (which seems preferable, unless you have a very specific reason to deal with JSON directly).

Deserializing rest client response from wordpress.org

I have a wordpress.org locally hosted on my pc.
I've installed a wordpress plugin called json-api which let you retrieve posts from your wordpress site.
I'm running the following code:
var client = new RestClient(BlogArticlesUrl);
var request = new RestRequest();
request.Timeout = 5000;
request.RequestFormat = DataFormat.Json;
request.Method = Method.GET;
request.AddParameter("json", "get_tag_posts");
request.AddParameter("slug", "featured");
request.AddParameter("count", "3");
var articles = client.Execute<List<BlogArticleModel>>(request);
After executing the code, in the variable articles I have the following:
Inside the Content there are few keys but I would only like to convert 'posts' to a model in c#
How do I acheive that?
EDIT:
I have found a solution using newtonsoft for dot net
Newtonsoft.Json.JsonConvert.DeserializeObject<BlogArticleResponse>(articles.Content);
In RestSharp, the Content is what gets deserialized. So, the type you pass into the .Execute<T> method must be the same structure as the response.
In your case, it will look something like this:
public class BlogArticleResponse
{
public string status { get; set; }
public int count { get; set; }
public int pages { get; set; }
public BlogTag tag { get; set; }
...
}
public class BlogTag
{
public int id { get; set; }
public string slug { get; set; }
public string title { get; set; }
public string description { get; set; }
...
}
You can then execute the request like this:
var result = client.Execute<BlogArticleResponse>(request);
For more information, have a look at the documentation.

C# convert string to dictionary

I get this response string from the Bitly api:
{ "status_code": 200,
"status_txt": "OK",
"data":
{ "long_url": "http:\/\/amazon.de\/",
"url": "http:\/\/amzn.to\/1mP2o58",
"hash": "1mP2o58",
"global_hash": "OjQAE",
"new_hash": 0
}
}
How do I convert this string to a dictionary and how do I access the value for the key "url" (without all the \)
This isn't just some ordinary string. This is a data structure in JSON format, a common and well-established format, originally used in Javascript but now rather common as a data transfer mechanism between services and clients.
Rather than reinventing the wheel and parsing the JSON yourself, I suggest you use an existing JSON library for C#, such as JSON.NET, which will eat up that string and parse it into .NET objects for you.
Here's a code sample, taken from JSON.NET's documentation, showing its usage:
string json = #"{
'href': '/account/login.aspx',
'target': '_blank'
}";
Dictionary<string, string> htmlAttributes =
JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
Console.WriteLine(htmlAttributes["href"]);
// /account/login.aspx
Console.WriteLine(htmlAttributes["target"]);
// _blank
If you add a package like Newtonsoft's Json to your project, you can deserialize the Json in to an anonymous type. You can then fetch the url from that. This is available via NuGet within Visual Studio and provides support for async or sync serialization/deserialization.
public string GetUrl(string bitlyResponse)
{
var responseObject = new
{
data = new { url = string.Empty },
};
responseObject = JsonConvert.DeserializeAnonymousType(bitlyResponse, responseObject);
return responseObject.data.url;
}
I'd use JSON.NET.
http://james.newtonking.com/json
MIT License which means if you're doing anything commercial you are good.
I don't think you would want to go straight to a Dictionary, because there is some stuff there that isn't a one to one relationship. So you could make a class like the following.
public class BitlyData
{
public string LongUrl{ get; set; }
public string Url { get; set; }
public string Hash { get; set; }
public string GlobalHash { get; set; }
public string NewHash { get; set; }
}
You could then use Json.NET to turn that String into an JObject. So we'll call your string bitlyString.
JObject bitlyObject = JObject.Parse(bitlyString);
Now we have that all that is left to do is access the data.
BitlyData theData = JsonConvert.DeserializeObject<BitlyData>(bitlyObject["data"]);
Then you can access the url (and any other pieces) using the getters.
Of course you could make it even better by having class that handles the other bits as well so you just do one serialisation.
1)Add these classes to your project
public class Rootobject
{
public int status_code { get; set; }
public string status_txt { get; set; }
public Data data { get; set; }
}
public class Data
{
public string long_url { get; set; }
public string url { get; set; }
public string hash { get; set; }
public string global_hash { get; set; }
public int new_hash { get; set; }
}
2)Add a reference to JSON.NET
3)
string jsonString= "YOUR JSON STRING";
Rootobject weps = JsonConvert.DeserializeObject<Rootobject>(jsonString);
Console.WriteLine(weps.status_code);
if (weps.data != null)
{
Console.WriteLine(weps.data.url);
Console.WriteLine(weps.data.global_hash);
//...
}

How to map JSON to C# Objects

I am having issues with understanding how to make this happen.
Basically we have an API, the user sends a JSON of the format:
{
"Profile":[
{
"Name":"Joe",
"Last":"Doe",
"Client":{
"ClientId":"1",
"Product":"Apple",
"Message":"Peter likes apples"
},
"Date":"2012-02-14"
}
]
}
I have a class called Profile with parameters Name, Last, and an object as one of its members called Client as well as property Date.
Something like this:
public class Profile {
public string Name {get; set;}
public string Last {get; set;}
public Client client {get; set;}
public DateTime dDate {get; set;}
}
So basically, I am not sure how to grab the JSON and then map it to my object.
Any help with "helping" me understand would be much appreciated.
You can use Json.NET to deserialize your json string as (with some modifications to your classes)
var yourObject = JsonConvert.DeserializeObject<Root>(jsonstring);
public class Root
{
public Profile[] Profile;
}
public class Profile
{
public string Name { get; set; }
public string Last { get; set; }
public Client Client { get; set; }
public DateTime Date { get; set; }
}
public class Client
{
public int ClientId;
public string Product;
public string Message;
}
You can use a JSON library for this, for example Newtonsoft.Json which is free. It will map json to your types automatically.
Sample:
public static T Deserialize<T>(string json)
{
Newtonsoft.Json.JsonSerializer s = new JsonSerializer();
return s.Deserialize<T>(new JsonTextReader(new StringReader(json)));
}
There is also a NuGet package available.
Easiest way I know is to use JSON.Net by newtonsoft.
To make it easier to understand, I always make matching classes in C# with the same name.
Then its easier to deserialize it.
As an example, if it is an array of objects in js, it will map to a list of object with the same names in C#.
As for the date time, its a bit tricky.
Id do the client side validation and Datetime.tryParse in the serverside, itll take care of the dashes or slashes.
var serializer = new JavaScriptSerializer();
List<abc> abcList = serializer.Deserialize<List<abc>>(PassedInJsonString);
I know this is a long time question, but I would like to add one more option, which does not use third party libraries, and only uses stock .Net libraries, and is available from .Net Core 3.1 onwards.
First of all, I leave a link to the official Microsoft documentation (where you will find examples on how to serialize and deserialize json strings): https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to
Let's build on your example. We have our starting json string:
{
"Profile":[
{
"Name":"Joe",
"Last":"Doe",
"Client":{
"ClientId":"1",
"Product":"Apple",
"Message":"Peter likes apples"
},
"Date":"2012-02-14"
}
]
}
If we build a data structure that can hold that definition, it would be something like:
public class Root
{
public List<Profile> Profile { get; set; }
}
public class Profile
{
public string Name { get; set; }
public string Last { get; set; }
public Client Client { get; set; }
public string Date { get; set; }
}
public class Client
{
public string ClientId { get; set; }
public string Product { get; set; }
public string Message { get; set; }
}
Now, and finally the answer to how to deserialize a json string into a particular object without third party libraries:
Root root = JsonSerializer.Deserialize<Root>(json);
Where json is the variable that contains your json string.
I add another link of interest, the official documentation of the Deserialize(...) method: https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserialize
Something that is really useful is the exception that can be thrown, JsonException: https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonexception
DataContractJsonSerializer does the job, but it uses more sophisticated format for DateTime serialization.

Categories

Resources