Deserializing a local xml file using Rest Sharp - c#

I have no problem deserializing an xml into my class while using the following code. I was wondering if it was possible to use the same code on a local file, as our source files are saved locally for archival purposes and are occasionally reprocessed.
This works for remote xml but not for local xml:
RestRequest request = new RestRequest();
var client = new RestClient();
//doesnt work
client.BaseUrl = directory;
request.Resource = file;
//works
client.BaseUrl = baseURL;
request.Resource = url2;
IRestResponse<T> response = client.Execute<T>(request);
return response.Data;
Is there a way to use RestSharp from a local file? I was going to try to use the same function regardless of whether the xml is local or remote and just pass it the location of the xml to read.

This is in fact possible using built in JsonDeserializer class as below. I have used this method to stub API response for testing.
// Read the file
string fileContents = string.Empty;
using (System.IO.StreamReader reader = new System.IO.StreamReader(#"C:\Path_to_File.txt"))
{
fileContents = rd.ReadToEnd();
}
// Deserialize
RestResponse<T> restResponse = new RestResponse<T>();
restResponse.Content = fileContents;
RestSharp.Deserializers.JsonDeserializer deserializer = new RestSharp.Deserializers.JsonDeserializer();
T deserializedObject = deserializer.Deserialize<T>(restResponse);

This is not possible with standard functionality. For example "file://" URLs do not work with RestSharp.
I would recommend using RestSharp do get the returned data from a Uri and having another function to deserialize this data into an object.
You can use the same funcion then to deserialize from file data.
RestSharp is a library to do REST calls, not to deserialize from arbitrary sources. Even if there is a possibility to make RestSharp believe it is talking to a website instead of a file, it would be a hack.
If you need it you could still use the XmlDeserializer from RestSharp. It expects a IRestResponse object, but it only uses the Content property from it, so it should be easy to create. It still feels like a hack though and there are more than enough other XmlSerializers out there that will do a great job

Related

Deserializing JSON from RestSharp response

I am receiving a JSON result from this API web page (https://flagrantflop.com/api/endpoint.php?api_key=13b6ca7fa0e3cd29255e044b167b01d7&scope=team_stats&season=2019-2020&season_type=regular&team_name=Atlanta%20Hawks)
Using the RestSharp library, so far I've got this:
var client = new RestClient("https://flagrantflop.com/api/endpoint.php?api_key=13b6ca7fa0e3cd29255e044b167b01d7&scope=team_stats&season=2019-2020&season_type=regular&team_name=");
var request = new RestRequest("Atlanta Hawks", DataFormat.Json);
var response = client.Get(request);
I have tested the URL and the request part that specifies the team and both work.
I know there are a number of methods of deserializing the JSON, however not sure the best way.
The request isn't working because the argument you're supplying in RestRequest is treated as its own page stemming off the base URI.
You can verify that by calling client.BuildUri(request) with your current setup―you'll see that the resolved URL is https://flagrantflop.com/api/Atlanta Hawks, which is why you weren't getting the proper JSON response. I recommend rewriting the request like this, but there are other valid ways:
var client = new RestClient("https://flagrantflop.com/api/")
.AddDefaultQueryParameter("api_key", "13b6ca7fa0e3cd29255e044b167b01d7")
.AddDefaultQueryParameter("scope", "team_stats")
.AddDefaultQueryParameter("season", "2019-2020")
.AddDefaultQueryParameter("season_type", "regular");
var request = new RestRequest("endpoint.php")
.AddQueryParameter("team_name", "Atlanta Hawks");
After that, you can have RestSharp automatically deserialize your response:
RootObject response = client.Get<RootObject>(request);
By default, this uses SimpleJson to deserialize your object.

How to upload a file to database using the endpoint provided in webAPI C#?

I have an end point("uploadmyfile") to which I need to upload a file to the database using the webapi service. I am not sure how to upload a file.
I did uploading an object using PostAsync as below.
var settings = new JsonSerializerSettings {ContractResolver = new CamelCasePropertyNamesContractResolver()};
var data = JsonCOnvert.SerializeObject(objectData, settings);
HttpContent httpContent = new StringContent(data, Encoding.UTF8, "application/json");
HttpResponseMessage tResp = await Hclient.PostAsync("uploadmyfile", httpContent);
If I am aware of what content is in the file, I can create a class of same structure and can serialize the content to that particular type. As I don't know what content resides in the file, I cannot create an object of that content type and serialize it.
I am very new to the webapi stuff. Kindly excuse me if pointed out anything wrong.
It would be great if anyone can help me out to resolve this issue.
Create a binary column in the database, or use byte[] in Entity Framework, and just save the file as byte[]. So you don't have to know anything about the file.

Pass complex object via http

I’ve got 2 projects that run on different servers but both have a reference to a common dll that contains a complex type called LeadVM. LeadVM contains sub-objects, like Employer which contains properties. Ex:
LeadVM.FirstName
LeadVM.LastName
LeadVM.Employer.Name
LeadVM.Employer.Phone
So, project 1 can create a LeadVM type of object, and populate it. I need to then, via an HTTP call, POST in the data to a controller/action in the 2nd project. The 2nd project knows what a LeadVM object is.
How can I...serialize(?) LeadVM and pass it to the accepting Action in the 2nd project?
EDIT: Thanks to #Unicorno Marley, I ended up using the Newtonsoft JSON stuff.
Now I just create my object in project 1, then do the following code (I'm sure it's clunky but it works).
LeadVM NewCustomer = new LeadVM();
NewCustomer.set stuff here....
var js = Newtonsoft.Json.JsonSerializer.Create();
var tx = new StringWriter();
js.Serialize(tx, NewCustomer);
string leadJSON = tx.ToString();
And then I can use HttpWebRequest to send a web request to my project 2.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:1234/Lead/Create");
request.Method = "POST";
StreamWriter streamOut = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
streamOut.Write(System.Web.HttpUtility.UrlEncode(leadJSON));
streamOut.Close();
HttpWebResponse resp = null;
resp = (HttpWebResponse)request.GetResponse();
StreamReader responseReader = new StreamReader(resp.GetResponseStream(), Encoding.UTF8);
sResponse = responseReader.ReadToEnd();
resp.Close();
In project 2, I can catch the json sent like this and my NewCustomer object in project 2 is already populated, ready for use.
var buffer = new byte[Request.InputStream.Length];
Request.InputStream.Read(buffer, 0, buffer.Length);
string json = System.Text.Encoding.Default.GetString(buffer);
json = System.Web.HttpUtility.UrlDecode(json);
LeadVM NewCustomer = Newtonsoft.Json.JsonConvert.DeserializeObject<PhoenixLead.LeadVM>(json);
I'm sure I'm doing things very awkwardly. I'll clean it up, but wanted to post the answer that I was led to.
Json is probably the most common option, there is a good json library for c# that can be found here:
http://james.newtonking.com/json
Alternatively, since youre just doing an HTTP post and you only have one object, the fastest option would just be to write out the data line by line and have the recipient machine parse it. Since they both know what a LeadVM is, and both presumably have the same definition, it would be trivial to read a text string into the proper variables. This quickly becomes the slower option if you decide to add more object types to this process though.

RestSharp PUT XML, RestSharp is sending it as GET?

I am attempting to edit a product using the prestashop API, using RestSharp in C#, using XML. The documentation's instructions are as follows:
To edit an existing resource: GET the full XML file for the resource you want to change (/api/customers/7), edit its content as needed, then PUT the whole XML file back to the same URL again.
I am attempting to edit /customers/1.
My GET calls are working fine to retrieve the data. I am now deserializing the data, editing it as needed, and re-saving to an XML file. All seems to be going well. The only fields I am attempting to change right now are firstname and lastname. The rest of the data is untouched. Here is a copy of the XML I am using:
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<customer>
<id><![CDATA[1]]></id>
<id_default_group xlink:href="http://heatherfazelinia.com/api/groups/3"><![CDATA[3]]></id_default_group>
<id_lang xlink:href="http://heatherfazelinia.com/api/languages/1"><![CDATA[1]]></id_lang>
<newsletter_date_add><![CDATA[2013-12-13 08:19:15]]></newsletter_date_add>
<ip_registration_newsletter></ip_registration_newsletter>
<last_passwd_gen><![CDATA[2014-06-20 16:56:30]]></last_passwd_gen>
<secure_key><![CDATA[6a9b9eab95448d74a026b869d8cd723e]]></secure_key>
<deleted><![CDATA[0]]></deleted>
<passwd><![CDATA[6028853eb1033578f7432015042fa486]]></passwd>
<lastname>newLastName</lastname>
<firstname>newFirstName</firstname>
<email><![CDATA[pub#prestashop.com]]></email>
<id_gender><![CDATA[1]]></id_gender>
<birthday><![CDATA[1970-01-15]]></birthday>
<newsletter><![CDATA[1]]></newsletter>
<optin><![CDATA[1]]></optin>
<website></website>
<company></company>
<siret></siret>
<ape></ape>
<outstanding_allow_amount><![CDATA[0.000000]]></outstanding_allow_amount>
<show_public_prices><![CDATA[0]]></show_public_prices>
<id_risk><![CDATA[0]]></id_risk>
<max_payment_days><![CDATA[0]]></max_payment_days>
<active><![CDATA[1]]></active>
<note></note>
<is_guest><![CDATA[0]]></is_guest>
<id_shop><![CDATA[1]]></id_shop>
<id_shop_group><![CDATA[1]]></id_shop_group>
<date_add><![CDATA[2014-08-01 13:20:37]]></date_add>
<date_upd><![CDATA[2014-08-01 13:20:37]]></date_upd>
<associations>
<groups node_type="groups">
<groups xlink:href="http://heatherfazelinia.com/api/groups/3">
<id><![CDATA[3]]></id>
</groups>
</groups>
</associations>
</customer>
</prestashop>
That file is saved as EditedXML.xml. Again, according to the documentation (that I pasted above), to edit a resource I am supposed to use PUT to put the XML back to the same URL (which is /customers/1). So I am using the following code right before creating this topic to try to do just that:
// PUT call
var putRequest = new RestRequest("/customers/1", Method.PUT);
var body = System.IO.File.ReadAllText("EditedXML.xml");
request.AddBody(body);
IRestResponse putResponse = client.Execute(putRequest);
Console.WriteLine("Response: " + putResponse.Content);
Now comes my problem. I am getting the error (originally in HTML form, I opened it as HTML to post it more readable:)
Method Not Implemented
GET to /api/customers/1 not supported.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
That error I find VERY confusing for 2 reasons:
1) It seems that even though my request is Method.PUT, it is being read as GET?
2) What it is claiming isn't even true? I have to call a GET function on that same resource to get the initial data?
Just incase anyone would like to see the GET call, here it is:
request = new RestRequest(Method.GET);
request.Resource = "/customers/1";
IRestResponse<customer> newResponse = client.Execute<customer>(request);
Anyone have any idea what is going on? I'm not sure how to debug this, I'm not sure if the PUT call is working at all, or if the arguments with my PUT call are wrong, or what...
We had a similar problem, we had to use the following code to set the body correctly.
request.AddParameter("application/x-www-form-urlencoded", rawXml, ParameterType.RequestBody);
"request.AddBody(body);" seems not to be working.
Please check this example on how i'm updating customer.
// GET customer with id 1
var client = new RestClient(PrestaShopBaseUrl);
client.Authenticator = new HttpBasicAuthenticator(PrestaShopAccount, "");
RestRequest request = new RestRequest("/customers/1", Method.GET);
IRestResponse response = client.Execute(request);
XmlDocument doc = new XmlDocument();
doc.LoadXml(response.Content);
doc.Save(#"Customer.xml");
// do something with customer file
// init XMLDocument and load customer in it
doc = new XmlDocument();
doc.Load(#"Customer.xml");
// Update (PUT) customer
request = new RestRequest("/customers/1", Method.PUT);
request.Parameters.Clear();
request.AddParameter("text/xml;charset=utf-8", doc.InnerXml, ParameterType.RequestBody);
response = client.Execute(request);

Webservice in GAE, call from a C# client

I have created a webapplication on Google App Engine that gets and sets data in datastore, using Python API and it's working fine.
Now I want to access to that data from a client application, written in C# so I was thinking of creating a webservice in GAE to provide access to the data to my app.
I have started to play a bit with ProtoRPC, and built a "hello" webservice as in the tutorial and now I want to call that webservice from my C# client application.
I have found Jayrock lib which seems to do the job; unfortunately I can't find how to make it work.
Here is my code, based on JayrockRPCClient sample :
JsonRpcClient client = new JsonRpcClient();
client.Url = "http://localhost:8081/hello";
JsonObject p = new JsonObject { { "my_name", "Joe" } };
Console.WriteLine(client.Invoke("hello.hello", p));
I always get Missing value error.
Can anybody point me to what do I do wrong ?
And as another question, what do you think of that architecture, as there a simplier way to build a webservice in GAE and call it from C#?
Note that while ProtoRPC communicates via JSON, it is not a JSON-RPC service. By using a JSON-RPC client, you are most likely sending messages in the wrong format.
You should be doing a POST to http://localhost:8081/hello.hello with a request body of {"my_name": "Joe"}. Check to make sure your client is sending requests in this format.
Using WebClient:
var uri = new Uri("http://localhost:8081/hello.hello");
var data = "{\"my_name\":\"Joe\"}";
var wc = new WebClient();
wc.Headers["Content-type"] = "application/json";
wc.Encoding = Encoding.UTF8;
var response = wc.UploadString(uri, data);
For serializing objects, you can use DataContractJsonSerializer.

Categories

Resources