cannot call web api successfully when sending xml data - c#

I cannot successfully call an API using C# at the moment. I have attached a screen shot of the call being successfully made with Chrome PostMan although I'm not able to replicate it in C#. He is my attempt so far which fails. The response I get back from the server is included below. Can anyone see what I'm doing wrong?
Many thanks,
James
Code Snippet
const string xml = "<Envelope><Body> <AddRecipient>...";
var req = (HttpWebRequest)WebRequest.Create(ApiUrl);
var requestBytes = System.Text.Encoding.ASCII.GetBytes(xml);
req.Method = "POST";
req.Headers.Add("Authorization", "Bearer " + token);
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = requestBytes.Length;
var requestStream = req.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();
var res = (HttpWebResponse)req.GetResponse(); // Call API
var sr = new StreamReader(res.GetResponseStream(), System.Text.Encoding.Default);
var backstr = sr.ReadToEnd();
sr.Close();
res.Close();
Chrome PostMan
Response back from API
<Envelope><Body><RESULT><SUCCESS>false</SUCCESS></RESULT><Fault><Request/><FaultCode/><FaultString>Server Error</FaultString><detail><error><errorid>50</errorid><module/><class>SP.API</class><method/></error></detail></Fault></Body></Envelope>

Is there any documentation about what error 50 is? Could just be a bad pram? If not I recommend downloading fiddler. You can then properly compare the request from both PostMan and your application to see what the actual difference is.

Related

Unable to post to merchant API due to error saying I must provide a request body

I spent all day trying to figure out what I was doing wrong yesterday.
Coming here to try and find some help.
The follow error is triggered when I run the actual GetResponse.
I am new to APIs so I am sure I am missing something real simple.
You must provide a request body if you set ContentLength>0 or SendChunked==true. Do this by calling [Begin]GetRequestStream before [Begin]GetResponse.
Here is my code I am using to try and send JSON to the API. Payment object just has the form values entered in and the credentials to use the correct account on the merchants end.
var json = JsonConvert.SerializeObject(payment);
var apiUrl = new Uri($"Removed endpoint URL");
var postBytes = Encoding.UTF8.GetBytes(json);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var httpWebRequest = (HttpWebRequest)WebRequest.Create(apiUrl);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.ContentLength = postBytes.Length;
httpWebRequest.AllowWriteStreamBuffering = false;
//This is where the error triggers and drops to the catch.
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
I appreciate any help in advance, I may be doing this completely wrong, its a series of things I threw together trying to fix issues with the call.
Unless I missed it, you're not actually writing your payload data to the HttpWebRequest body before you're sending it.
using (Stream _reqStrm = httpWebRequest.GetRequestStream())
{
_reqStrm.Write(postBytes, 0, postBytes.Length);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
....
Unrelated but if you can, consider HttpClient
Hth..

http response returning webpage

Excuse any ignorance on my part with this methodology as it is somewhat new to me. I've been reading up on it as much as I can, but haven't been able to solve this yet.
I'm trying to accomplish a SSO with a vendor through an http post. Simple enough. I've done this in the past, but it usually returns a url that I can then redirect the user to. Unfortunately, with this vendor they are returning the entire page, html and all. Is this typical? If so, is my only solution to post this to a new window?
For reference, here's my code so far:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] postBytes = Encoding.UTF8.GetBytes(postString);
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
var responseReader = new StreamReader(responseStream);
var responseString = responseReader.ReadToEnd();
responseReader.Close();
responseStream.Close();
response.Close();
Does everything look normal and ok so far?
It is normal for a POST request to return a new web page. I would think the redirect would be the abnormal case.
You're pretty vague about your app, so I'm not sure how you'll want to get the returned html shown to the user.
You might want to check out the WebClient class which could simplify your code considerably.
using (var client = new WebClient())
{
var resultBytes = client.UploadData(new Uri("http://example.com"), "POST", data);
}

HttpWebRequest to https server works in fiddler but NOT from Visual Studio

Here is the scenario. I have written code use a digital certificate to GET cookies from a secured url, to in turn POST data back to another url using the retrieved cookies and same digital certificate. The GET works and cookies are retrieved, the POST comes back with an error 500. I installed fiddler to see what was going on...POST looks fine...cookies are present. I used the feature in fiddler that allows creating a request via drag and drop. POST the exact same POST recorded from C# code that was recorded in fiddler and it works!
What is Fiddler doing that Visual Studio is not? It must be doing something if fiddler can POST the data but Visual Studio returns an error 500. Here is the code below:
X509Certificate cert = new X509Certificate("mycert.pfx", "certpassword");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://servertoGETcookies/fileUpload.html");
req.CookieContainer = new CookieContainer();
req.Method = "GET";
req.ClientCertificates.Add(cert);
HttpWebResponse Response = (HttpWebResponse)req.GetResponse();
CookieCollection ck = req.CookieContainer.GetCookies(req.RequestUri);
string strcookie = ck[0].Value;
string strcookie2 = ck[1].Value;
Response.Close();
req = (HttpWebRequest)WebRequest.Create("https://servertoPOSTdatawithcookies/main");
req.CookieContainer = new CookieContainer();
Cookie auth = new Cookie("_wl_authcookie_", strcookie2);
Cookie jsess = new Cookie("JSESSIONID", strcookie);
auth.Domain = "server";
jsess.Domain = "server";
req.CookieContainer.Add(auth);
req.CookieContainer.Add(jsess);
req.ClientCertificates.Add(cert);
req.Method = "POST";
Byte[] data = ReadByteArrayFromFile("filewithdatatoPOST.txt");
req.ContentLength = data.Length;
Stream myStream = req.GetRequestStream();
myStream.Write(data, 0, data.Length);
myStream.Close();
HttpWebResponse Response2 = (HttpWebResponse)req.GetResponse();
Stream strm = Response2.GetResponseStream();
StreamReader sr2 = new StreamReader(strm);
Response2.Close();
Does your code work if you set
req.ServicePoint.Expect100Continue = false;
on all your WebRequests?
Solved!!! It wasn't related to the Expect100Continue.
So after weeks of troubleshooting....6 different programmers....I figured it out. I'm not sure if this is always true, but in this scenario the problem was that the url we were getting cookies from:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://servertoGETcookies/fileUpload.html");
was not the same as the url that we were posting the data back to:
req = (HttpWebRequest)WebRequest.Create("https://servertoPOSTdatawithcookies/main");
Getting the cookies and posting back to the same url fixed the issue:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://servertoGETandPOSTcookies/main");
req = (HttpWebRequest)WebRequest.Create("https://servertoGETandPOSTcookies/main");

C# HttpWebRequest with XML Structured Data

I'm developing the client-side of a third party webservice. The purpose is that I send xml-file to the server.
How should I attach the xml-file to the httpwebrequest? What contentType is needed? More suggestions?
I cannot use mtom or dime.ie because I am using httpwebrequest. I am unable to use WCF either.
Here is a very basic method of sending XML structured data using HttpWebRequest (by the way you need to use request.ContentType = "application/xml";) :
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(myUrl));
request.Method = "POST";
request.ContentType = "application/xml";
request.Accept = "application/xml";
XElement redmineRequestXML =
new XElement("issue",
new XElement("project_id", 17)
);
byte[] bytes = Encoding.UTF8.GetBytes(redmineRequestXML.ToString());
request.ContentLength = bytes.Length;
using (Stream putStream = request.GetRequestStream())
{
putStream.Write(bytes, 0, bytes.Length);
}
// Log the response from Redmine RESTful service
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
Logger.Info("Response from Redmine Issue Tracker: " + reader.ReadToEnd());
}
I use this at one of my projects (NBug) to submit an issue report to my Redmine issue tracker which accepts XML structured data over web requests (via POST). If you need further examples, you can get a couple of fully featured examples here: http://nbug.codeplex.com/SourceControl/list/changesets (click 'Browse' under 'Latest Verion' label on the right then navigate to "NBug\Submit\Tracker\Redmine.cs")

WebRequest to connect to the Wikipedia API

This may be a pathetically simple problem, but I cannot seem to format the post webrequest/response to get data from the Wikipedia API. I have posted my code below if anyone can help me see my problem.
string pgTitle = txtPageTitle.Text;
Uri address = new Uri("http://en.wikipedia.org/w/api.php");
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
string action = "query";
string query = pgTitle;
StringBuilder data = new StringBuilder();
data.Append("action=" + HttpUtility.UrlEncode(action));
data.Append("&query=" + HttpUtility.UrlEncode(query));
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data.ToString());
request.ContentLength = byteData.Length;
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
}
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream.
StreamReader reader = new StreamReader(response.GetResponseStream());
divWikiData.InnerText = reader.ReadToEnd();
}
You might want to try a GET request first because it's a little simpler (you will only need to POST for wikipedia login). For example, try to simulate this request:
http://en.wikipedia.org/w/api.php?action=query&prop=images&titles=Main%20Page
Here's the code:
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create("http://en.wikipedia.org/w/api.php?action=query&prop=images&titles=Main%20Page");
using (HttpWebResponse response = (HttpWebResponse)myRequest.GetResponse())
{
string ResponseText;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
ResponseText = reader.ReadToEnd();
}
}
Edit: The other problem he was experiencing on the POST request was, The exception is : The remote server returned an error: (417) Expectation failed. It can be solved by setting:
System.Net.ServicePointManager.Expect100Continue = false;
(This is from: HTTP POST Returns Error: 417 "Expectation Failed.")
I'm currently in the final stages of implementing an C# MediaWiki API which allows the easy scripting of most MediaWiki viewing and editing actions.
The main API is here: http://o2platform.googlecode.com/svn/trunk/O2%20-%20All%20Active%20Projects/O2_XRules_Database/_Rules/APIs/OwaspAPI.cs and here is an example of the API in use:
var wiki = new O2MediaWikiAPI("http://www.o2platform.com/api.php");
wiki.login(userName, password);
var page = "Test"; // "Main_Page";
wiki.editPage(page,"Test content2");
var rawWikiText = wiki.raw(page);
var htmlText = wiki.html(page);
return rawWikiText.line().line() + htmlText;
You seem to be pushing the input data on HTTP POST, but it seems you should use HTTP GET.
From the MediaWiki API docs:
The API takes its input through
parameters in the query string. Every
module (and every action=query
submodule) has its own set of
parameters, which is listed in the
documentation and in action=help, and
can be retrieved through
action=paraminfo.
http://www.mediawiki.org/wiki/API:Data_formats

Categories