My Blog

Author:Philip BeadleCreated:Monday, September 15, 2008 10:40 AM
This blog is more general than my Blog at http://www.dotnetnuke.com/Community/Blogs/tabid/825/Default.aspx. You'll find mostly technical tips and tricks and things i am doing in the MS user group community.

Last year I saw Nikhil Kothari do a session called - Enhancing Ajax Applications with Silverlight.  One of his demos was using the OpenFileDialog and a webservice to transfer chunks of data up to the webserver which I downloaded and worked out how it all fit together.  Now that beta 2 is released I thought I'd update the demo to call the webservice using a Service Reference and the Async event model.

So lets see how it works.

  1. The web page has a single button and a div that works as the progress bar.
  2. The user clicks the button which opens the OpenFileDialog
  3. User selects as many files as they want
  4. The files are sent one at a time by breaking them down into chunks
  5. A chunk is sent through the webservice and then the system waits for the Async Completed event
  6. The async event will then send the next chunk until the file is sent and moves on to the next file.

 Lets see what the code does now:

The aspx page hosts the Silverlight control with a couple of extra parameters than standard.

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/FileUploader.xap"            OnPluginLoaded="onUploaderAvailable"
MinimumVersion="2.0.30523"
Width="0" Height="0" HtmlAccess="Enabled" InitParameters="UploadServiceUrl=http://localhost:7345/ClientBin/Uploader.asmx" />

I want the Silverlight control to be able to interact with the HTML so HtmlAccess is set to true.  I also want to set the location of the service so the InitParameters is set and lastly I want to run some javascript when the Silverlight control has loaded so the OnPluginLoaded event is wired up. 

 Now have a look at the js for the page.

 <script type="text/javascript">

 
    var _uploader;
 
    function onUploaderAvailable(sender, e) {
        slCtl = sender.get_element();
        _uploader = slCtl.Content.uploader;
 
        _uploader.uploadStarting = onUploaderStarting;
        _uploader.uploadCompleted = onUploaderCompleted;
        _uploader.uploadProgress = onUploaderProgress;
    }
 
    function onUploaderCompleted(sender, e) {
        document.getElementById('progressContainer').style.visibility = 'hidden';
    }
 
    function onUploaderProgress(sender, e) {
        document.getElementById('progressLabel').innerHTML = e.fileName;
        var total = e.totalLength;
        var sent = e.sentLength;
 
        var width = Math.ceil(200 * sent / total) + 'px';
        document.getElementById('progressFill').style.width = width;
    }
 
    function onUploaderStarting(sender, e) {
        document.getElementById('progressCountLabel').innerHTML = _uploader.uploadCount;
        document.getElementById('progressContainer').style.visibility = 'visible';
    }
 
    function uploadFiles() {
        _uploader.uploadFiles();
    }
script>

When the Silverlight control has loaded the first method will fire which gets a reference to a custom object called "uploader".  This object is a [ScritableMember] that gets registered with the Page (you'll see that in a minute) that can now be accessed and used by the js on the page.  Now that we have a reference the events on the "Uploader" are wired up to the js methods so that when an event such as UploadStarting fires the UI can be updated.  As you can see there will be no visible XAML component.

[ScriptableMember]
public event UploadEventHandler uploadProgress;
 

 In the Uploader class you can see the [ScriptableMember] marked on the public events and methods that the js needs access to.  In the onUploaderAvailable js event that is fired when the Silverlight plugin is loaded a reference to the Uploader instance is gained and the public events are wired up to the js methods.  the Uploader instance is registered in the load event of the Page.xaml class like so:

_uploader = new Uploader();
HtmlPage.RegisterScriptableObject("uploader", _uploader);
 

 Now that the Html page knows about the uploader and the events have been wired up we can now click the Upload Button which will fire the uploadFiles js method which fires the uploadFiles method on the uploader object.  If you debug the method in the cs file you will see that the js is calling directly into the cs via the scripting bridge that [ScritableMember] creates.

The uploadFiles method spins up an OpenFileDialog which has MultiSelect set to true and the filter set to XML, once the user selects the files they want a list of those files is created to be processed.  You can also see that a new webservice client is created and its Completed event is wired up.

// Create the Service
client = new UploaderSoapClient(binding, addr);
// Register for the Completed Event
client.UploadFileChunkCompleted += new EventHandler<UploadFileChunkCompletedEventArgs>(client_UploadFileChunkCompleted);
 

Since any call to a webservice is Asynchronous a completed event must be wired up to handle the call back, here we define client_UploadFileChunkCompleted to fire when the web service call to UploadFileChunk is done.  To do the call to the web service a ServiceReference was added to the Silverlight project and the binding and end point set up as shown here:

EndpointAddress addr = new EndpointAddress(App.uploaderEndPoint);
BasicHttpBinding binding = new BasicHttpBinding();
UploaderSoapClient client;
 

The uploaderEndPoint was retrieved from the InitParams in App.xaml.cs like so:

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new Page();
    uploaderEndPoint = e.InitParams["UploadServiceUrl"].ToString();
}
 

 The InitParams are set on the Silverlightncontrol like this

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/FileUploader.xap"
OnPluginLoaded="onUploaderAvailable" MinimumVersion="2.0.30523" Width="0"
Height="0" HtmlAccess="Enabled" InitParameters="UploadServiceUrl=http://localhost:7345/ClientBin/Uploader.asmx" />

So now everything is wired up we are ready to upload the files. Enjoy!

You can download this solution here...

I have just posted the slides and code from my ReMIX sessions here.

Building Rich Internet Applications using Microsoft Silverlight 2 - Philip Beadle
Learn how to use Microsoft Visual Studio 2008 to create applications, including how to create UI using XAML markup and code, how to build a custom control, how to retrieve data from a Web service, and how to manipulate data with XML and LINQ.

Read More »

Our 300 year old Chinese Marriage bed is nearly finished being restored. Here's a picture so you can see how its going.

Read More »

Ill be speaking at Code Camp Oz this weekend in Wagga Wagga, check out the details here

http://www.codecampoz.com/

Im very happy to have been reawarded my MVP status again, makes all teh late nights worthwhile.  I also just hit 1000 posts on DotNetNuke.  I have tried to make sure i only post meaningful content and not just ramble or "ditto" peoples posts.

1000 posts on DotNetNuke Forums

Set up my workstation again with all my toys connected together. Now I can work, play records, mix dance tracks and mix in Ableton Live for all my digital mixing as well.

Check it out.

DotNetNuke now has the DNN Forge where anyone can setup a CodePlex project.  The CodePlex team released this blog post http://blogs.msdn.com/codeplex/archive/2008/02/12/codeplex-dotnetnuke-partnership-in-dotnetnuke-forge.aspx about it and you can see all the projects here http://www.dotnetnuke.com/tabid/824/default.aspx

  
DNN Template Maker

Artisteer - Web Design Generator

  
UsersOnline
MembershipMembership:
Latest New UserLatest:andpro
Past 24 HoursPast 24 Hours:0
Prev. 24 HoursPrev. 24 Hours:0
User CountOverall:32

People OnlinePeople Online:
VisitorsVisitors:10
MembersMembers:0
TotalTotal:10

Online NowOnline Now:
  
Talk to me
  
Good Books
My Logos


MVP Logo
From: 2004-2009

Lorraine Young's DNN Site

DotNetNuke Sponsor and Platinum Benefactor logo

 Microsoft ASP.net logo

microsoftcertifiedprofessional.gif

vicnet_logo.gif