Page 1 of 1

Working with proxy servers Get your internet app's working with them

#1 danny_kay1710  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 28
  • View blog
  • Posts: 358
  • Joined: 27-April 08

Posted 08 March 2010 - 05:00 AM

Recently, I have tried to create a web service for software licensing and discovered that proxy server's can be a bit of a nightmare. There is information out there but it is scattered around and it can take some time to bring it all together and get a working solution.

For that reason I have decided to turn my working solution into a small tutorial on how to work with proxy servers.

using System.Net;

Firstly I am only going to cover detecting proxy settings for IE and authenticating to that proxy. Some other browsers also use these settings e.g. Chrome (Firefox doesn't however, it has it's own independent settings)

The framework is clever and will use IE's proxy settings automatically (these settings are in WebRequest.DefaultWebProxy) however it is only so clever. If proxy authentication is not enabled then you will never have a problem connecting to the internet through C#, but if it is it won't ask for a username and password automatically like IE, it will just error and vaguely tell you that a username and password is required.

Also it is important to note that IE supports NTLM integration which when used with a compatible proxy server (e.g. ISA server) will seamlessly use your Windows credentials to authenticate with. This means it doesn't look like your proxy needs a username and password but it really does.

Step One
So, firstly, how do you know in C# when the users internet connection goes through a proxy server?
if (WebRequest.DefaultWebProxy.GetProxy(new System.Uri("http://www.example.com")).ToString() == "http://www.example.com/") {
    // A proxy is not in use here
} else {
    // A proxy is in use
}



Let's dissect that code a little. The function WebRequest.DefaultWebProxy.GetProxy takes one parameter of type Uri called destination address. The destination address should be what you want to connect to - that way if there is a proxy in use it can tell you what the proxy server address is that allowed you to connect to that site.

The function then returns a Uri. If the Uri address is the same as the destination Uri you passed earlier then you are NOT using a proxy. If it is different it returns the proxy it used. NOTE: the Uri returned with include a trailing "/" even if your passed one didn't (like mine above)!

Step Two
How do we find out if authentication is required? Well, unfortunately the best way I found was to attempt to connect to the internet.

// Check to see if authentication is required
WebClient wc = new WebClient();
bool AuthRequired = false;	

try {
	wc.OpenRead("http://www.example.com/default.aspx");
} catch (WebException wx) {
	if (((HttpWebResponse)wx.Response).StatusCode == 407)
		AuthRequired = true;
}



In the above example we made a WebClient object and attempted to read a page from our website. If there is no authentication required that will succeed and the boolean var AuthRequired will indicate this to us later in the code.

However if it fails we need to check for HTTP Status Code 407. To do this we must catch all WebExceptions. To check for status code you must first convert wx.Response to a HttpWebResponse object and check the StatusCode property

Step Three
Great! We know we need authentication, what do we do now?

Well we have two options, we can prompt user for username and password right now, or we can allow for NTLM authentication for seamless authentication. After all many users using NTLM will not be aware they need a username and password to connect to the internet.

Assuming you are still in the correct scope for wc and AuthRequired to be accessible take a look at the below:

if (AuthRequired)
{
    // Try default credentials (e.g. for ISA with NTLM integration)
    WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
    AuthRequired=false;	// Assume this will allow us to connect for now
    // Code continues below



The above sets the Credentials of the DefaultWebProxy to what is known as the Default Credentials (your windows login generally).

We then also set the authRequired to false, assuming that this will allow us to connect to the internet until we perform another check.

    try {
    	wc.OpenRead("http://www.example.com/default.aspx");	    			
    } catch (WebException wx) {
	if (((HttpWebResponse)wx.Response).StatusCode == 407)
		AuthRequired = true;		    		
    }
} // End of If statement above



So we use the exact same code as before to do another connection test. Since wc automatically uses the DefaultProxy object altering the credentials for the DefaultProxy alters the credentials in use for the WebClient.

If the authentication fails we return status code 407 again which signals it isn't integrated with your Windows Login

Step Four
So what's next. We still can't connect but we now know the proxy requires authentication and it isn't using NTLM.

We now need to prompt the user asking for their credentials. If these conditions are met at this stage it is likely the user will be aware of the need of a username and password to connect to the internet.

I am not going to cover creating a method for getting these details from the user, just how to connect once you have them

if (AuthRequired)
{
	//TODO: Request Credentials here
	WebRequest.DefaultWebProxy.Credentials = new NetworkCredential("user", "pass");// Set the credentials here
	AuthRequired=false; // Assume this will allow us to connect for now

	try {
		wc.OpenRead("http://www.example.com/default.aspx");	    			
	} catch (WebException wx) {
    	    if (((HttpWebResponse)wx.Response).StatusCode == 407)
    		AuthRequired = true;	
    	    // TODO: Username and password is incorrect. Implement a loop or goto no internet connection screen
	}
}	   	



Again very similar to above code however this time we create a new NetworkCredential object passing the username and password to it's constructor and we assign this to the WebRequest.DefaultWebProxy.Credentials property.

I hope this helps anyone trying to implement proxy support, please feel free to leave any questions!!

Is This A Good Question/Topic? 2
  • +

Replies To: Working with proxy servers

#2 vacko  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 1
  • Joined: 07-November 13

Posted 07 November 2013 - 02:07 AM

Hi, two issues:
1) in my case StatusCode == 407 can't be used, becasue of error Operator '==' cannot be applied to operands of type 'System.Net.HttpStatusCode' and 'int'. Had to use StatusCode == httpStatusCode.ProxyAuthenticationRequired.
2) if user set bad proxy server address inside IE, exception happen due to System.NullReferenceException was unhandled (on line where StatusCode is used).
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1