I'm looking for solution to send request with JSON like parameter to server.
I use this code,
var httpClient = new HttpClient();
var tempByteArray = Encoding.UTF8.GetBytes("my valid json");
var stream = new MemoryStream(tempByteArray);
var streamContent = new StreamContent(stream);
var request = new HttpRequestMessage(HttpMethod.Post, Constants.LocalServer);
request.Content = streamContent;
request.Headers.TransferEncodingChunked = true;
HttpResponseMessage response = await httpClient.SendAsync(request);
But in response I get:
{
StatusCode: 501,
ReasonPhrase: 'NotImplemented',
Version: 1.0,
Content: System.Net.Http.StreamContent,
Headers: {
X-Squid-Error: ERR_UNSUP_REQ0X-Cache: MISSfromproxy3.itos.orgX-Cache-Lookup: NONEfromproxy3.companyname.org: portProxy-Connection: closeDate: Thu,
18Apr201309: 17: 53GMTServer: squid/2.6.STABLE21Via: 1.0proxy3.companyname.org: port(squid/2.6.STABLE21)Content-Length: 1099Content-Type: text/htmlExpires: Thu,
18Apr201309: 17: 53GMT
}
}
May be have another way to sent request with json parameter on Win8?
UPDATE I found solution:
public static async Task<string> LoadData(string json, string serverUrl)
{
var request = (HttpWebRequest)WebRequest.Create(new Uri(Constants.LocalServer));
request.ContentType = "application/json";
request.Method = "POST";
using (var requestStream = await request.GetRequestStreamAsync())
{
var writer = new StreamWriter(requestStream);
writer.Write(json);
writer.Flush();
}
using (var resp = await request.GetResponseAsync())
{
using (var responseStream = resp.GetResponseStream())
{
var reader = new StreamReader(responseStream);
return = reader.ReadToEnd();
}
}
}
It's work great, but must exists more simple way(i hope). And I'll try to find it.
When I post data using your two code snippets, I see some differences in the requests.
Here is the raw post for the first code sample (that you say does not work):
POST http://testing.foo.com/api/Values HTTP/1.1
Host: testing.foo.com
Expect: 100-continue
Connection: Keep-Alive
Content-Length: 75
{
id:"1",
title:"title text",
post:"post text",
isDeleted:"False"
}
This is the raw post for the code in your update (code that you say works):
POST http://testing.foo.com/api/Values HTTP/1.1
Content-Type: application/json
Host: testing.foo.com
Content-Length: 75
Expect: 100-continue
{
id:"2",
title:"title text",
post:"post text",
isDeleted:"False"
}
The differences in the two requests are as follows:
In the first request, the content type is never set.
In the first request, the content is UTF8 encoded.
To fix your non-working code, I would suggest you try one or both of the following:
Set the content type to application/json
Not UTF8 encode the request
At that moment this solution is most useful.
public static async Task<string> LoadData(string json, string serverUrl)
{
var request = (HttpWebRequest)WebRequest.Create(new Uri(Constants.LocalServer));
request.ContentType = "application/json";
request.Method = "POST";
using (var requestStream = await request.GetRequestStreamAsync())
{
var writer = new StreamWriter(requestStream);
writer.Write(json);
writer.Flush();
}
using (var resp = await request.GetResponseAsync())
{
using (var responseStream = resp.GetResponseStream())
{
var reader = new StreamReader(responseStream);
return = reader.ReadToEnd();
}
}
}
Related
I'm facing a problem when using HttpClient. The call works right and I get an answer but I can't get the content properly.
The function I wrote looks like this:
public async Task<string> MakePostRequestAsync(string url, string data, CancellationToken cancel)
{
String res = String.Empty;
using (HttpClient httpClient = new HttpClient())
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
HttpContent content = new StringContent(data, Encoding.UTF8, "application/xml");
httpClient.DefaultRequestHeaders.Authorization = getHeaders();
httpClient.DefaultRequestHeaders.Add("Accept", "application/xml");
httpClient.DefaultRequestHeaders.Add("User-Agent", "C#-AppNSP");
httpClient.DefaultRequestHeaders.ExpectContinue = false;
HttpResponseMessage response = await httpClient.PostAsync(url, content, cancel);
response.EnsureSuccessStatusCode(); // Lanza excepción si no hay éxito
res = await response.Content.ReadAsStringAsync();
if (String.IsNullOrEmpty(res))
{
throw new Exception("Error: " + response.StatusCode);
}
}
return res;
}
The response string I get is similar to this one:
HTTP/1.1 0 nullContent-Type: application/xml;charset=UTF-8
Content-Length: 1263
Date: Tue, 02 Jul 2019 07:48:07 GMT
Connection: close
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SeguimientoEnviosFechasResponse xsi:noNamespaceSchemaLocation="SeguimientoEnviosFechasResponse.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Error>0</Error>
<MensajeError></MensajeError>
<SeguimientoEnvioFecha>
<!-- more XML here -->
</SeguimientoEnvioFecha>
</SeguimientoEnviosFechasResponse>
This string includes headers for some reason, so when I try to deserialize it I get an error.
How can I remove this headers in the response string?
Your server returns headers in the response body. Would be good to fix this on a server side, if it's not possible you should extract body from the response:
var xml = res.Substring(res.IndexOf("<?xml", StringComparison.Ordinal));
You may try this:
using (var receiveStream = response.GetResponseStream())
{
using (var readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
Console.WriteLine (readStream.ReadToEnd ());
}
}
I use .NET 4.61. Can I get the response from https://1106-7916.el-alt.com/wp-json/wc/v2/products/407 instead of https://1106-7916.el-alt.com/wp-json/wc/v2/products, which causes a redirect? Can I add code to BuildRequest, shown below, to get that response automatically?
I am using the WooCommerce REST API to create products. Here is my request:
POST-https://1106-7916.el-alt.com/wp-json/wc/v2/products?consumer_key=X
{"attributes":[{"name":"Color","visible":true,"variation":true,"options":["Red","Blue","Green","Orange"]},{"name":"Size","visible":true,"variation":true,"options":["S","M","L"]}],"title":"FooFoo","sku":"TestCreateProductWoo1026","description":"Test","categories":[],"tags":[],"type":"variable"}
Here is the response:
HTTP/1.1 201 Created
Cache-Control: no-cache, must-revalidate, max-age=0
Allow: GET, POST
Location: https://1106-7916.el-alt.com/wp-json/wc/v2/products/407
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found here</body>{"id":407,"name":"Product","slug":"product"}
Here is my code:
private string BuildRequest(string path, IDictionary<string, string> query, HttpMethodTypes httpMethod, object body)
{
string pathAndQuery = BuildParameters(path, query);
string resultData = string.Empty;
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(pathAndQuery);
myHttpWebRequest.Accept = "application/json";
myHttpWebRequest.ContentType = "application/json";
myHttpWebRequest.UserAgent = "JMA Web Technologies";
myHttpWebRequest.AllowAutoRedirect = true;
SetHeaders(myHttpWebRequest);
if (httpMethod != HttpMethodTypes.GET)
myHttpWebRequest.Method = httpMethod.ToString();
SetResponseBody(body, myHttpWebRequest);
WebResponse httpResponse = myHttpWebRequest.GetResponse();
Stream responseStream = httpResponse.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
resultData = reader.ReadToEnd();
responseStream.Close();
httpResponse.Close();
return resultData;
}
Any help is greatly appreciated.
While interacting with an API there is a situation where they will return a 401 response that also contains data. I would like to return this data regardless of the error code of the response.
I have created a function to submit a either a GET or POST using HttpWebRequest that returns a string containing the response data. The only problem is that if the response is a 401, an error is thrown and the data is not read.
Here is an example of what is returned:
HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: false
Content-Type: application/json; charset=UTF-8
Date: Tue, 19 May 2015 17:56:10 GMT
Vary: Accept-Encoding
Vary: Accept-Encoding
Content-Length: 254
Connection: keep-alive
{"status":"error","message":"access_token (...) was deleted (at Tue May 19 17:52:49 UTC 2015). Use your refresh token (if you have one) to generate a new access_token.","requestId":"..."}
Here is what I have for my function so far:
private string SendHttpRequest(string url, out int statusCode, string method = "GET", object postData = null, string contentType = "application/json")
{
bool isPost = method.Equals("POST", StringComparison.CurrentCultureIgnoreCase);
byte[] content = new ASCIIEncoding().GetBytes(isPost ? JsonConvert.SerializeObject(postData) : "");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AllowAutoRedirect = true;
request.Method = method;
request.ContentType = contentType;
request.ContentLength = postData == null ? 0 : content.Length;
if (isPost && postData != null)
{
Stream reqStream = request.GetRequestStream();
reqStream.Write(content, 0, content.Length);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); // Throws error here
string result;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
statusCode = (int)response.StatusCode;
response.Close();
return result;
}
How can I still get the data for a 401 response? There is no requirement to use HttpWebRequest, that is just what I have been using so far.
The call to GetResponse is throwing a WebException. You can catch that exception and extract the response via the exception's Response property:
private string SendHttpRequest(string url, out int statusCode, string method = "GET", object postData = null, string contentType = "application/json")
{
bool isPost = method.Equals("POST", StringComparison.CurrentCultureIgnoreCase);
byte[] content = new ASCIIEncoding().GetBytes(isPost ? JsonConvert.SerializeObject(postData) : "");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AllowAutoRedirect = true;
request.Method = method;
request.ContentType = contentType;
request.ContentLength = postData == null ? 0 : content.Length;
if (isPost && postData != null)
{
Stream reqStream = request.GetRequestStream();
reqStream.Write(content, 0, content.Length);
}
HttpWebResponse response = null;
//Get the response via request.GetResponse, but if that fails,
//retrieve the response from the exception
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = (HttpWebResponse)ex.Response;
}
string result;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
statusCode = (int)response.StatusCode;
response.Close();
return result;
}
I want to login to this site: http://subcard.subway.co.uk/de_cardholder/JSP/login_reg.jsp
And i found out that I have to send a POST request to the server and I also know that I have to work with this POST request:
POST /de_cardholder/servlet/SPLoginServlet HTTP/1.1
Host: subcard.subway.co.uk
language=de&userID=ID&password=PASSWORD&transIdentType=1&programID=6
And after the login I want to parse the HTML data. But how can I implement the POST request on WP in C# and is it as easy as I think?
Try this,
Uri RequestUri = new Uri("subcard.subway.co.uk/de_cardholder/servlet/SPLoginServlet HTTP/1.1?language=de&userID=ID&password=PASSWORD&transIdentType=1&programID=6", UriKind.Absolute);
string PostData = "";
WebRequest webRequest;
webRequest = WebRequest.Create(RequestUri);
webRequest.Method = "POST";
webRequest.ContentType = "text/xml";
HttpWebResponse response;
string Response;
using (response = (HttpWebResponse)await webRequest.GetResponseAsync()) ;
using (Stream streamResponse = response.GetResponseStream())
using (StreamReader streamReader = new StreamReader(streamResponse))
{
Response = await streamReader.ReadToEndAsync();
}
if(Response != null)
{
//data should be available in Response
}
var postRequest = (HttpWebRequest)WebRequest.Create("your Url here");
postRequest.ContentType = "application/x-www-form-urlencoded";// you can give the type of request content here
postRequest.Method = "POST";
if you have any data to be posted along with the request as part of content and not as part of URL itself you can add this. example:- ( language=de&userID=ID&password=PASSWORD&transIdentType=1&programID=6)
using (var requestStream = await postRequest.GetRequestStreamAsync())
{
byte[] postDataArray = Encoding.UTF8.GetBytes("your request data");
await requestStream.WriteAsync(postDataArray, 0, postDataArray.Length);
}
if you do not have any data to be a send as content ignore the above code
WebResponse postResponse = await postRequest.GetResponseAsync();
if (postResponse != null)
{
var postResponseStream = postResponse.GetResponseStream();
var postStreamReader = new StreamReader(postResponseStream);
string response = await postStreamReader.ReadToEndAsync();// Result comes here
}
I've got a problem with sending POST request to the apache server with htaccess using WebClient (I've tryed to using HttpRequest as well as WebRequest but it had the same result).
I've got the following example from vendor on PHP:
$soap = curl_init(url);
curl_setopt($soap, CURLOPT_POST, 1);
curl_setopt($soap, CURLOPT_RETURNTRANSFER, 1);
$XML = file_get_contents("test.xml");
$request = <<<XML
$XML
XML;
curl_setopt($soap, CURLOPT_HTTPHEADER, array('Content-Type: text/xml; charset=utf-8', 'Content-Length: '.strlen($request)));
curl_setopt($soap, CURLOPT_POSTFIELDS, $request);
$response = curl_exec($soap);
curl_close($soap);
My version on C# is:
public static string Post(string login, string password, string url, string content) {
var result = String.Empty;
var uri = new Uri(url);
using (var client = new WebClient()) {
client.Credentials = new NetworkCredential(login, password);
client.Encoding = Encoding.UTF8;
client.Headers[HttpRequestHeader.ContentType] = "text/xml; charset=UTF-8";
client.Headers[HttpRequestHeader.Accept] = "application/xml";
result = client.UploadString(uri, content);
}
return result;
}
When I run the program I've got an exception with 400 error (bad request). I've sniff the request using Fiddler2 and found the following error message: "Request header field is missing ':' separator"
Can anyone help me found what is wrong in the request and why a server reject the request?
P.S: Request header
POST http://production.is.topdelivery.ru/tests/xmlGate/index.php HTTP/1.1
Content-Type: text/xml; charset=utf-8
Authorization: Basic YmFiYWR1OmJhYmFkdXBhc3M=
Host: production.is.topdelivery.ru
Content-Length: 1617
Expect: 100-continue
In my case following code works properly
private string post(string content)
{
var result = String.Empty;
var uri = new Uri(_url);
WebRequest req = HttpWebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "text/xml";
String encoded = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("user:pass"));
req.Headers.Add("Authorization", "Basic " + encoded);
using (var s = req.GetRequestStream())
using (var sw = new StreamWriter(s, Encoding.UTF8))
{
sw.Write(content);
}
using (var s = req.GetResponse().GetResponseStream())
using (var sr = new StreamReader(s, Encoding.UTF8))
{
result = sr.ReadToEnd();
};
return result;
}
This helped me. I was having an issue with a newer release of Apache not seeing the credentials even though there was no issue with an older version. I changed
client.Credentials = new NetworkCredential(login, password);
to
String encoded = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("user:pass"));
req.Headers.Add("Authorization", "Basic " + encoded);
and it worked!
Thank you.