RestSharp XML Deserialization into List - c#

I am trying to deserialize the following xml using RestSharp, but I always get a list of null elements. I am new to REST based services and need some expert help! =)
Solution Found: I figured it out. You have to explicitly tell RestSharp what kind of data is being deserialized:
request.OnBeforeDeserialization = resp => {
resp.ContentType = "application/json";
};
Full XML: http://autocomplete.wunderground.com/aq?query=San%20F&format=xml
Some of the XML is below:
<RESULTS>
<name>San Francisco, California</name>
<type>city</type>
<c>US</c>
<zmw>94101.1.99999</zmw>
<tz>America/Los_Angeles</tz>
<tzs>PDT</tzs>
<l>/q/zmw:94101.1.99999</l>
</RESULTS>
Here is my XMLResults class:
public class XMLResults
{
public List<name> names {get; set;}
}
public class name
{
public string city {get; set;}
}
And here is my getWeather method:
public void getWeather(string query)
{
var client = new RestClient ();
var request = new RestRequest(Method.GET);
client.BaseUrl = "http://autocomplete.wunderground.com";
request.Resource = "aq";
request.AddParameter ("query", query);
request.AddParameter ("format", "xml");
request.RequestFormat = DataFormat.Xml;
var city = client.Execute<XMLResults>(request);
Console.WriteLine (city.Data.names.Count); // Results in 20
}

If it were me I would take a valid XML response ( like the one you posted ) and create a class from it using the xsd.exe program that comes with Visual Studio (it is VS Command Line Tool)
Generate C# class from XML
Then you can easily Serialize and Deserialize your Object.

I had to explicitly tell RestSharp what kind of data is being deserialized: request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json";};

Related

RestSharp - Not able to post json using RestSharp if I am reading my json from a file

I am struggling to get this done and have tried various options but not able to post JSON when I read it from a file and pass it in request.AddJsonBody(jsonBody);
Note* It works, when i try passing it directly like: request.AddJsonBody(new { deviceId = "qa" });
But my requirement is to save request in a file and read it from there and pass it in request.AddJsonBody(jsonBody);
AddBody is deprecated, thus I am using AddJsonBody. Reading content from a file and then converting into JsonObject to pass in AddJsonBody doesn't work as it treats it like we have not passed valid json or treat it like an empty json.
[TestMethod]
public void createWithFile()
{
static readonly string textFile = #"C:\Users\RequestFiles\Users.txt"; // sample contents of my file : {"deviceId" : "qa"}
if (File.Exists(textFile))
{
text = File.ReadAllText(textFile);
}
JObject jsonBody = JObject.Parse(text);
Console.WriteLine(jsonBody);
RestClient client = new RestClient("myurl");
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddJsonBody(jsonBody);
request.AddHeader("Accept", "application/json");
var response = client.Execute(request);
Console.WriteLine(response.Content);
Console.WriteLine(response.StatusCode.ToString());
}
You can send any text as the request body. AddJsonBody specifically designed to serialise the object that is given as a parameter to JSON. If you have the JSON string already, just use the AddParameter with the RequestBody parameter type.
It is clear from the test code:
[Test]
public void Can_Be_Added_To_PUT_Request()
{
const Method httpMethod = Method.PUT;
var client = new RestClient(_server.Url);
var request = new RestRequest(RequestBodyCapturer.Resource, httpMethod);
const string contentType = "text/plain";
const string bodyData = "abc123 foo bar baz BING!";
request.AddParameter(contentType, bodyData, ParameterType.RequestBody);
client.Execute(request);
AssertHasRequestBody(contentType, bodyData);
}
You need to set the correct content type, of course.

How to make GET with request body

How do I make a GET query with request body using RestSharp (I'm using RestSharp v. 106.6.10 with .NET Core 2.2). I can do it using WebClient/Postman etc. no problem.
Here's the code failing with {["A non-empty request body is required."]}.
var client = new RestClient("BaseUri");
var request = new RestRequest("URL", Method.GET);
request.AddJsonBody(Body);
client.Execute(request); // {["A non-empty request body is required."]}
This represents a valid use case, pity if it's not supported.
Update: The motivation for having GET requests with body is to avail of get requests having complex parameters, which can't be nicely encoded into a query string. I know people serialize their jsons an put them into a querystrings but I'd rather put it into a request body, considering it's a permissible usage after all.
From my experience AddJsonBody is completely broken (had a multiple times when it wasn't serialize my model just pasting in Body something like MyProject.Models.MyModel or even left body empty). So I use following:
var client = new RestClient("BaseUri");
var request = new RestRequest("URL", Method.GET);
request.AddHeader("Content-Type", "application/json");
string serializedBody = Newtonsoft.Json.JsonConvert.SerializeObject(Body);
request.AddParameter("application/json; charset=utf-8", serializedBody, ParameterType.RequestBody);
client.Execute(request);
UPDATE sorry i wasn't patient when reading you question. Answer is provided for RestSharp not PostSharp
I solved it by using reflection, to trick WebRequest that it is legal to send a body with a GET request.
1.Create Model for body parameters,
public class SampleBodyModel
{
public String name{ get; set; }
public String password{ get; set; }
}
Initialize the request.
SampleBodyModel sampleRequest = new SampleBodyModel
{
name= "name",
password= "password"
};
//initialize the API call
var request = WebRequest.Create("API_END_POINT");
request.ContentType = "application/json";
request.Method = "GET";
var myHttpWebRequest = (HttpWebRequest)request;
// ------- Add these two lines if your using JWT token -------
myHttpWebRequest.PreAuthenticate = true;
myHttpWebRequest.Headers.Add("Authorization", "Bearer " + "TOKEN");
// -----------------------------------------------------------
var type = myHttpWebRequest.GetType();
var currentMethod = type.GetProperty("CurrentMethod",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(myHttpWebRequest);
var methodType = currentMethod.GetType();
methodType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic |
BindingFlags.Instance).SetValue(currentMethod, false);
//Add the Request body
using (var streamWriter = new
StreamWriter(myHttpWebRequest.GetRequestStream()))
{
streamWriter.Write(Newtonsoft.Json.JsonConvert.SerializeObject(sampleRequest));
}
var response = (HttpWebResponse)myHttpWebRequest.GetResponse();
var responseStream = response.GetResponseStream();
var myStreamReader = new StreamReader(responseStream, Encoding.Default);
var json = myStreamReader.ReadToEnd();
responseStream.Close();
response.Close();

How to get list of item from restsharp api response

I am calling a api and getting list of ids in json format in restsharp api response. But problem i am unable to write the syntax for List in restsharp Execute method. Please check the code bellow. And correct my List<> Syntax.
var client2 = new RestClient(apiEndPoint);
var request2 = new RestRequest(Method.GET);
var Result2 = client.Execute<List><PageIds>(request);
My id model:
class PageIds
{
public int Id { get; set; }
}
Hay i think this is your answer-
var Result2 = client.Execute<List<PageIds>>(request);
However until we see your json response cant sure this will work or not. But at-least it is the correct syntax for List on this particular situation.

Parse JSON response where the object starts with a number in c#

I'm trying to deserialise a response from a REST service into C# Strongly typed classes - however I've ran into the same issue has in this post:
How do I output this JSON value where the key starts with a number?
However I have the issue that you cannot start a variable name in c# with a number - meaning that the class at that level just deserialises into null.
I need to know how to get into the objects and deserialise them into the c# classes.
My Current code is below:
public static async Task<T> MakeAPIGetRequest<T>(string uri)
{
Uri requestURI = new Uri(uri);
using (HttpClient client = new HttpClient())
{
HttpResponseMessage responseGet = await client.GetAsync(requestURI);
if (responseGet.StatusCode != HttpStatusCode.OK)
{
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
responseGet.StatusCode,
responseGet.Content));
}
else
{
string response = await responseGet.Content.ReadAsStringAsync();
T objects = (JsonConvert.DeserializeObject<T>(response));
return objects;
}
}
}
EDIT: I cannot change the way the service is pushing the data back
The correct way to deal with this was to use the JsonProperty tag on the target classes to define what Json property to listen for, as shown below (referenced from https://stackoverflow.com/questions/24218536/deserialize-json-that-has-some-property-name-starting-with-a-number
public class MyClass
{
[JsonProperty(PropertyName = "24hhigh")]
public string Highest { get; set; }
...
Thanks to #HebeleHododo for the comment answer
While there is no direct way to construct a strongly typed C# object in this case, You could still have the capabilities to parse the json string manually and extract values -
var json = "{'1':{'name':'test','age':'test'}}";
var t = JObject.Parse(json)["1"];
Console.WriteLine(t["name"]); //test
Console.WriteLine(t["age"]); //test

POST Web Service Client using C#

Can you please give me a sample example of how to make the JSON request body in C#. I am using Visual Studio 2015. I know SOAP UI, but I am new to C#.
Thanks in advance.
You can try the following
Lets assume you have the following webmethod
public void Webmethod(string parameter)
{
//Do what ever
}
In C# you will do the following to call the webmethod, You require Json.net, Newtonsoft or other Json serializer
var webRequest = WebRequest.Create("http:\\www.somesite.com/path/to/webservice/webservice.asmx/Webmethod");
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
Build a Json object representing the parameters
var jsonobjectrepresentingparameters = new {parameter = "Value"};
Get the Json string using Newtonsoft JsonConvert
var datastring = Newtonsoft.Json.JsonConvert.SerializeObject(jsonobjectrepresentingparameters);
Get the bytes
var bytes = Encoding.ASCII.GetBytes(datastring);
Write the bytes to the request
var requestStream = webRequest.GetRequestStream();
requestStream.Write(bytes, 0,bytes.Length);
Get repsonse
var response = webRequest.GetResponse();
If your Webmethod returned anything like a string, int or other data you can use the following class to deserialize
public class Type<T>
{
public T D { get; set; }
public Type()
{
}
}
You will notice when you work with webservices it returns a json object with property d as the value which is why you require the above class in C#
Then you will require the following extra two lines if your return type was string
var json = (new StreamReader(response.GetResponseStream())).ReadToEnd();
var object = JsonConvert.DeserializeObject<Type<string>>(json);

Categories

Resources