Delegates And WCF Methods
I have successfully designed a large file upload method using WCF. Now, I would like to report progress for each unique file being loaded. In my upload method, i have the following code block:
while ((bytesRead = request.FileByteStream.Read(buffer, 0, bufferSize)) > 0)
{
outfile.Write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
if (this.ProgressChanged != null)
this.ProgressChanged(this, new ProgressArgs(totalBytesRead, request.FileByteStream.Length));
}
Which uses the deleget ProgressEventHandler as declared below:
public delegate void ProgressEventHandler(object sender, ProgressArgs e);
public event ProgressEventHandler ProgressChanged;
I do not use delegates all that much (but am trying to learn) and got this far by
following examples online. The class ProgressArgs was missing from the example but
I am guessing that is where the calculation takes place and is returned? Something
like: return Convert.ToInt32((totalBytesRead * 100) / fileSize)
?
开发者_如何学CSo, my questions are thus:
1) Assming I have declared and called my ProgressChanged event correctly, what do I do with ProgressArgs?
2) How do I report progress back to the client? My WCF method call currently has a 'void' return type:upload.UploadFile(fileinfo, m_objFile.InputStream);
Will I need to fire a simultaneous JavaScript method that calls a WCF JSON method or something of that nature? A detailed explanation of how to view progress from the client would be seriously appreciated.
Thanks!
PS - I am using ASP.NET 2.0 / Framework 3.5 / C# / and I am self-hosting currently.
Wow, you're asking about a lot of different layers in one question.
Callbacks, not events
You're trying to do something that is .NET specific and does not map to web service programming directly. You cannot use events/delegates in web services. Instead you must define what is called a "callback contract". This is another interface that has methods on it that represent the notifications you want to tell the caller about and is applied to your service contract like so:
public interface MyCallbackContract
{
void ProgressChanged(float percentComplete);
}
[ServiceContract(CallbackContract = typeof(MyCallbackContract)]
public interface MyServiceContract
{
void UploadFile(Stream stream);
}
Now, callback contracts require two way (duplex) communication, so if you're just using basicHttpBinding
now, you would need to switch to use wsDualHttpBinding
or some non-http binding altogether which blows interop for this service out of the water. Assuming your service is entirely intranet, then this shouldn't be a showstopper.
There's a lot more to learn about the callback programming model which I won't go into here. Instead I will refer you to an awesome MSDN article by Juval Lowey which covers the subject in great detail.
How's this help me in the browser?
The second part of your question is how can you get this information from the browser and, well, first we have to accept that there's definitely no way it's communicating with the afforementioned service directly. Instead you will need to build an AJAX "bridge" service. Since the browser is pure HTTP here, you have to do file uploads using a POST to a REST based WCF service. If you wanted to simultaneously retrieve status about that upload you would then have to make polling requests to get status.
Honestly this is one of those places where the browser still just sucks as a platform. The browser knows how much data it has sent, you should be able to report progress just based on that, but it's not exposed anywhere. This is why people turn to using a Flash based upload utility because Flash does expose these details and so you don't need to poll the server to get progress.
精彩评论