Blog

Gooddogs Development Blog

Nov 22

Written by: Steve Fabian
11/22/2009 11:23 AM 

Series 1. DotNetNuke and WCF

Agenda/Intro:
Why use WCF with DotNetNuke?
Quick Look at WCF
•Demos / code examples
    –Monitoring your web site
    –Offline management of your content
•Questions

Ok, so all the groundwork is set. You should now understand how to add a WCF service to your DotNetNuke web site and how to expose both a SOAP-based and REST-based endpoint to your service.  In this section, we’ll talk a little about DataContracts and show you how to expose some data about your DotNetNuke web site to external clients.  We’ll add an OperationContract to expose some Metrics about our site, and write a Windows Forms application that will use the service and allow you to monitor your site’s activity without have to browse to your web site.

DataContracts:

In our example so far our OperationContract returned a single data vaue, in the case of our SayHello function it returned a string.  What if you want to return a more complex data object, with multiple properties?  Well, then you use a DataContract.

DataContracts can be specified in your Interface file, or in a separate .cs file.  If your DataContract might be used in multiple WCF Services, then place your DataContract in a separate file.  If your DataContract is specific to your Service, then you might as well just place it directly in your Interface file along with your OperationContracts.

A DataContract is nothing more than a public class with some special attributes to let WCF know that it will be used as either input or output from an OperationContract.

Exposing DotNetNuke site data with WCF:

In this next example, we’ll write a function named GetDNNMetrics() that will return some site metrics from our site, how many Page Views today, how many Unique Visitors have we had to our site today and finally, how many Registered Users do we have on our site.  Of course, there are many, many metrics available for a DotNetNuke site and you can decide which ones are important to you, but this example will walk you through the steps to expose Data through a WCF service and you can modify or extend this example as you wish.

To start, we open our IDNNService.vb interface file.

We need to import a new namespace, System.Runtime.Serialization.

  1: Imports System.Runtime.Serialization

Next, we go to the bottom of our interface file and add a public class, we’ll name it DNNMetrics, and set the class properties for the values we want to return from our service call.  In this example, we’ll create a public class named DNNMetrics. This is the object that we will return and establish three properties, Views, Visitors and Users.

  1: Public Class Metrics
  2: 
  3:     Public PageViews As Integer
  4:     Public UniqueVisitors As Integer
  5:     Public RegisteredUsers As Integer
  6: 
  7: End Class

To convert this public class to a DataContract, we just add some attributes.  We place a DataContact attribute on the class, and for each property that we want WCF to serialize as part of this contract we add a DataMember attribute. This means that you can have a class with many properties and you do not have to return all of them as part of a service call, you can decide which ones you want to return as part of the data object and then only place DataMember attributes on the ones you do want to return.

So, in this example we’ll return all three properties, so our attributed DataContract looks like this.

  1: <System.Runtime.Serialization.DataContract()> _
  2: Public Class Metrics
  3: 
  4:     <DataMember()> _
  5:     Public PageViews As Integer
  6:     <DataMember()> _
  7:     Public UniqueVisitors As Integer
  8:     <DataMember()> _
  9:     Public RegisteredUsers As Integer
 10: 
 11: End Class

Ok, now we have a DataContract that we can use to return a complex data object from our service. Next, we’ll add a new OperationContract to expose the DNNGetMetrics() function.

  1:     <OperationContract()> _
  2:     <WebGet(ResponseFormat:=WebMessageFormat.Xml, UriTemplate:="metrics/{portal}")> _
  3:     Function DNNGetMetrics(portal As String) As DNNMetrics

We define our OperationContract, we define a URI so we can access this function using our REST interface, we tell WCF to return our data in XML format and we prototype our function to expect a single input parameter named ‘portal’, and it will return a DNNMetrics data object.  Because of the DataContract and DataMember attributes, WCF will serialize our DNNMetrics class to an XML object.

NOTE: Even though portal will be an integer, REST calls can only treat parameters as string (they are coming in over Http and are not strongly typed, so if you are exposing a REST interface all of your input paramters must be strings and then you can convert and validate them within your function.

Implementing our DNNMetrics() function:

Next we write our implementation code. Open the DNNService.vb file and add the GetDNNMetrics() function.  Because we are running our service within the DotNetNuke context, we have full access to all of the DotNetNuke namespaces and assemblies.  In our GetDNNMetrics() function, we can use the LogController service to get our metrics data. We create an instance of a SiteLogController ( line 5 ), we validate our input parameters, making sure portal is numeric ( line 8 ), make a call to the GetSiteLog() function ( line 18 ) which returns an IDataReader.  We then get the data from the reader ( line 22 ) and move the data into our DNNMetrics data object ( lines 24-26). If we get any exceptions, we Throw them back to the client ( line 9 and 30 ).  One of the parameters to the GetSiteLog() function is the PortalAlias, on line 19, I’ve hard-coded it to my sample web site. You can store this alias in your web.config as an Application setting, or if you have multiple DotNetNuke web sites, you could add alias as an input parameter to the GetDNNMetrics() function.

   1:  Public Function GetDNNMetrics(ByVal portal As String) As DNNMetrics _
   2:  Implements IDNNService.GetDNNMetrics
   3:   
   4:     Dim results As New DNNMetrics
   5:     Dim logController As New DotNetNuke.Services.Log.SiteLog.SiteLogController
   6:   
   7:     ' validate parameters
   8:     If Not IsNumeric(portal) Then
   9:         Throw New Exception("PortalId must be an Integer")
  10:     End If
  11:   
  12:     Try
  13:         Dim PortalId As Integer = Int32.Parse(portal)
  14:         Dim StartDate = Date.Today().ToShortDateString()
  15:         Dim EndDate = Date.Now()
  16:         Dim ReportType As Integer = 1
  17:   
  18:         Using reader As IDataReader = logController.GetSiteLog(PortalId, _
  19:                 "http://localhost:50318/DNNWCFBlogs/", _
  20:                  ReportType, StartDate, EndDate)
  21:   
  22:            reader.Read()
  23:   
  24:            results.PageViews = Int32.Parse(reader("Views"))
  25:            results.UniqueVisitors = Int32.Parse(reader("Visitors"))
  26:            results.RegisteredUsers = reader("Users")
  27:         End Using
  28:   
  29:     Catch ex As Exception
  30:        Throw New Exception("Unable to retrieve DNN Site Metrics")
  31:     End Try
  32:   
  33:     Return results
  34:   
  35:  End Function

We then return our data object ( line 33 ).  WCF will serial our data into XML. Let’s go test it out!.  We open an Internet Explorer browser and browse to our REST URI for the GetDNNMetrics OperationContract.

http://localhost:50318/DNNWCFBlogs/DNNService.svc/rest/metrics/0


We make a call to our REST interface, the /rest/metrics/0 matches the “metrics/{portal}” URI on our REST endpoint so WCF knows we want to execute the GetDNNMetrics() function.  The function is executed, a DNNMetrics data object is created, the metrics data is moved into that object and WCF serializes it into XML and returns it as shown below.

image


You can see that we got back XML with DNNMetrics as the root node and we can see our PageViews, RegisteredUsers and UniqueVisitors data.

Let’s review where we are.  We’ve created a WCF service, defined OperationContracts and a DataContract to expose metrics data, wrote the implemenation code to retrieve and return site metrics from our DotNetNuke site, and finally tested it out using IE and our REST endpoint.

Writing a Windows Forms Application to Display Site Metrics:

Let’s create a Windows Forms application and use our service to display site metrics on our Desktop.

In Visual Studio, create a Windows Forms app, I’ll call it “DNNDesktopMetrics”.  We’ll add 6 labels to the form, one for each metric and it’s value

image

 

We need to add a “Service Reference”, so right-click on our forms project and select “Add Service Reference…”

image


We browse to our DNNService.svc file and add a reference

image


When we add a reference to our service, Visual Studio will generate a client side proxy and add some entries in our app.config file. Let’s look at the app.config entries.

   1:  <client>
   2:      <endpoint address="http://localhost:50318/DNNWCFBlogs/DNNService.svc"
   3:          binding="wsHttpBinding" 
   4:          bindingConfiguration="WSHttpBinding_IDNNService"
   5:          contract="DNNServiceReference.IDNNService" 
   6:          name="WSHttpBinding_IDNNService">
   7:          <identity>
   8:              <dns value="localhost" />
   9:          </identity>
  10:      </endpoint>
  11:      <endpoint binding="customBinding" 
  12:          bindingConfiguration="WebHttpBinding_IDNNService"
  13:          contract="DNNServiceReference.IDNNService" 
  14:          name="WebHttpBinding_IDNNService" />
  15:  </client>

Because our service exposes two endpoints, Visual Studio generated two client side endpoints so that we can decide which one we want to use when accessing our service.  The first client endpoint will use our SOAP endpoint ( you can tell by the binding configuration, wsHttpBinding ) and the second client endpoint is for our REST endpoint ( webHttpBinding ).  The key here is that each client endpoint has a “name” attribute.  In this Form application, let’s use the SOAP endpoint, so take note of the name of that client endpoint, WSHttpBinding_IDNNService”.

Now, let’s write some code in the Form_Load function to call our service using the SOAP endpoint, retrieve some site metrics and display then on our form.  On line 5 we create an instance of our service client. Note that since we have mutiple endpoints defined, we need to tell the service client WHICH endpoint to use, and we do so by  passing the client endpoint name as a parameter. We pass WSHttpBinding_IDNNService, so this call will use the SOAP endpoint.  We then call the GetDNNMetrics() OperationContract on line 7, passing a 0, notice it’s a string :), and then because we  have a strongly types client side proxy, we can access the metrics properties from the metrics return object and set the labels on our Form.

   1:  Private Sub Form1_Load(ByVal sender As System.Object, _
   2:      ByVal e As System.EventArgs) Handles MyBase.Load
   3:   
   4:      Using proxy As New _
   5:          DNNServiceReference.DNNServiceClient("WSHttpBinding_IDNNService")
   6:   
   7:          Dim metrics = proxy.GetDNNMetrics("0")
   8:   
   9:          lblPageViews.Text = metrics.PageViews.ToString()
  10:          lblUniqueVisitors.Text = metrics.UniqueVisitors.ToString()
  11:          lblRegisteredUsers.Text = metrics.RegisteredUsers.ToString()
  12:   
  13:      End Using
  14:   
  15:  End Sub

Let’s see what that looks like when we fire up our Desktop Forms Application…

image

Woo Hoo!!

We can extend this Forms application to use a Timer, and if we move the service call code to the Timer elapsed function, we can have a desktop forms application that will keep an eye on our web site. We can see “live” metrics about our web site on our desktop or sidebar gadget without having to browse to our web site.

So, now we have used a WCF service to expose “Data” from our DotNetNuke web site to external clients.

In the next section I will show you how to expose “functionality” and we’ll build a desktop forms application that will allow us to monitor and administer module content through our WCF service

Next: Demo 2: Exposing Functionality From Your DotNetNuke Web Site (coming soon)

Tags:

2 comment(s) so far...

Re: Part#5: Using WCF to expose DotNetNuke Data

hi steve,

any idea when the next part of the WCF series gets online ? I'm specifically interested in dealing with security. Will you cover this in your next step ?

Best regards
Torsten from germany

By torsten weggen on   12/10/2009 1:52 PM

Re: Part#5: Using WCF to expose DotNetNuke Data

this is a great series, steve. are you still planning on doing the next section? i'm working on putting a wcf service in with dotnetnuke to allow my client app to use the same users, roles, etc. from dnn and it would be benefical to hear what you have to say.

By martin mizzell on   2/1/2010 4:35 PM