c# .net Http response 411 length required when length is included - c#

I'm trying to get a simple response from a local .net site of my own. (Really I'm just trying to see what the content-body looks like from the server side.) Here is the controller method that's sending the response:
public HttpResponseMessage Post([FromBody]string value)
{
data.Add(value);
var msg = Request.CreateResponse(HttpStatusCode.Created);
msg.Headers.Location = new Uri(Request.RequestUri + "/" + (data.Count-1).ToString());
msg.Content = new StringContent(value);
return msg;
}
And here is the code that's making the request:
HttpWebRequest request;
request = (HttpWebRequest)WebRequest.Create ("http://localhost:50203/api/Values");
request.Method = "POST";
try
{
WebResponse response = (HttpWebResponse)request.GetResponse();
Stream dataStream = response.GetResponseStream();
byte[] requestBody = ASCIIEncoding.ASCII.GetBytes(HttpUtility.UrlEncode("grant_type=client_credentials"));
request.ContentLength = requestBody.Length;
dataStream.Write(requestBody, 0, requestBody.Length);
StreamReader reader = new StreamReader(dataStream);
myString = reader.ReadToEnd();
}
I'm getting the response message: HTTP Error 411. The request must be chunked or have a content length. But as you can see I DO assign the content length in the line: request.ContentLength = requestBody.Length;.
Why am I getting this error?

Thanks to help from itsme86 I was able to see what was happening. It had to do with misunderstanding the HttpWebRequest method. I was trying to set the content length and write to the request after I'd already posted it using the GetResponse method. I should have posted the length first. This wasn't a particularly good question, and no one else should answer.

Related

C# HTTP request 401 and 500 error

I've been working on the Walmart API but I keep getting either the 401 error or the 500 error when I run the code
public void post()
{
byte[] data = Encoding.ASCII.GetBytes(
$"username={user}&password={password}");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://marketplace.walmartapis.com/v2/feeds?feedType=item");
request.Method = "POST";
request.Accept = "application/xml;";
request.ContentLength = data.Length;
request.Headers.Add("WM_SVC.NAME", "Walmart Marketplace");
request.Headers.Add(authId);
request.Headers.Add("WM_CONSUMER.ID", user);
request.Headers.Add( time);
request.Headers.Add(CorId);
using (Stream stream = request.GetRequestStream ())
{
stream.Write(data , 0, data.Length);
}
string responseContent = null;
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader sr99 = new StreamReader(stream))
{
responseContent = sr99.ReadToEnd();
}
}
}
MessageBox.Show(responseContent);
}
where authID is a signature generated from a jar file provided by walmart
time is also generated from the jar file
CorID is a randomly generated number
and user is the user id.
here is the link that describes the header parameters. Did I miss something in my header?
https://developer.walmartapis.com/#getting-started
There are multiple problems with your request. First, you are submitting a feed, but sending it as an application/xml when it should be a multipart/form-data request. Beyond this, your headers aren't set up properly and there is currently a major problem with submitting multipart/form-data requests to Walmart using C#. I have not seen a post from anyone successfully sending a feed to Walmart via C#. I am currently using C# to execute a batch file that then fires a modified version of the Walmart Java SDK which is capable of sending the multipart/form-data requests.
The reponse below is for any request other than feeds. I would start with the example listed below to get familiar with how you need to set your headers up. This is going to work for the majority of Walmart interfacing, but if the request is a feed style request, you will either need to come up with a better solution to the multipart/form-data issue, use the Java SDK, or wait for the C# SDK. If someone reads this and has a better answer as to how to submit feeds via C# exclusively I would love to hear about it!
Here is an example of an application/xml request that works.
string timestamp = CurrentTimeMillis().ToString().Trim();
string query = #"orders/"+poID+"/acknowledge";
string request = v3BaseUrl + query; //Constructed URI
string stringToSign = consumerId + "\n" +
request.Trim() + "\n" +
"POST" + "\n" +
timestamp + "\n";
string signedString = signData(stringToSign); //Your signed string
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(request);
webRequest.Accept = "application/xml";
webRequest.ContentType = "application/xml";
webRequest.Method = "POST";
webRequest.Headers.Add("WM_SVC.NAME", "Walmart Marketplace");
webRequest.Headers.Add("WM_SEC.AUTH_SIGNATURE", signedString);
webRequest.Headers.Add("WM_CONSUMER.ID", consumerId);
webRequest.Headers.Add("WM_SEC.TIMESTAMP", timestamp.ToString().Trim());
webRequest.Headers.Add("WM_QOS.CORRELATION_ID", Guid.NewGuid().ToString());
webRequest.Headers.Add("WM_CONSUMER.CHANNEL.TYPE", channelType);
webRequest.ContentLength = 0;
webRequest.Timeout = Timeout.Infinite;
webRequest.KeepAlive = true;
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
success = true;
}
}

HttpWebResponse contentLength always -1

My web response content length always seem to be -1 after my web request. I'm sure you massage and signature are right.
What am I doing wrong here?
string msg = string.Format("{0}{1}{2}", nonce, clientId, apiKey);
string signature = ByteArrayToString(SignHMACSHA256(apiSecret, StrinToByteArray(msg))).ToUpper();
const string endpoint = "https://www.bitstamp.net/api/balance/";
HttpWebRequest request = WebRequest.Create(endpoint) as HttpWebRequest;
request.Proxy = null;
request.Method = "POST";
request.ContentType = "application/xml";
request.Accept = "application/xml";
request.Headers.Add("key", apiKey);
request.Headers.Add("signature", signature);
request.Headers.Add("nonce", nonce.ToString());
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
From the documentation,
The ContentLength property contains the value of the Content-Length header returned with the response. If the Content-Length header is not set in the response, ContentLength is set to the value -1.
Got it working with webClient instead of the httpWebRequest.
If someone can get it working with httpWebRequest, you wil get the answer.
string msg = string.Format("{0}{1}{2}", nonce, clientId, apiKey);
var signature = ByteArrayToString(SignHMACSHA256(apiSecret, StrinToByteArray(msg))).ToUpper();
var path = "https://www.bitstamp.net/api/user_transactions/";
using (WebClient client = new WebClient())
{
byte[] response = client.UploadValues(path, new NameValueCollection()
{
{ "key", apiKey },
{ "signature", signature },
{ "nonce", nonce.ToString()},
});
var str = System.Text.Encoding.Default.GetString(response);
}
Because this worked with 'WebClient', there was nothing wrong with the request, which means almost definitely that the request was being sent back 'Chunked'. This is indicated by the header 'Transfer-Encoding'.
There are several reasons why the webserver might send back something chunked including the fact that the return is binary.
I came to this page because Fiddler was "interfering" with my request by turning a perfectly good response by the server and then returning it chunked to my client. That was because I had the 'Stream' button pushed or active. When it isn't, it sends the data back buffered which preserves the response from the server. That was a horrible thing to track down..
But the research did tell me about why the Content-Length header might be -1.
The solution? Either fix the way the server (or proxy in my case) is sending the response back, or just read the response stream to the end. The latter will return all the chunks to you connected and you can take a length of the bytes returned.
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
String responseString = reader.ReadToEnd();
int responseLength = responseString.Length;
If you want bytes it is more involved -- not sure if there is a reader that allows you to read to the end -- the Binary reader requires a buffer up front.
An elegant way to consume (all bytes of a) BinaryReader?
Njoy.

Unable to read HttpResponse from HTTPS

public void HttpsRequest(string address)
{
string data;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
byte[] resp = new byte[(int)response.ContentLength];
Stream receiveStream = response.GetResponseStream();
using (StreamReader reader = new StreamReader(receiveStream, Encoding.ASCII))
{
data = reader.ReadToEnd();
}
}
I get an Arithmetic operation resulted in an overflow when I am trying to read a page over https. Errors occur because the response gives me ContentLenght = -1.
Using fiddler I can see that the page was received. Some other websites using HTTPS works fine but most of them not.
If I query https://www.google.com, I get the same error message, because not every response has a content length. Use this code to avoid the problem:
public static void HttpsRequest(string address)
{
string data;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
request.Method = "GET";
using (WebResponse response = request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
data = reader.ReadToEnd();
}
}
}
This behavior is expected: not every response contains content length.
There is nothing in your sample that requires length to be known, so simply not reading it maybe enough.
From HttpWebResponse.ContentLength Property
The ContentLength property contains the value of the Content-Length header returned with the response. If the Content-Length header is not set in the response, ContentLength is set to the value -1.
If Content-Length header is not set it does not mean that you got a bad response.

Getting error " The remote server returned an error: (400) Bad Request." on line WebResponse response = request.GetResponse();

//Create a request using a URL that can receive a post.
WebRequest request = WebRequest.Create("https://go.urbanairship.com/api/push/");
request.Credentials = new NetworkCredential("pvYMExk3QIO7p2YUs6BBkg", "rO3DsucETRadbbfxHkd6qw");
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
//WRITE JSON DATA TO VARIABLE D
string postData = "{\"aps\": {\"badge\": 1, \"alert\": \"Hello from Urban Airship!\"}, \"device_tokens\": [\"6334c016fc643baa340eca25bc661d15055a07b475e9a6108f3f644b15dd05ac\"]}";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/json";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
using (Stream dataStream = request.GetRequestStream())
{
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
}
// Get the response.
WebResponse response = request.GetResponse();
//Error "The remote server returned an error: (400) Bad Request"
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
using (Stream dataStream = response.GetResponseStream())
{
// Open the stream using a StreamReader for easy access.
using (var reader = new StreamReader(dataStream))
{
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
response.Close();
}
}
I have experienced a similar problem to what he is getting.
When the exception is thrown calling GetResponse(), it is a WebException. Cast it as such, then check out the response stream. Yes, the content length is -1, but ignore that.
catch (Exception ex)
{
//byte[] buffer = new byte[999999];
WebException wex = (WebException)ex;
var s = wex.Response.GetResponseStream();
string ss = "";
int lastNum = 0;
do
{
lastNum = s.ReadByte();
ss += (char)lastNum;
} while (lastNum != -1);
s.Close();
s = null;
ErrorHasOccurred(new Exception("An error has occurred sending the notification to Urban Airship. Please see the InnerException for details. Please note that, for sending messages, the master password is required (instead of the regular password). ERROR: " + ss, ex));
}
Then just breakpoint right where I have ErrorHasOccurred and read the contents of the ss variable. It will tell you the actual error that Urban Airship returns.
What is your question? The server is saying your request is bad. Use Fiddler if you're not sure what you are actually sending to the server, then fix your request. Otherwise fix your server code.
Either way, this is "not a real question" fodder without some clarification.
It is a valid question...
First. Not use hard code for build the json string, use JavaScriptSerializer
var json = new JavaScriptSerializer().Serialize(yourObject);
Second. For single parameter, use
...
BodyStyle = WebMessageBodyStyle.Bare,
...
insted of
BodyStyle = WebMessageBodyStyle.WrappedRequest,
(I spend a few hours with a similar problem)

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