I have created my own silverlight API to get/set data from/to MailChimp.
It was working fine, but today I am getting an error. Example code is :
string MailChimpURL = "https://us2.api.mailchimp.com/1.3/?method=lists&apikey=my_api_key-us2";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(MailChimpURL));
request.BeginGetResponse(new AsyncCallback(ReadCallback), request);
private void ReadCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
using (StreamReader streamReader1 = new StreamReader(response.GetResponseStream()))
{
string resultString = streamReader1.ReadToEnd();
}
}
This works fine with http but gives error when using https.
The error which https is for yesterday. Months back it was working fine for both http and https. Now its only working for http.
Is this a problem in my code or this from MailChimp.
I don't think you are showing us the true exception. The exception you are seeing when inspecting the AsyncWaitHandle property you will always get when debugging because Siverlight does not support that property.
You really need to place some error handling in your ReadCallBack so you can report back to the UI in a friendly way anything that may have gone wrong.
Related
I used the following code to call a web service written in C# and hosted in IIS, but it returns an error
Remote server returned an error: (405) Method not enabled
But when I use Postman with the same input info, it works fine.
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url_to_post);
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.KeepAlive = true;
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(json_object);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
// return result;
}
First of all, please capture the request fiddler and check its response server.
We need to figure out where the 405 come from. If the response server is HTTP API/2.0 then it must come from http.sys. You may need to check your request URL.
However, if the response server is IIS. Then please enable failed request tracing.
Most of time, IIS will return 405 error because either IIS use the wrong handler or your correct handler didn't allow POST method.
So please enable failed request tracing and check what module/handler is returning 405 error.
https://learn.microsoft.com/en-us/iis/troubleshoot/using-failed-request-tracing/troubleshooting-failed-requests-using-tracing-in-iis
Please ensure WebDAV handler is not handling the request. And Static content feature has been installed. You need to ensure correct handler is handling the request and the handler also allow the POST method.
Scenario
Win10 x64
VS2013
I'm trying to make a WebRequest, but I'm getting the following error:
The underlying connection was closed: An unexpected error occurred on a send.
Digging into the inner exception, I got:
"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."
The code which does the request is the following:
private static Hashtable exec (String method, String uri, Object data, String contentType) {
Hashtable response;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create (API_BASE_URL + uri);
request.UserAgent = "MercadoPago .NET SDK v"+MP.version; //version resolves to 0.3.4
request.Accept = MIME_JSON; // application/json
request.Method = method; //GET
request.ContentType = contentType; //application/json
setData (request, data, contentType); //setData in this case does nothing.
String responseBody = null;
try {
HttpWebResponse apiResult = (HttpWebResponse)request.GetResponse (); //Error throws here
responseBody = new StreamReader (apiResult.GetResponseStream ()).ReadToEnd ();
response = new Hashtable();
response["status"] = (int) apiResult.StatusCode;
response["response"] = JSON.JsonDecode(responseBody);
} catch (WebException e) {
Console.WriteLine (e.Message);
}
}
What i've already done:
Made the request via Console Application and MVC Application controller. Both throws the same exception
Called the API via Postman with the exact same headers, which brings me the content correctly.
Those requests were working okay via c# about 4 days ago and I suddenly started having issues, but considering the fact that it responds okay for Postman, I can't figure out where's the problem.
Here's Postman's response
EDIT: Did both requests with Fiddler listening. The result for Postman shows a direct request to the API with HTTPS. When trying with my ConsoleApplication, it shows a HTTP request, which makes a tunnel to the API endpoint, port 443.
The TextView from Fiddler for the tunnel request says the following:
I noticed the "time" field which refers to a very old date, but i don't know what does it mean.
It is kind of bad practice to enable Tls12 like this-
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
In future, if you'd need to use higher version of TLS, you'll have to update your code.
If you are using an older version of .NET, you can simply switch it higher version in which Tls12 is enabled by default.
For example, this simple change in your web.config will enable Tls12 automatically-
<httpRuntime targetFramework="4.6.1"/>
You can try the code below:
string url = ""; // url of the endpoint
WebClient client = new WebClient();
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
client.Encoding = Encoding.UTF8;
client.Headers.Add("content-type", "application/json"); // same as other parameters in the header
var data = client.DownloadString(url);
Figured it out. I needed to include the use of TLS1.2.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
(As a reference for others who have the same issue)this also might be the result of a Double Hop issue , where you should pass the credited user along(in the pool) to the passing server or from one Environment to the other , otherwise the user is set to "ANONYMOUS/USER" and you will get a "An existing connection was forcibly closed by the remote host." Error
i found same error, just mention
request.UserAgent = "anything u want";
I was asked in my internship to post create a form that submit information to a server, now I am to submit that form programmatically as many times as possible to test the site and try to see if it would break by receiving so much data at once. Am a newbie and I tried search how to do it but am still not getting it. This is what I tried.
namespace project_1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
WebRequest req = WebRequest.Create("http://localhost:68644/project-2");
string postData = "item1=11111&item2=22222&Item3=33333";
byte[] send = Encoding.Default.GetBytes(postData);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = send.Length;
Stream sout = req.GetRequestStream();
sout.Write(send, 0, send.Length);
sout.Flush();
sout.Close();
WebResponse res = req.GetResponse();
StreamReader sr = new StreamReader(res.GetResponseStream());
string returnvalue = sr.ReadToEnd();
}
}
}
p.s I got this idea from: How do you programmatically fill in a form and 'POST' a web page?
But I keep getting this error message: "The request was aborted: The operation has timed out"
Thanks for your anticipated help.
Ok I think you are misunderstanding what is going on when you request a page from asp.net or any other http server.
First the client requests a page using HTTP. Usually this is the initial GET request for the page like /MyForm.aspx made from a browser
Then the c# code get executed on the server. This creates the html page.
The client most likely browser gets the page that the server created and renders the html, JavaScript, css... This is done on the client machine this machine can't run c# if you are making a request from the browser.
Then the client fills in the fields in the form and once the submit button is pressed the browser sends another HTTP request from the client to the server now using the POST method. POST method is different then GET because it's intended to have a body section of HTTP. Inside that body portion you have your form data. Usualy the data is formatted as x-www-form-urlencoded string.
Then the server runs the server code for post.
Best way to see what is going on there is to use Fiddler it's an http proxy intended to show you http requests.
What your code is doing right now is creating the post request of the whole process. And the c# code works fine on this side. The error you are getting is related to what ever is running on project-2 since there is no response from the server.
This can be caused but many things (bad proxy setup, long running code on the server, dns issues...)
BUT most well written servers will prevent you from doing this by design. It's a security issue and should not be simple to do this. So you might be getting no response by design.
I am working on a client that uses a webservice to get some events pushed its way - the webservice is designed so, that upon the client POST'ing a subscribe command, it will send back some events of interest and keep doing so as long as the client stay connected.
When POSTing the command, the service responds (immediately) with an initial answer with these headers
Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked
and then keeps the connection open until it times out (after 30s, if the client does not send some keep-alive data)
Since it is a mix of POST + having to read the response + keeping the connection open until endOFStream, it appears I have to use HttpWebRequest with BeginGetRequestStream (to POST) and BeginGetResponse to read and act on the response.
My problem is that the BeginGetResponse callback is not called until the input stream is actually closed by the server/service (after 30s), despite AllowReadStreamBuffering being set to false.
The doc have this to say on AllowReadStreamBuffering:
The AllowReadStreamBuffering property affects when the callback from BeginGetResponse method is called. When the AllowReadStreamBuffering property is true, the callback is raised once the entire stream has been downloaded into memory. When the AllowReadStreamBuffering property is false, the callback is raised as soon as the stream is available for reading which may be before all data has arrived.
I've seen a few suggestions that no matter what AllowReadStreamBuffering is set to, HttpWebRequest will not call BeginGetResponse until it's buffer is filled up - but I have not been able to find anything on that in the docs.
Does any one have an idea on how to control this buffering behaviour or maybe suggestion to another approach I should try when dealing with this kind of webservice?
The relevant snippets of the code I currently use, look like this:
public void open()
{
string url = "http://funplaceontheinternet/webservice";
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "POST";
request.Credentials = new NetworkCredential("username", "password");
request.CookieContainer = new CookieContainer();
request.AllowReadStreamBuffering = false;
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
}
void GetRequestStreamCallback(IAsyncResult result)
{
Debug.WriteLine("open.GetRequestStreamCallback");
HttpWebRequest webRequest = (HttpWebRequest)result.AsyncState;
// End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(result);
// Create the post data
byte[] byteArray = Encoding.UTF8.GetBytes(_xmlEncodedSubscribeCommand);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(BeginGetResponseCallback), webRequest);
}
void BeginGetResponseCallback(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = null;
if (request != null)
response = (HttpWebResponse)request.EndGetResponse(result);
else
Debug.WriteLine("request==null :-(");
if (response != null)
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
Debug.WriteLine("BeginGetResponseCallback - received: " + line);
}
Debug.WriteLine("BeginGetResponseCallback - reader.EndOfStream");
}
}
else
Debug.WriteLine("response==null :-(");
}
You've mentioned that the service is a web service, but not which platform.
If this is a "normal" web service, then I assume that XML is the transport format.
If so, I suspect the problem may be that this style of communication does not really lend itself to streaming. The web service infrastructure at the server end might not be creating the SOAP envelope and payload until all the data is available. If you wanted to stream like this, you might be better using some custom service at the server end, rather than a web service.
Do you know for sure that the server is really streaming the response? (e.g confirmed with something like wireshark?)
If you really want to use a web service, then I would suggest you complete the request when the first event(s) are available, and don't wait for the timeout. This will still achieve the latency reduction that I assume you are trying to get.
I'm having a lot of problems calling a Java based Google App Engine server from a C# client
This is how my client code looks like:
// C# Client
static void Main(string[] args)
{
const string URL = "http://localhost:8888/googlewebapptest7/greet";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "text/x-gwt-rpc; charset=utf-8";
string content = "<?xml version='1.0'?><methodCall><methodName>greetServlet.GetName</methodName><params></params></methodCall>";
byte[] contentBytes = UTF8Encoding.UTF8.GetBytes(content);
request.ContentLength = contentBytes.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(contentBytes, 0, contentBytes.Length);
}
// get response
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
string res = new StreamReader(responseStream).ReadToEnd();
Console.WriteLine("response from server:");
Console.WriteLine(res);
Console.ReadKey();
}
The server is basically the Google default web project with an additional method:
public String GetName()
{
return "HI!";
}
added to GreetingServiceImpl.
Everytime I run my client, I get the following exception from the server:
An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh button on your browser. ( Malformed or old RPC message received - expecting version 5 )
I would like to keep it in plain HTTP requests.
Any idea what's going on?
As Nick pointed out you're trying to emulate GWT's RPC format. I tried that too :)
Then I took different approach. I used Google Protocol Buffers as encoder/decoder over HTTP(S).
One of my projects is desktop application written in C#. Server-side is also C#.Net. Naturally we use WCF as transport.
You can plug-in Protocol Buffers into WCF transport. You'll have same interface configuration both for C# client and Java server. It's very convenient.
I'll update this answer with code-samples when I'm less busy with work.
I never found a good way to use XML based RPC on the Google App Engine. Instead i found this excellent JSON library with tutorial:
http://werxltd.com/wp/portfolio/json-rpc/simple-java-json-rpc/
it works very well!