Why does this request works using HttpWebRequest but not with RestSharp? - c#

I am consuming an API that expects a XML in the body request. First i consumed the api via Postman and it worked, then i used that tool of Postman to convert the request to RestCharp C# code, and then using that code the reponse that i was receiving was different compared to postman. After that, i used Fiddler to generate c# code with the postman request, and using that code that fiddler generated i was able to consume the API via code sucessfully. I am just trying to understand what is the difference between the code generated from postman and the code generated from Fiddler.
This is the code that is generated from Fiddler and it works:
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create("http://x.x.x.x.x");
request.Accept = "*/*";
request.KeepAlive = true;
request.Method = "POST";
request.ServicePoint.Expect100Continue = false;
byte[] postBytes = System.Text.Encoding.UTF8.GetBytes(body);
request.ContentLength = postBytes.Length;
Stream stream = request.GetRequestStream();
stream.Write(postBytes, 0, postBytes.Length);
stream.Close();
response = (HttpWebResponse)request.GetResponse();
This is the code generated from Postman (slightly altered, but still the code that was generated from postman didn't work and i don't think that the changes that was made interfered with the result) using RestSharp that doesn't work:
var client = new RestClient("http://x.x.x.x.x");
client.ConfigureWebRequest((r) =>
{
r.ServicePoint.Expect100Continue = false;
r.KeepAlive = true;
});
var request = new RestRequest();
request.AddXmlBody(body);
IRestResponse response = client.Post(request);
return response;
I tried a lot of things in the RestSharp code, like adding a header with different content-types and encoding, for example
request.AddHeader("Content-Type", "text/xml;charset=utf-8");
but nothing worked. The response from the api when consumed by the RestSharp code says it got an error of NPE, which i believe it means NullPointerException, but since the api is working just fine via postman and the code generated by Fiddler, i don't think the problem is in the API. Btw, the parameter body in the code are the exact same in both codes.

It looks like the request body is not matching with expected content type by API. When the content does not match the content type expected by the API then you may get NPE error.
in your fiddler generated code you are sending XML string as text.
Please add the following code:
request.AddHeader("Content-Type", "text/plain");
request.AddParameter("undefined", "<YourXml></YourXml>", ParameterType.RequestBody);
or
request.AddHeader("Content-Type", "application/xml");
request.AddParameter("undefined", "<YourXml></YourXml>", ParameterType.RequestBody);
Instead of
request.AddXmlBody(body);

Related

Cannot access azure storage table using SAS via c#. Works in postman and browser

I am trying to obtain and parse a table from azure storage.
I generated a Shared Access Signature in azure storage explorer.
If I paste the generated url into browser or postman I get the table back as xml.
However, trying to do a HttpWebRequest with the url results in
System.Net.WebException: 'The remote server returned an error: (415) Unsupported Media Type.'
I have tried different content and accept types
const string url = #"https://laptopdeploymentfiles.table.core.windows.net/PaulLoginScript?st=2019-08-21T08%3A10%3A22Z&se=2019-08-22T08%3A10%3A22Z&sp=r&sv=2018-03-28&tn=paulloginscript&sig=***";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
var webResponse = request.GetResponse();
I have tried both
request.Accept = "application/xml";
and
request.ContentType = "application/xml";
but still get the same error.
I have also tried creating and accessing a new table with only simple data. The data accessed via the brower is valid xml, but I still get the same error from a c# app.
The solution was to use both the following contenttype and accept formats
request.Accept = "application/json";
request.ContentType = "application/json";
The solution was to use both the following contenttype and accept formats
request.Accept = "application/json";
request.ContentType = "application/json";
Tested your specific scenario and got it working by using the HttpClient class.
Here's the code I used to get it working:
// Create an instance of HttpClient with the BaseAddress
var client = new HttpClient
{
BaseAddress = new Uri("https://<STORAGE_NAME>.table.core.windows.net/")
};
// Add an Accept Header to tell the service you're expecting the data in JSON format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Get the actual table
var result = await client.GetAsync("<REST_OF_THE_URI");
When omitting the Accept-header, this code gives the error message:
Atom format is not supported.
EDIT
Taken from Query Tables - Request headers about the Accept header you can specify:
Optional. Specifies the accepted content type of the response payload. Possible values are:
application/atom+xml (versions prior to 2015-12-11 only)
application/json;odata=nometadata
application/json;odata=minimalmetadata
application/json;odata=fullmetadata
I think you need to tell your request what kind of data to expect. Try adding this:
request.ContentType = "application/xml";
I've not tested, so I can't promise this will work. Let me know if it does!
EDIT:
Paul, I tested this code below:
const string url = #" -- used my own xml file in Azure Blob Storage --";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/xml";
var webResponse = request.GetResponse();
It worked with no errors. webResponse was populated just fine. I just whipped up a console app and put these 5 lines of code in it, and then stepped through in debug mode to see what would happen.
I wonder what is different about your environment? Could you try isolating these lines of code?
EDIT 2:
Just a thought... are you sure the XML in your file is valid?

Postman C# code snippet working on postman and not in app

I have an XML file that is sent as form-data to a remote server. When I use postman, I receive the response that I was supposed to receive.
Postman response
Then I use the code snippet generator to port the call to my C# app, and when I run on the app it does not work.
C# response
The code snippet is:
var client = new RestClient("http://172.20.27.1/xxxxxx/xxxxxx");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "1d9df75d-2c8f-4c92-b861-9f4291145846");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"Metas\"; filename=\"C:\\Users\\agufprad\\Desktop\\Pepillo\\FLEX_REMAN_CfgRec_Final_00-00-00-4D_20190311-102223_1010039188_7000AHB.xml\"\r\nContent-Type: application/xml\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Is there anything I am not seeing here?
Can you export + upload the postman collection. That would help a lot.
A couple of things I see off the bat
1) You have a postman token header - why do you need this in C#?
2) Does none multi-part data work?
3) Are you sure content type is supposed to have the boundary data?
4) There is no file associated with the snippet. Pretty sure you can't just AddParameter multi-part data. Look for AddFile, which may be your issue.
5) Does an example off the web work? Currently this looks like it would be a malformed multi-part request
Thanks to everyone for the responses, gave an idea of where to look.
Finally i added a header on the post method request.AddHeader("Accept", "text/plain");
And added the file request.AddFile(fileName, Properties.Settings.Default.SaveRoute + fileName);
Thanks a lot!
I would advice you remove any content-length param, postman-token, cookie param generated from the code generator on Postman, and it should work as its own specific request.
Remove
request.AddHeader("Postman-Token", "1d9df75d-2c8f-4c92-b861-9f4291145846");

Postman to C#(Restsharp) code snippet issue

I am feeling pretty stupid right now I can not figure this out. I am using postman to generate some C#(Rest sharp) to post a file to a restAPI.
In postman it works file the code snippet that it generates for C# does not work. The response code shows an internal server error in C#. I can not figure out where the problem is.
Here is the code snippet.
client = new RestClient("https://login.mydgsi.ca/WebAPI/Attachment?aboutType=Candidate&referenceID=1314180%20&attachmentTypeID=Resume&Name=Resume&expirationDate=1900/01/01&Note=Candidate%20REeume");
request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "b339e68d-9257-44eb-8698-1f3f0c86ebfe");
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("Authorization", "Bearer " + secruityToken.access_token);
request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"\"; filename=\"C:\\Users\\jbungay\\Documents\\MyJabberFiles\\ddemchuk#domain.not.set\\3vertical Number 1 Resume.docx\"\r\nContent-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Here is fiddler shows on the postman post. I am new to Fiddler and Postman.
Screen of the inspector from Fidder
Try changing "Postman-Token" to just "token". This worked for me on another project. Keep in mind the request parameters change with every request.

RestSharp code generated form Postman does not work

I am testing the QuickPay API in Postman and everything works fine. When I use the Postman Code Generator to generate a RestSharp snippet of the succesful result, the code does not return a status 200 against the API, and nothing happens.
I have posted the generated code her (altered the auth code though)
var client = new RestClient("http://api.quickpay.net/subscriptions/18612/recurring?Accept-Version=v10&id=18427612&amount=9900&order_id=test1234");
var request = new RestRequest(Method.POST);
request.AddHeader("postman-token", "145e85d9-0e36-4e6a-2742-b36fb3dccadb");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("accept-version", "v10");
request.AddHeader("authorization", "Basic OjczYWY3NzlmZDYzMjIxNGUx33yYj5266ZkO222Z322221M34334433434344ZWY=");
IRestResponse response = client.Execute(request);
Any help is very much appreciated.
Best regards
I found out that instead of posting parameters into the url as querystring parameters, I should post them as parameters into the reqeuest method. No need for the Postman token nor the cache-control headers. And importantly, the url should be https://api.quickpay.net/subscriptions/18612/recurring

Can I send an empty HTTP POST WebRequest object from C# to IIS?

Do I need to just slap some random garbage data in a WebRequest object to get by the HTTP status code 411 restriction on IIS?
I have an HttpPost action method in an MVC 3 app that consumes a POST request with all the relevant information passed in the querystring (no body needed).
[HttpPost] public ActionResult SignUp(string email) { ... }
It worked great from Visual Studio's built in web host, Cassini. Unfortunately, once the MVC code was live on IIS [7.5 on 2008 R2], the server is pitching back an HTTP error code when I hit it from my outside C# form app.
The remote server returned an error:
(411) Length Required.
Here is the calling code:
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader responseReader = new StreamReader(responseStream)) {
// Do something with responseReader.ReadToEnd();
}
Turns out you can get this to go through by simply slapping an empty content length on the request before you send it.
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
request.ContentLength = 0;
Not sure how explicitly giving an empty length vs. implying one makes a difference, but IIS was happy after I did. There are probably other ways around this, but this seems simple enough.
I believe you are required to set a Content-Length header anytime you post a request to a web server:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.contentlength.aspx
You could try a GET request to test it.

Categories