When I use the methods below to send an xml request to an asmx service, it works fine, the only difference is is that the content type is application/soap+xml. I am getting the error: 400 Bad Request. Here is the method I am using below to send the request via HTTP Post to the WCF Service:
private static void SendRequest(string request)
{
var req = (HttpWebRequest) WebRequest.Create("http://urltoservice.svc");
req.ContentType = "text/xml";
req.Method = "POST";
using (var stm = req.GetRequestStream())
{
using (var stmw = new StreamWriter(stm))
{
stmw.Write(request);
}
}
byte[] myData;
using (var webResponse = req.GetResponse())
{
var responseStream = webResponse.GetResponseStream();
myData = ReadFully(responseStream);
}
// Do whatever you need with the response
string responseString = Encoding.ASCII.GetString(myData);
}
It seems to throw it at the line: var webResponse = req.GetResponse()
What is the type of service that you are trying to call. Is it REST WCF service or SOAP WCF Service?
You can monitor your request using Fiddler to see how your request looks when it works and when it doesnt.
Also enable Tracing on your service to know why you get a 400 Bad Request.
No idea why this works, if someone can explain it it would be great. I needed to append the method name to URI in order for it to work, for example,
http://urltoservice.svc/MethodToCall
Related
This might be an odd question, but I'm ultimately trying to click an "add to cart" button by sending a POST request in C#. I'm currently using Advanced REST Client to try to send the request and I'm having a lot trouble. This is the item I'm trying to add to cart. I am sending the POST request with
http://www.supremenewyork.com/shop/169720/add?authenticity_token=oZ2ZwxDZwEJ%2BUSczNZrhUlNSGw5NnsP%2FvcbxiSnxnSM%3D&commit=add%20to%20cart&size=32377&utf8=%E2%9C%93
but I keep getting 404 not found. I might be putting in the wrong information into the client. I just started learning about POST/GET requests yesterday, so any advice would be greatly appreciated; thank you.
You can use this method to get content using POST request.
public static async Task<byte[]> GetPostContentAsync(string url, string data)
{
var content = new MemoryStream();
var cookies = new CookieContainer();
HttpWebRequest webReq;
webReq = (HttpWebRequest)WebRequest.Create(url);
webReq.CookieContainer = cookies;
webReq.Method = "POST";
webReq.ContentType = "application/x-www-form-urlencoded";
Stream requestStream = await webReq.GetRequestStreamAsync();
using (var writer = new StreamWriter(requestStream))
{
await writer.WriteAsync(data);
}
using (var responseStream = await webReq.GetResponseAsync())
{
using (Stream response = responseStream.GetResponseStream())
{
await response.CopyToAsync(content);
}
}
return content.ToArray();
}
I've followed the following article to set up a simple Web API solution:
http://www.codeproject.com/Articles/350488/A-simple-POC-using-ASP-NET-Web-API-Entity-Framewor
I've omitted the Common project, Log4Net and Castle Windsor to keep the project as simple as possible.
Then I created a WPF project. However, now which project should I reference in order access the WebAPI and the underlying models?
Use the HttpWebRequest class to make request to the Web API. Below a quick sample for something I've used to make requests to some other restful service (that service only allowed POST/GET, and not DELETE/PUT).
HttpWebRequest request = WebRequest.Create(actionUrl) as HttpWebRequest;
request.ContentType = "application/json";
if (postData.Length > 0)
{
request.Method = "POST"; // we have some post data, act as post request.
// write post data to request stream, and dispose streamwriter afterwards.
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(postData);
writer.Close();
}
}
else
{
request.Method = "GET"; // no post data, act as get request.
request.ContentLength = 0;
}
string responseData = string.Empty;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
responseData = reader.ReadToEnd();
reader.Close();
}
response.Close();
}
return responseData;
There are also a nuget package available called "Microsoft ASP.NET Web API client libraries" which can be used to make requests to the WebAPI. More on that package here(http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client)
i wrote a simple C# function to retrieve trade history from MtGox with following API call:
https://data.mtgox.com/api/1/BTCUSD/trades?since=<trade_id>
documented here: https://en.bitcoin.it/wiki/MtGox/API/HTTP/v1#Multi_currency_trades
here's the function:
string GetTradesOnline(Int64 tid)
{
Thread.Sleep(30000);
// communicate
string url = "https://data.mtgox.com/api/1/BTCUSD/trades?since=" + tid.ToString();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string json = reader.ReadToEnd();
reader.Close();
reader.Dispose();
response.Close();
return json;
}
i'm starting at tid=0 (trade id) to get the data (from the very beginning). for each request, i receive a response containing 1000 trade details. i always send the trade id from the previous response for the next request. it works fine for exactly 4 requests & responses. but after that, the following line throws a "System.Net.WebException", saying that "The operation has timed out":
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
here are the facts:
catching the exception and retying keeps causing the same exception
the default HttpWebRequest .Timeout and .ReadWriteTimeout are already high enough (over a minute)
changing HttpWebRequest.KeepAlive to false didn't solve anything either
it seems to always work in the browser even while the function is failing
it has no problems retrieveing the response from https://www.google.com
the amount of successful responses before the exceptions varies from day to day (but browser always works)
starting at the trade id that failed last time causes the exception immediately
calling this function from the main thread instead still caused the exception
running it on a different machine didn't work
running it from a different IP didn't work
increasing Thread.Sleep inbetween requests does not help
any ideas of what could be wrong?
I had the very same issue.
For me the fix was as simple as wrapping the HttpWebResponse code in using block.
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
{
// Do your processings here....
}
Details: This issue usually happens when several requests are made to the same host, and WebResponse is not disposed properly. That is where using block will properly dispose the WebResponse object properly and thus solving the issue.
There are two kind of timeouts. Client timeout and server timeout. Have you tried doing something like this:
request.Timeout = Timeout.Infinite;
request.KeepAlive = true;
Try something like this...
I just had similar troubles calling a REST Service on a LINUX Server thru ssl. After trying many different configuration scenarios I found out that I had to send a UserAgent in the http head.
Here is my final method for calling the REST API.
private static string RunWebRequest(string url, string json)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
// Header
request.ContentType = "application/json";
request.Method = "POST";
request.AllowAutoRedirect = false;
request.KeepAlive = false;
request.Timeout = 30000;
request.ReadWriteTimeout = 30000;
request.UserAgent = "test.net";
request.Accept = "application/json";
request.ProtocolVersion = HttpVersion.Version11;
request.Headers.Add("Accept-Language","de_DE");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
byte[] bytes = Encoding.UTF8.GetBytes(json);
request.ContentLength = bytes.Length;
using (var writer = request.GetRequestStream())
{
writer.Write(bytes, 0, bytes.Length);
writer.Flush();
writer.Close();
}
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var jsonReturn = streamReader.ReadToEnd();
return jsonReturn;
}
}
This is not a solution, but just an alternative:
These days i almost only use WebClient instead of HttpWebRequest. Especially WebClient.UploadString for POST and PUT and WebClient.DownloadString. These simply take and return strings. This way i don't have to deal with streams objects, except when i get a WebException. i can also set the content type with WebClient.Headers["Content-type"] if necessary. The using statement also makes life easier by calling Dispose for me.
Rarely for performance, i set System.Net.ServicePointManager.DefaultConnectionLimit high and instead use HttpClient with it's Async methods for simultaneous calls.
This is how i would do it now
string GetTradesOnline(Int64 tid)
{
using (var wc = new WebClient())
{
return wc.DownloadString("https://data.mtgox.com/api/1/BTCUSD/trades?since=" + tid.ToString());
}
}
2 more POST examples
// POST
string SubmitData(string data)
{
string response;
using (var wc = new WebClient())
{
wc.Headers["Content-type"] = "text/plain";
response = wc.UploadString("https://data.mtgox.com/api/1/BTCUSD/trades", "POST", data);
}
return response;
}
// POST: easily url encode multiple parameters
string SubmitForm(string project, string subject, string sender, string message)
{
// url encoded query
NameValueCollection query = HttpUtility.ParseQueryString(string.Empty);
query.Add("project", project);
query.Add("subject", subject);
// url encoded data
NameValueCollection data = HttpUtility.ParseQueryString(string.Empty);
data.Add("sender", sender);
data.Add("message", message);
string response;
using (var wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
response = wc.UploadString( "https://data.mtgox.com/api/1/BTCUSD/trades?"+query.ToString()
, WebRequestMethods.Http.Post
, data.ToString()
);
}
return response;
}
Error handling
try
{
Console.WriteLine(GetTradesOnline(0));
string data = File.ReadAllText(#"C:\mydata.txt");
Console.WriteLine(SubmitData(data));
Console.WriteLine(SubmitForm("The Big Project", "Progress", "John Smith", "almost done"));
}
catch (WebException ex)
{
string msg;
if (ex.Response != null)
{
// read response HTTP body
using (var sr = new StreamReader(ex.Response.GetResponseStream())) msg = sr.ReadToEnd();
}
else
{
msg = ex.Message;
}
Log(msg);
}
For what it's worth, I was experiencing the same issues with timeouts every time I used it, even though calls went through to the server I was calling. The problem in my case was that I had Expect set to application/json, when that wasn't what the server was returning.
I have a REST web service written in jRuby with entry point http://localhost:4567/v4/start.htm
The web service downloads data from SQL server and sends it to a client.
How do I use C# and httpWebrequest to access the functions provided by the web service.
Thank you
Generally speaking you're going to do something like this:
HttpWebRequest Request = WebRequest.Create(Url) as HttpWebRequest;
Request.Method = "GET"; //Or PUT, DELETE, POST
Request.ContentType = "application/x-www-form-urlencoded";
using (HttpWebResponse Response = Request.GetResponse() as HttpWebResponse)
{
if (Response.StatusCode != HttpStatusCode.OK)
throw new Exception("The request did not complete successfully and returned status code " + Response.StatusCode);
using (StreamReader Reader = new StreamReader(Response.GetResponseStream()))
{
string ReturnedData=Reader.ReadToEnd();
}
}
I haven't mixed RoR and C# yet (let alone jRuby), but it should be just a basic modification of the above.
This is driving me a bit nuts. I am trying to do something quite simple, and I have done it many times before. Just trying to call a REST API.
I am trying to call GetMessage with endpoint = "http://feed.linksynergy.com/productsearch?token=717f8c8511725ea26fd5c3651f32ab187d8db9f4b208be781c292585400e682d&keyword=DVD", and it keeps returning empty string. If I pass it any other valid URL, it will work. But if I just copy and paste the original URL into the web browser, it returns fine!
Can any smart developer tell me what's going on?
Code below. Thanks in advance.
James
public string GetMessage(string endPoint)
{
HttpWebRequest request = CreateWebRequest(endPoint);
using (var response = (HttpWebResponse)request.GetResponse())
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
string message = String.Format("POST failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grab the response
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
}
private HttpWebRequest CreateWebRequest(string endPoint)
{
var request = (HttpWebRequest)WebRequest.Create(endPoint);
request.Method = "GET";
request.ContentLength = 0;
request.ContentType = "text/xml";
return request;
}
Not sure why your setting ContentLength/ContentType - that is generally for HTTP POST, where there is a request body for which you write data to via a stream.
This is a HTTP GET, so there is no request body. (just URI w/ query string)
This should work:
using System;
using System.IO;
using System.Net;
using System.Text;
// Create the web request
HttpWebRequest request = WebRequest.Create("http://www.someapi.com/") as HttpWebRequest;
// Get response
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Console application output
Console.WriteLine(reader.ReadToEnd());
}
EDIT
#Gabe is also quite right - try this on another computer, that is isn't behind any kind of firewall/proxy server.
My work PC was behind a proxy server, so in order to make REST-based HTTP calls, i needed to do this:
var proxyObject = new System.Net.WebProxy("http://myDomain:8080/", true);
System.Net.WebRequest req = System.Net.WebRequest.Create("http://www.someapi.com/");
req.Proxy = proxyObject;
proxyObject.Credentials = New System.Net.NetworkCredential("domain\username","password")