Posting Soap XML in Windows 8 Metro App - Errors - c#

I am writing C# code for a WinRT Surface Tablet in Visual Studio Express 2012 for Windows 8. Although my xml is formatted (I am porting from apps on other platforms that work fine) I am apparently having trouble with the request syntax.
I've been trying several different approaches and hit dead ends with the limitation of windows store apps in methods. The last I have tried is using HttpClient, HttpContent and HttpRequestMessage: (omitting the actual xml and urls, obviously)
string xmlSOAP = "..............[my soap xml]................."
string url = "http://example.domain.com/myMagicalwebservice.asmx"
string SOAPAction = "www.blahblah.com/doXMLStuff";
HttpClient hc = new
HttpContent content = new String Content(xmlSOAP);
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, url);
req.Headers.Add("SOAPAction", SOAPAction);
req.Method = HttpMethod.Post;
req.Content = content;
req.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/soap+xml;charset=UTF-8");
hc.SendAsync(req).ContinueWith(responseTask =>
{
System.Diagnostics.Debug.WriteLine(responseTask.Result);
});
This results in a System.FormatException of "The format of value 'application/soap+xml;charset=UTF-8' is invalid."
If I instead add the content type directly to the HttpContent instead of to HttpRequestMessage, I get the same outcome.
If I simply comment out the line adding the content type (just doing dumb trial and error here) I receive a result with statuscode 415: "Unsupported Media Type."
I have tried posting using the PostAsync method of HttpClient but I am unsure how to get the response using that.
Any help would be very much appreciated, and I thank you in advance for your time!

Try this:
req.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/soap+xml;charset=UTF-8");

Related

WebRequest returns unreadable string [duplicate]

I'm trying to download an html document from Amazon but for some reason I get a bad encoded string like "��K��g��g�e".
Here's the code I tried:
using (var webClient = new System.Net.WebClient())
{
var url = "https://www.amazon.com/dp/B07H256MBK/";
webClient.Encoding = Encoding.UTF8;
var result = webClient.DownloadString(url);
}
Same thing happens when using HttpClient:
var url = "https://www.amazon.com/dp/B07H256MBK/";
var httpclient = new HttpClient();
var html = await httpclient.GetStringAsync(url);
I also tried reading the result in Bytes and then convert it back to UTF-8 but I still get the same result. Also note that this DOES NOT always happen. For example, yesterday I was running this code for ~2 hours and I was getting a correctly encoded HTML document. However today I always get a bad encoded result. It happens every other day so it's not a one time thing.
==================================================================
However when I use the HtmlAgilitypack's wrapper it works as expected everytime:
var url = "https://www.amazon.com/dp/B07H256MBK/";
HtmlWeb htmlWeb = new HtmlWeb();
HtmlDocument doc = htmlWeb.Load(url);
What causes the WebClient and HttpClient to get a bad encoded string even when I explicitly define the correct encoding? And how does the HtmlAgilityPack's wrapper works by default?
Thanks for any help!
I fired up Firefox's web dev tools, requested that page, and looked at the response headers:
See that content-encoding: gzip? That means the response is gzip-encoded.
It turns out that Amazon gives you a response compressed with gzip even when you don't send an Accept-Encoding: gzip header (verified with another tool). This is a bit naughty, but not that uncommon, and easy to work around.
This wasn't a problem with character encodings at all. HttpClient is good at figuring out the correct encoding from the Content-Type header.
You can tell HttpClient to un-zip responses with:
HttpClientHandler handler = new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.GZip,
};
using (var client = new HttpClient(handler))
{
// your code
}
This will be set automatically if you're using the NuGet package versions 4.1.0 to 4.3.2, otherwise you'll need to do it yourself.
You can do the same with WebClient, but it's harder.

C# WPF POST Request to php file on https site on strato server not working

I want to post one or more values to a php file on a strato (the host) server on a https domain using a C# WPF desktop application. However, after several attempts with a test program nothing seems to work. The testing value is not posted to the server, the $_POST Array is empty, respectively. I do get an echoed answer from the server but its always 'Error' (See script below).
I did try this with several techniques as well:
Webclient / HttpClient
HttpWebRequest
Adjusting SecurityProtocolType
sending value as byte[]
and what not.
$_GET by the way works perfectly fine as I always get back the computed testing value from the php script. However, I would like to have a POST Request since I am sending user data to the server.
More precisely, I already have tried these solutions (and several similar ones):
How to make HTTP POST web request (basically all of them except 3rd Party)
C# HttpClient not sending POST variables
https://holger.coders-online.net/118
http://www.howtosolvenow.com/how-to-send-https-post-request-with-c/
Testing PHP Script:
$newnumber = 'Error';
if(isset($_POST['number']))
{
$newnumber = $_POST['number']+1;
}
echo $newnumber;
//keeps on returning 'Error'
Latest attempt of C# code:
string resultString = null;
string _url = "https://myURL.com/test.php";
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
HttpClient client = new HttpClient();
var content = new FormUrlEncodedContent(new[] {
new KeyValuePair<string,string>("number", "2"),
});
var response = await client.PostAsync(_url, content);
resultString = await response.Content.ReadAsStringAsync();
this._txt.Text = resultString;

404 error when trying to upload crash to hockeyapp

I'm trying to upload crash manually to HockeyApp using public API. When calling the api link using Postman and uploading crash.log file it works fine but when I try to do the same from C# code I get 404 error.
Here is my code:
string log = ""; //log content
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*"));
var content = new MultipartFormDataContent();
var stringContent = new StringContent(log);
stringContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("text/plain");
content.Add(stringContent, "log", "crash.log");
var response = await this.client.PostAsync("https://rink.hockeyapp.net/api/2/apps/[APP_ID]/crashes/upload", content);
}
I was using WireShark to analyse the request that Postman is sending and tried to make mine look exactly the same. The only difference I see is that request from C# code has filename* field in Content-Disposition for the attachment while the one from Postman doesn't:
Content-Disposition: form-data; name="log"; filename="crash.log"; filename*=utf-8''%22crash.log%22
It might be worth mentioning that the code is written in portable library in Xamarin project.
Following #Lukas Spieß sugestion I asked the question on HockeyApp support. Apparently they don't handle quotes in the boundary header. The one thing I missed comparing Postman request and mine.
Here is the solution:
var contentTypeString = content.Headers.ContentType.ToString().Replace("\"", "");
content.Headers.Remove("Content-Type");
content.Headers.TryAddWithoutValidation("Content-Type", contentTypeString);

upload feed to walmart

I am breaking my head trying to upload a feed to walmart, after many times trying i used postman to generate C# restsharp code for me, in postman it works, but when using the c# restsharp code it returns a mysterious error. like this:
"No message body writer has been found for response class FeedAcknowledgement"
what does that mean?
here is my code:
string requestUrl = "";
requestUrl = string.Format("https://marketplace.walmartapis.com/v2/feeds?feedType=inventory");
string method = "POST";
// string[] sig = getSig(method, requestUrl).Replace("\r", "").Split('\n');
var mySig = new Signature(ConsumerID, SecretKEY, requestUrl, method);
var s = mySig.TimeStamp;
var returendSigniture = mySig.GetSignature(s);
var client = new RestClient("https://marketplace.walmartapis.com/v2/feeds?feedType=inventory");
var request = new RestRequest(Method.POST);
//request.AddHeader("postman-token", "c325ba5f-813a-f990-7899-6bfc4b14aa1b");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
request.AddHeader("accept", "application/xml");
request.AddHeader("wm_consumer.id", "--");
request.AddHeader("wm_sec.auth_signature", returendSigniture);
request.AddHeader("wm_sec.timestamp", mySig.TimeStamp);
request.AddHeader("wm_qos.correlation_id", "123456abcdef");
request.AddHeader("wm_svc.name", "Walmart Marketplace");
request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"BOUNDERY\"\r\n\r\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<wm:inventory xmlns:wm=\"http://walmart.com/\">\n <wm:sku>PP00500-2PC</wm:sku>\n <wm:quantity>\n <wm:unit>EACH</wm:unit>\n <wm:amount>120</wm:amount>\n </wm:quantity>\n <wm:fulfillmentLagTime>1</wm:fulfillmentLagTime>\n</wm:inventory>\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
I spent all day in figuring out how to request Walmart v3. I propose you the following two steps:
Use Walmart signer in order to generate signed token.
You will need to use HttpWebRequest for getting response from Walmart in a way similar to what is described here.
I have not been able to get this to work natively in C#, but I do have a work around.
The Java SDK can successfully submit multi-part requests to Walmart. I wrote a wrapper around the SDK functions that can accept basic command line input to read a text file and send the appropriate call with attached files. From here, you can just call the .jar file (I do it via dynamically generated batch file) from your C# program and receive responses back via text file. This is a sub-optimal system, but it works reliably and when the choice was between updating inventory on 2000 items every day and using some dirty code, I went with the Java wrapper method. This will be replaced as soon as the C# SDK comes out, but I believe this is one of the reasons why the C# SDK may be being delayed.
This solution was used, only after spending about a week trying to get boundaries / streams / attachments to work in C# and having zero success. Cases were also submitted to walmart and I was able to work with some of their top tier engineering support staff and this problem completely stumped them. I was able to trace the Java SDK execution all the way down to a built in Maven / Java function that constructed the web request so there's something under the hood that Java is doing with a multi-part request that isn't immediately clear in C#.

Error posting a share on LinkedIn using Hammock lib

I'm trying to send a new Share on a Linkedin Person. This is my client code:
RestClient client = new RestClient()
{
Authority = "http://api.linkedin.com/v1",
Credentials = this.AccessCredentials(connectionData.ApplicationKey, connectionData.ApplicationSecret, connectionData.AccessToken, connectionData.AccessSecret),
Method = WebMethod.Post,
Encoding = Encoding.UTF8,
};
RestRequest request = new RestRequest()
{
Path = "people/~/shares",
Encoding = Encoding.UTF8,
};
Share share = new Share(socialMessage.Text, socialMessage.Name, socialMessage.Description, VisibilityCode.Anyone);
share.Content.SubmittedImageUrl = socialMessage.PictureLink;
share.Content.SubmittedUrl = socialMessage.Link;
String content = Utilities.SerializeToXml<Share>(share);
client.AddPostContent(System.Text.Encoding.UTF8.GetBytes(content));
client.AddHeader("Content-Type", "text/xml");
request.AddPostContent(System.Text.Encoding.UTF8.GetBytes(content));
request.AddHeader("Content-Type", "text/xml");
RestResponse response = client.Request(request);
I always obtain this error message after the call "Couldn't parse share document: error: Unexpected end of file after null".
Does anyone can tell me how to use Hammock library to send a POST to LinkedIn?
Thanks & Regards
Also there is possible solution here:
https://github.com/danielcrenna/hammock/issues/4
I'm not sure how to use the hammock library, but you can debug API calls for LinkedIn (or any other web service) using the tips at
http://developer.linkedin.com/documents/debugging-api-calls
This will show you how to install an HTTP sniffer and watch the traffic to see what's happening. Once you've done that, if you're still having issues post them and it'll be possible to debug what's going wrong.

Categories