Gooddogs Development Blog

WCF Series: Part #7 Offline Data Management using WCF

Feb 13

Written by:
2/13/2011 4:46 PM  RssIcon

In this section of the “DotNetNuke and WCF” series, we will use the WCF service methods we built in Part #6 to do some offline data management. We defined a couple of OperationContracts to enable offline moderation of Repository module uploads. Now, we’ll build a desktop application that will monitor our portal for new uploads requiring moderation and allow us to review/approve them from our application without having to browse to our website.

Quick Review:

We added a WCF service to our module (in this example, we used the Repository module). In that service we exposed 2 methods as OperationContracts, one to retrieve a list of unapproved Repository items, and a second to approve an item.

Building the Desktop Client:

First thing, let’s layout our form. It will be a simple form with a listbox that will show me any Repository uploads that need to be reviewed/approved. To make it as simple as possible, let’s use checkboxes to allow me to check multiple uploads and approve them all at once. I’ll need a button to “Approve” whatever items are checked , another button to “Refresh” the listbox, and a label to show the last time the listbox was refreshed. Using, I throw together a quick mock-up.


OK, so that looks pretty good.

Now, we’ll build a Windows Forms application that will use our WCF service. We create a new project, in this example, I’ll create a C# Windows Forms Application. I’ll name the application “RepositoryOfflineModeration”.


And based on our mockup, let’s drop a “checked listbox”, a label, a couple of buttons and a status bar on our Form1.


The Service Reference:

In order to use our service, we need to add a Service Reference to our WCF service. Right-click on the “References” folder in our solution and select “Add Service Reference…”


The Add Service Reference dialog will be displayed. Enter the URL to the .svc file of our WCF service. Click to “Go” button and Visual Studio will retrieve contract information from the .svc file. Our service will be displayed and drilling into the service, we can see our Interface and on the right the Operations that we’ve exposed. Name your reference, in this example I named it “DNNServiceReference” and click “OK”.


We now have a client-side proxy, generated by Visual Studio, that will allow our desktop application to make service calls to our WCF service. This step also adds some entries in our app.config file to configure the available endpoints exposed by our service. Remember our service exposed two endpoints, one for soap calls (line 2) and one for rest calls (line 8). Also take note, each endpoint has a “name” property. We’ll use that name property when we use our client-side proxy to access our service. By default, Visual Studio will name the endpoints something like this… “BasicHttpBinding_IRepositoryService”, but you can change it in the app.config to make it more friendly, so I’ve changed my endpoint names to “soap” and “rest” Smile

 1: <client> 
 2:   <endpoint 
 3:     address="http://stevexps/dnn531/DesktopModules/Repository/RepositoryService.svc" 
 4:     binding="basicHttpBinding" 
 5:     bindingConfiguration="BasicHttpBinding_IRepositoryService" 
 6:     contract="DNNServiceReference.IRepositoryService" 
 7:     name="soap" /> 
 8:   <endpoint 
 9:     binding="customBinding" 
 10:    bindingConfiguration="WebHttpBinding_IRepositoryService" 
 11:    contract="DNNServiceReference.IRepositoryService" 
 12:    name="rest" /> 
 13: </client>

There’s one last configuration option I usually like to set when using WCF services. If I have OperationContracts that return a list of items, I prefer to use Generic Lists rather than ArrayList or Arrays. Once you’ve added the Service Reference, right-click on it and select “Configure Service Reference…”


On the configuration dialog, change the “collection type” setting to “System.Collections.Generic.List” and hit “OK”. Now when the service returns a List<RepositoryFile>, our client application will be able to process the items as a List.


The Code:

Now let’s drop some code, open the Form1.cs file. First thing we’ll write is some code to make a service call and get a list of any Repository items that need moderation. Let’s write this function to return a Generic List of RepositoryItems as we defined in our service’s DataContract. Here is the code so far in our Form1.cs file.

 1: using System; 
 2: using System.Windows.Forms; 
 3: using System.Collections.Generic; 
 4: using RepositoryOfflineModeration.DNNServiceReference; 
 6: namespace RepositoryOfflineModeration 
 7: { 
 8:    public partial class Form1 : Form 
 9:    { 
 10:      public Form1() 
 11:      { 
 12:         InitializeComponent(); 
 13:      } 
 15:      private static List<RepositoryFile> GetItems(int portalid) 
 16:      { 
 17:        using (var proxy = new RepositoryServiceClient("soap")) 
 18:        { 
 19:          return proxy.GetUnapprovedRepositoryFiles( 
 20:             portalid.ToString()); 
 21:        } 
 22:      } 
 23:   } 
 24: } 

A couple of things to notice. I use the namespace.service reference on Line 4 to bring in a namespace using statement. And on line 17, where I create my proxy, I pass “soap” as the endpoint name, telling the proxy to use the soap endpoint as defined in the app.config. The code is pretty simple, create a proxy, call the GetUnapprovedRepositoryFiles() OperationContract and return the List<RepositoryFile>.

Now, let’s hook up our function to the Form1_Load() event so that when we fire up our application, it makes a service call to see if there are any items awaiting our review. We’ll bind the results to our list box and with any luck, we should see our 1 record which we uploaded in Part #6. We write a private function to Bind the list box, and then call that function from our Form1_Load() function and the “Refresh” button.

 1: private void BindListBox() 
 2: { 
 3:   // clear list box 
 4:   checkedListBox1.Items.Clear(); 
 5:   checkedListBox1.CheckOnClick = true; 
 7:   // get unapproved items 
 8:   GetItems(0).ForEach( 
 9:     item => checkedListBox1.Items.Add( 
 10:       string.Format("[{0}] {1} - Uploaded by {2}", 
 11:       item.ItemID, item.Title, item.User))); 
 13:  // update the status bar 
 14:  toolStripStatusLabel1.Text = 
 15:    string.Format("{0} items require moderation", 
 16:    checkedListBox1.Items.Count); 
 18:  // set label to indicate last refresh 
 19:  label1.Text = String.Format( 
 20:     "Last Refresh : {0}", DateTime.Now); 
 21: } 
 23: private void Form1_Load(object sender, EventArgs e) 
 24: { 
 25:   BindListBox(); 
 26: } 
 28: private void bntRefresh_Click(object sender, EventArgs e) 
 29: { 
 30:   BindListBox(); 
 31: }

We clear the checkedlistbox on line 4, call our private function on line 8, which will retreive a list of all Repository Items that have been uploaded and need approval. We then update the status bar with the count of items (line 14), and finally update our label with a timestamp to show the last time we refreshed the list (line 19).


Let’s compile and run our application and see if it works ( hint: I bet it does Smile )


Nice! The program ran, called the WCF service to get a list of items and displayed the items in the list box. Our label shows us the last time the service was called and our status bar shows us we have one item to approve.


The last step is to hook up some code to the “Approve Checked” button, that will use the WCF service to approve items.

Our Approval code, will look at the items in the checkedlistbox and for each “checked” item, it will parse the item string to get the ItemID (the number between the square brackets]. Then it will use the proxy to call the service method and approve the items that are checked.

 1: private void btnApprove_Click(object sender, EventArgs e) 
 2: { 
 3:   using (var proxy = new RepositoryServiceClient("soap")) 
 4:   { 
 5:     foreach (var item in checkedListBox1.CheckedItems) 
 6:     { 
 7:       // parse the item string to get the ItemID 
 8:       var s = item.ToString().Split(new char[] { '[',']' }); 
 9:       proxy.ApproveRepositoryFile(s[1]); 
 10:    } 
 11:  } 

Final Test:

We run our application, check the item listed (#3 Whiskey), and click the Approve Checked button.


After clicking “Approve Checked”, our listbox is refreshed and now there are no items listed !


Just to complete our test, let’s go to a browser and load up our web site. Taking a look at the page with our Repository module, we now see that Whiskey has been approved and is now displayed in the module!



We created a Desktop Windows Forms application that uses our WCF service. The application will allow us to see when items have been uploaded that require approval, and we can approve those items from our desktop application without ever having to browse to our web site.


In a real-world application, you would most likely add a “Timer” to your form so that the list is automaticall refreshed at some interval. You would also probably expose more “item data” via your DataContract, so you could review the image, and file uploaded by the user before approving it. You could also use the same techniques to develop a Windows “Gadget” to sit in your sidebar or desktop and alert you with popup system tray alerts (ala Outlook) when a item is uploaded.. The service provides the tech, you provide the creativity.

Coming up next…

In the next and final part of this series, I’ll talk about security. Obviously if you are building a WCF service that provides data management or administrative functions, you’ll need to implement a security layer to restrict access to certain operations. We’ll implement a securirty layer that uses the DotNetNuke security functions to require an ID and password, and determine role membership. Then we’ll introduce a security check for the OperationContracts that we want to restrict to certain security roles.


2 comment(s) so far...


Re: WCF Series: Part #7 Offline Data Management using WCF

First, thank you for this series.
I manage to follow it through step 6, but I have a problem with step 7. When i add the service reference, I have only the "wsHttpBinding" endpoint in my app.config, but I do not have the 2 others as descibed in the tutorial. Should I add by hand, or I made a mistake.
Thank's by advance.

By Antoine Laplante on   11/1/2012 7:26 PM

Re: WCF Series: Part #7 Offline Data Management using WCF

First, thank you for this series.
I manage to follow it through step 6, but I have a problem with step 7. When i add the service reference, I have only the "wsHttpBinding" endpoint in my app.config, but I do not have the 2 others as descibed in the tutorial. Should I add by hand, or I made a mistake.
Thank's by advance.

By Antoine Laplante on   11/1/2012 8:07 PM
Privacy Statement | Terms Of Use | Copyright 2007-2009 by