How to AutoDetect/Use IE proxy settings in .net HttpWebRequest - c#

Is it possible to detect/reuse those settings ?
How ?
The exception i'm getting is
This is the exception while connecting to http://www.google.com
System.Net.WebException: Unable to connect to the remote server --->
System.Net.Sockets.SocketException: A connection attempt failed because the
connected party did not properly respond after a period of time, or established
connection failed because connected host has failed to respond 66.102.1.99:80
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot,
SocketAddress socketAddress)
at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,
Socket s4, Socket s6, Socket& socket, IPAddress& address,
ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout,
Exception& exception)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.GetResponse()
at mvcTest.MvcApplication.Application_Start() in
C:\\home\\test\\Application1\\Application1\\Program.cs:line 33"

HttpWebRequest will actually use the IE proxy settings by default.
If you don't want to use them, you have to specifically override the .Proxy proprty to either null (no proxy), or the proxy settings of you choice.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://news.bbc.co.uk");
//request.Proxy = null; // uncomment this to bypass the default (IE) proxy settings
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.WriteLine("Done - press return");
Console.ReadLine();

I was getting a very similar situation where the HttpWebRequest wasn't picking up the correct proxy details by default and setting the UseDefaultCredentials didn't work either. Forcing the settings in code however worked a treat:
IWebProxy proxy = myWebRequest.Proxy;
if (proxy != null) {
string proxyuri = proxy.GetProxy(myWebRequest.RequestUri).ToString();
myWebRequest.UseDefaultCredentials = true;
myWebRequest.Proxy = new WebProxy(proxyuri, false);
myWebRequest.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
}
and because this uses the default credentials it should not ask the user for their details.
Note that this is a duplicate of my answer posted here for a very similar problem: Proxy Basic Authentication in C#: HTTP 407 error

For people having problems with getting this to play nice with ISA server, you might try to set up proxy in the following manner:
IWebProxy webProxy = WebRequest.DefaultWebProxy;
webProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
myRequest.Proxy = webProxy;

This happens by default, if WebRequest.Proxy is not set explicitly (by default it's set to WebRequest.DefaultWebProxy).

Related

ASP.NET receives post data issue

I used ASP.NET to write a web page that accesses other websites to log in to the API, and it was successfully placed on my server, but when it was placed on the school's server to receive the token from the post, the following error was reported:
Server Error in '/classMeeting' Application. A connection attempt failed because the connecting party did not properly reply after a period of time or the connected host became unresponsive. 112.65.235.59:443
Description: An unhandled exception occurred during the execution of the current web request.
Please review the stack trace for more information about the error and where it originated in the code.
Exception Details:
System.Net.Sockets.SocketException:
A connection attempt failed because the connected party did not properly reply after a period of time or the connected host became unresponsive. 112.65.235.59:443
Source Error:
An unhandled exception was generated during the execution of the current webrequest. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) +309
System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) +633
System.Net.HttpWebRequest.GetRequestStream(TransportContext& context) +708
System.Net.HttpWebRequest.GetRequestStream() +21
classMeeting.index.GetAccess_token(String code, String client_id, String redirect_uri, String client_secret) in C:\Users\admin\source\repos\classMeeting\index.aspx.cs:130 classMeeting.index.readyLogin() in C:\Users\admin\source\repos\classMeeting\index.aspx.cs:32
classMeeting.index.Page_Load(Object sender, EventArgs e) in C:\Users\admin\source\repos\classMeeting\index.aspx.cs:25
System.Web.UI.Control.OnLoad(EventArgs e) +109
System.Web.UI.Control.LoadRecursive() +68
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3321
My source code is:
public static string GetAccess_token(string code, string client_id, string redirect_uri, string client_secret)
{
var url = "https://openapi.yiban.cn/oauth/access_token";
byte[] byteArray = Encoding.UTF8.GetBytes(string.Format("client_id={0}&client_secret={1}&code={2}&redirect_uri={3}", client_id, client_secret, code, redirect_uri));
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(url));
webRequest.Method = "Post";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = byteArray.Length;
ServicePointManager.DefaultConnectionLimit = 50;
Stream newStream = webRequest.GetRequestStream();
newStream.Write(byteArray, 0, byteArray.Length);
newStream.Close();
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
StreamReader php = new StreamReader(response.GetResponseStream(), Encoding.Default);
return php.ReadToEnd();
}
How should we do to fix this error?
If you get any error code like 10036 for a socket connection error then you can find the related error section from this link
Check the parameters you use for connection like hostname and port, and also make sure your firewall doesn't drop packages or block your connection.
The code you provided is correct, there are several reasons for this phenomenon:
Check whether the status of the server is abnormal. For example, there may be a state of not starting or being paralyzed.
Whether the status of your destination URL is normal. Whether there is an unreachable state.
Whether your server can access your target website. Due to the server's need for a secure environment, there are usually some URLs that cannot be accessed by the server. At this point you need to change your server port. If it still doesn't work, try sending and receiving web requests to hosts that it can access successfully.

C# HttpClient An existing connection was forcibly closed by the remote host

I'm working on an integration with Alternative Payments using their hosted page integration. Their C# SDK does not have this integration available at the moment, but as you can see it's pretty simple and I made a small class to send the post request and get the JSON response.
I tested the json object I'm sending on PostMan and cURL and both work, also the authentication header, so I think they are not the problem. Here is the constructor of my class:
public AlternativePaymentsCli(string apiSecretKey)
{
this._apiSecretKey = apiSecretKey;
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var authInfo = _apiSecretKey;
authInfo = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:", _apiSecretKey)));
// The two line below because I saw in an answer on stackoverflow.
_httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
_httpClient.DefaultRequestHeaders.Add("Keep-Alive", "3600");
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Anything.com custom client v1.0");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
}
And the method where I'm posting the data:
public string CreateHostedPageTransaction(HostedPageRequest req)
{
var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
// I send this same json content on PostMan and it works. The json is not the problem
var content = new StringContent(JsonConvert.SerializeObject(req, settings), Encoding.UTF8, "application/json");
var response = _httpClient.PostAsync(this._baseUrl + "/transactions/hosted", content).Result;
var responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
return responseText;
return "";
}
Then I get this error: An existing connection was forcibly closed by the remote host, at the PostAsync line. This is the error details:
[SocketException (0x2746): An existing connection was forcibly closed by the remote host]
System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) +8192811
System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult) +47
[IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.]
System.Net.TlsStream.EndWrite(IAsyncResult asyncResult) +294
System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar) +149
[WebException: The underlying connection was closed: An unexpected error occurred on a send.]
System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) +324
System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) +137
[HttpRequestException: An error occurred while sending the request.]
I'm using C# 4.5, Asp.Net MVC. I've been reading answers for the same error and none of them solved my issue so far. What am I missing in this code?
Thanks for any help
I don't see in your code sample where you are setting the value of _baseUrl, but I'm assuming that is being done somewhere. I'm also assuming that since this related to payments, the URL is HTTPS. If the remote host has disabled TLS 1.0 and your connection is coming in as TLS 1.0, it could cause that behavior. I know C# 4.6 has TLS 1.0/1.1/1.2 support enabled by default, but I think C# 4.6 still defaults to only SSL3/TLS 1.0 even though TLS 1.1 and 1.2 are supported. If this is the cause of the issue, you can manually add TLS 1.1 and 1.2 to the enabled values using the following code.
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
If you are using .Net 4.0 then SecurityProtocolType.Tls11 and SecurityProtocolType.Tls2 are not defined so instead you can use the hard coded value below.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
It is possible to solve the issue without any changes in the code, as described in this excellent answer to a similar question:
Retarget the web project to .Net 4.6+, then update web.config as the following:
<system.web>
<compilation targetFramework="4.6" />
<httpRuntime targetFramework="4.6" />
</system.web>
This worked for me, the first line ensures the protocols ssl3 and TLS1.2, and the second line ignores any potential certificate errors (ignore and continue - like expired certs.):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
For me this error was caused by forgetting to configure the proxy server.
Using the following code to construct the HttpClient solved it for my .NET 4.7.2 application:
var httpClientHandler = new HttpClientHandler { Proxy = WebRequest.GetSystemWebProxy() };
var httpClient = new HttpClient(httpClientHandler);
Hope this helps someone.

WebClient.DownloadString fails in website, works otherwise

In our MVC 5 site we have a VerifyEmail method that contacts a service to check that an email exists. We do the basic preliminary checks, to make sure it looks like a valid email, etc, then we pass it to the service.
We're using a WebClient.DownloadString() function. When we navigate to the appropriate View and trigger the method, we get these errors:
When debugging:
<h2>Bad Request - Invalid Hostname</h2>
<hr><p>HTTP Error 400. The request hostname is invalid.</p>
When we're not debugging, we get this:
System.Net.WebException: Unable to connect to the remote server --->
System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:63595
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
--- End of inner exception stack trace ---
If I call the method (VerifyEmailOrgEmailVerificationClient.VerifyEmail) from LinqPad it works!!!
I get this:
MX record about emailserver.com exists.<br/>
Connection succeeded to emailserver-com.mail.protection.outlook.com SMTP.<br/>
220 SN1NAM01FT022.mail.protection.outlook.com Microsoft ESMTP MAIL Service ready at Mon, 29 Feb 2016 21:08:50 +0000<br/>
> HELO verify-email.org<br/>
250 SN1NAM01FT022.mail.protection.outlook.com Hello [verify-email.org]<br/>
> MAIL FROM: <check#verify-email.org><br/>
=250 2.1.0 Sender OK<br/>
> RCPT TO: <redacted#emailserver.com><br/>
=250 2.1.5 Recipient OK<br/>
That's what we should get. So, the code works from LinqPad, but not when we call it as a website. We put a test method together and get the same results. With our test, we're just trying to get a response from WebClient.DownloadString(). Even like that we get an error.
Here's our test method:
using System;
using System.IO;
using System.Net;
using System.Web.Mvc;
using PublicationSystem.ViewModels;
namespace TestWebClient.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var newModel = new TestViewModel();
using (var webClient = new WebClient())
{
webClient.Encoding = System.Text.Encoding.UTF8;
webClient.Headers["Content-Type"] = "application/json;charset=UTF-8";
var requestUrl = string.Empty;// GetRequestUrl(email);
try
{
requestUrl =
"http://api.verify-email.org/api.php?usr=igiglobal&pwd=emailsareweak&check=mkenyon#mkptechnologies.com";
newModel.ResponseString = webClient.DownloadString(requestUrl);
}
catch (WebException exception)
{
string responseText;
if (exception.Response != null)
{
using (var reader = new StreamReader(exception.Response.GetResponseStream()))
{
responseText = reader.ReadToEnd();
}
newModel.ResponseString = responseText;
}
else
{
newModel.ResponseString = exception.ToString();
}
}
catch (Exception exception)
{
newModel.ResponseString = exception.ToString();
}
}
return View(newModel);
}
Our AppPool is set for .Net 4.0. The app compiles for .Net 4.5. We're using MVC 5.
Any idea why our method, specifically the WebClient.DownloadString() fails while we're running the site, but works if we call the code from LinqPad?
UPDATE: I created a new MVC project with Visual Studio 2013, just like this project. In the new test project, I pasted the same code, and have tried to get the references to match as exactly as possible. My code works in the test project. So something with the way my project is set up is blocking WebClient.DownloadString(). Using Fiddler, it looks like it doesn't even send the request out.
Is there a setting that could block WebClient.DownloadString() while testing an MVC site?
UPDATE 2: In the web.config I found this. Could this be it?
<system.net>
<defaultProxy>
<proxy proxyaddress="http://localhost:63595/" />
</defaultProxy>
</system.net>
In the web.config I found this. Commenting it out let WebClient.DownloadString() work again. Hope this helps somebody. I'll have to do more research on this.
<system.net>
<defaultProxy>
<proxy proxyaddress="http://localhost:63595/" />
</defaultProxy>
</system.net>

Windows Phone Web Exception 404 not found but server gets requests

As the title says I am trying to run a Windows Phone App which is supposed to communicate with a Restful API(running on localhost). My server is actually getting my Http requests but Visual Studio keeps throwing this error:
"The remote server returned an error: NotFound."
private void connect_tap(object sender, System.Windows.Input.GestureEventArgs e)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.BeginGetResponse(GetResponseCallback, request);
}
void GetResponseCallback(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
if (request != null)
{
WebResponse response = request.EndGetResponse(result);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string read = streamRead.ReadToEnd();
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(read);
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
});
streamResponse.Close();
streamRead.Close();
response.Close();
}
}
This is the full error:
{System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound.
at System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClasse.b__d(Object sendState)
at System.Net.Browser.AsyncHelper.<>c__DisplayClass1.b__0(Object sendState)
--- End of inner exception stack trace ---
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at IonisSphere.Connect.GetResponseCallback(IAsyncResult result)
at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClass1d.b__1b(Object state2)}
The Web Exception occurs at the EndGetResponse() call. I removed the try/catch around to see the error but when it's there it always goes in the catch section and nothing happens.
I don't understand what is it not finding since my server gets my requests ...
It works fine with Postman by the way. I also tried with a POST method but got exactly the same result.
I'm stuck with this since a few days and I couldn't find anyhing helpful on the internet. I am quite new on Windows Phone and I know this is propably a stupid mistake but thanks in advance for the ones who will try to teach me =)

Windows Phone - failing to get a string from a website with login information

I am new to accessing web services with Windows Phone 7/8. I'm using a WebClient to get a string from a php-website. The site returns a JSON string but at the moment I'm just trying to put it into a TextBox as a normal string just to test if the connection works.
The php-page requires an authentication and I think that's where my code is failing. Here's my code:
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("myUsername", "myPassword");
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("https://www.mywebsite.com/ba/php/jsonstuff.php"));
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
try
{
string data = e.Result;
this.jsonText.Text = data;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
This returns first a WebException and then a TargetInvocationException. If I replace the Uri with for example "http://www.google.com/index.html" the jsonText TextBox gets filled with html text from Google (oddly enough, this also works even when the WebClient credentials are still set).
So is the problem in the setting of the credentials? I couldn't find any good results when searching for guides on how to access php-pages with credentials, only without them. Then I found a short mention somewhere to use the WebClient.Credentials property. But should it work some other way?
Update: here's what I can get out of the WebException (sorry for the bad formatting):
System.Net.WebException: The remote server returned an error: NotFound. --->System.Net.WebException: The remote server returned an error: NotFound.
at System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.ClientHttpWebRequest.<>c_DisplayClasse.b_d(Object sendState)
at System.Net.Browser.AsyncHelper.<>c_DisplayClass1.b_0(Object sendState)
--- End of inner exception stack trace ---
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
at System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)
Update 2: Here's the error log line:
Nov 16 17:51:12 myservice httpd[21036]: 127.0.0.1 - - [16/Nov/2012:17:51:12 +0200] "GET /ba/php/jsonstuff.php?origpath=/ba/php/jsonstuff.php HTTP/1.1" 401 290 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"
401 I guess would suggest false credentials?
In my opininion you really need to see how the server handles your request. "NotFound" in WebException could mean that you're referring to a location that doesn't exist. But I'm sure that you pass the right URL. So there must be some logic on the server that redirects you.
If you go to the url using your desktop browser - do you have any kind of SSL certificate error or warning? Maybe that's the reason. Try navigating on your phone using IE.
Or you could set up another host just to give it a try.
I'll set up a host on my machine and try it.
The problem is with the SSL certificate I guess. WP is very strict when it goes to checking SSL certificates, so you should try without ssl or install cert on your emulator/phone or install valid (not self generated) cert on your server.
Okay, so I found a way to get this working. The problem was that the WebClient class couldn't properly handle the cookies of the web service.
After some Google searches I found this solution and it works perfectly:
http://firebelly.net/post/3341374382/cookie-aware-webclient-for-wp7
So basically you just make your own client class that extends the WebClient class which can store cookies.

Categories