tags:

views:

116

answers:

2

I have a lot of trouble with the internet connectivity in the program I am working on and it all seems to spawn from some issue with the proxy settings. Most of the issues at this point are fixed, but the issue I am having now is that my method of testing the proxy settings makes some users wait for long periods of time.

Here is what I do:

System.Net.WebClient webClnt = new System.Net.WebClient();

webClnt.Proxy = proxy;
webClnt.Credentials = proxy.Credentials;

byte[] tempBytes;
try
{
    tempBytes = webClnt.DownloadData(url.Address);
}
catch
{
    //Invalid proxy settings

    //Code to handle the exception goes here
}

This is the only way that I've found to test if the proxy settings are correct. I tried making a web service call to our web service, but no proxy settings are needed when making the call. It will work even if I have bogus proxy settings. The above method, though, has no timeout member that I can set that I can find and I use the DownloadData as opposed to the DownloadDataAsync because I need to wait til the method is done so that I can know if the settings are correct before continuing on in the program.

Any suggestions on a better method or a work around for this method is appreciated.

Mike

EDIT: I tried something else, but no luck. I used the DownloadDataAsync method to download the data in a separate thread which raises the DownloadDataCompleted event of the WebClient when finished. While I wait for the event to get called I have a loop: while(DateTime.Now < downloadStart.AddMinutes(timeout) && !TestIsDone) {} The DownloadDataCompleted event sets the TestIsDone member to true when the event is called. The problem here is if the proxy settings are bad the Event never gets called, no exception is thrown, and the program waits for the entire timeout period before continuing. Here is the code for this approach:

public static bool TestProxy(System.Net.WebProxy proxy)
{
    ProxySettingsTestDone = false; //public static var
    string address = //url to some arbitrary data on our server

    System.Net.WebClient webClnt = new System.Net.WebClient();

    webClnt.Proxy = proxy;
    webClnt.Credentials = proxy.Credentials;

    try
    {
        webClnt.DownloadDataCompleted += new System.Net.DownloadDataCompletedEventHandler(DownloadDataCallback);
        webClnt.DownloadDataAsync(new Uri(address));

        //Timeout period
        DateTime dnldStartTime = DateTime.Now;
        while (DateTime.Now < dnldStartTime.AddMinutes(1.0) && !ProxySettingsTestDone)
        { }

        if (!ProxySettingsTestDone) //Exceded timeout
        {
            throw new System.Net.WebException("Invalid Proxy Settings");
        }
    }
    catch (System.Net.WebException e)
    {
        if (e.Status == System.Net.WebExceptionStatus.ProxyNameResolutionFailure)
        {
            //Proxy failed, server may or may not be there
            Util.ConnectivityErrorMsg = e.Message;
            return false;
        }
        else if (e.Status == System.Net.WebExceptionStatus.ProtocolError)
        {
            //File not found, server is down, but proxy settings succeded
            ServerUp = false;
            Util.ConnectivityErrorMsg = e.Message;
            return true;
        }

        return false;
    }

    Util.ConnectivityErrorMsg = "";
    return true;
}

private static void DownloadDataCallback(object sender, System.Net.DownloadDataCompletedEventArgs e)
{
    if (!e.Cancelled && e.Error == null)
        ProxySettingsTestDone = true;
    else
        throw new System.Net.WebException("Invalid Proxy Settings");
}

Sorry about the long post. I wanted to update this question with the information that I found after testing this new approach.

Thanks, Mike

+1  A: 

You can run the proxycheck in a seperate thread. And consider the check to be failed if the thread takes too long.

Or you could use WebRequest, it allows you set a timeout:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://url");
request.Proxy = proxy;
request.Timeout = 2000;

If the request has not finished within the given timeout a WebException with the Status property set to WebExceptionStatus.Timeout will be thrown.

CSmooth.net
I wound up using this separate thread method and it works, but it seems like such a kludge fix. Once I get the time and opportunity I will try the other method which looks a lot better. Thanks.
Mike Webb
A: 

Every method mentioned here are valid. But the most important one is to test the Proxy connection using the same Windows user account for the process that you want to test. Many proxies has specific privileges for each Windows user.