Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET error when calling System.Net.WebClient.UploadFileAsync

I am working with the System.Net.WebClient class, and I am attempting to upload a file using the UploadFileAsync method. I am using Visual Studio 2010, and all of my projects are set to use the .NET 4.0 standard runtime, not the client library.

Below is a small section of the code that I am using. About 90% of the time I get the following error:

Unable to cast object of type 'System.ComponentModel.AsyncOperation' to type 'UploadBitsState'.

Stack Trace:
 at System.Net.WebClient.UploadFileAsyncWriteCallback(Byte[] returnBytes, Exception exception, Object state)
 at System.Net.WebClient.UploadFileAsync(Uri address, String method, String fileName,   Object userToken)
 at FileUpload._StartUpload()

The FTP servers I am attempting to upload to are internal to my organization, but one is running IPSwitches WS-FTP and the other is running an IIS 6.0 FTP site, and I have experienced the same issue with both servers.

I have searched high and low for others with a similar problem to no avail.

The actual line that the exception occurs on is the _Client.UploadFileAsync method call.

private void _StartUpload()
{
    try
    {
        _Client = new WebClient
        {
            Credentials = _Credentials
        };
        _Client.UploadProgressChanged += ProgressChanged;
        _Client.UploadFileCompleted += UploadCompleted;
        _Client.UploadFileAsync(FileBeingUploaded, "STOR", _LocalFile, null);
    }
    catch (Exception exception)
    {
        // Methods calls removed for brevity
    }
}

private void UploadCompleted(Object sender, UploadFileCompletedEventArgs e)
{
    // Methods calls removed for brevity
}

private void ProgressChanged(object sender, UploadProgressChangedEventArgs e)
{
    // Methods calls removed for brevity
}
like image 741
Dale Couch Avatar asked Jun 14 '11 19:06

Dale Couch


1 Answers

This is kind of interesting. Looking at the reference source (WebClient.cs), the first line of UploadFileAsyncWriteCallback casts the state parameter to UploadBitsState.

In the method UploadFileAsync, there's some exception handling code that reads:

catch (Exception e)
{
    if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
    { 
        throw; 
    }
    if(fs != null){ 
        fs.Close();
    }
    if (!(e is WebException || e is SecurityException)) {
        e = new WebException(SR.GetString(SR.net_webclient), e); 
    }
    UploadFileAsyncWriteCallback(null, e, asyncOp); 
}

asyncOp is of type AsyncOperation.

It looks like the call to UploadFileAsyncWriteCallback here is a bug, because it's passing an object of the wrong type to the callback. The callback does a C-style cast (i.e. UploadBitsState uploadState = (UploadBitsState)state;).

But that will only happen if something triggers an exception during the upload.

Is it possible that something in your ProgressChanged or UploadCompleted event handlers is throwing an exception? Either that or one of the parameters you pass to UploadFileAsync is invalid.

More info

It really does look like there's a bug in UploadFileAsync. For example, the following throws InvalidCastException, when according to the documentation it should throw WebException.

var targetUri = new Uri("ftp://example.com/file.txt");
var srcFile = string.Empty;  // documentation says this will throw WebException
var client = new WebClient();
client.UploadFileAsync(targetUri, "STOR", srcFile, null);

I've reported the bug at https://connect.microsoft.com/VisualStudio/feedback/details/675575/webclient-uploadfileasync-throws-invalidcastexception

However, from the looks of things I'd say that the reason an exception is being thrown lies in your code. Unfortunately, it's impossible to say where, because UploadFileAsync is losing the exception information. Perhaps, as somebody else pointed out, trying a synchronous upload will shed more light on the subject.

like image 186
Jim Mischel Avatar answered Sep 27 '22 22:09

Jim Mischel