Home ยป BlogEngine.NET | Silverlight

A Silverlight BlogEngine.NET Control

28 Nov 2008 2:00 PM 28 Comments Bookmark and Share kick it on DotNetKicks.com

So here it is.  My first Silverlight BlogEngine.NET control. 

This one simply reports the version of BlogEngine.NET I'm currently running.

If you don't have Silverlight installed, this is what's shown...

PostView

So how was it done?

Well, to get the current BlogEngine version I had to create a WCF Service and have Silverlight asynchronously execute my service method.

 

Pre-requisites

Before I begin describing the steps to achieve the above, we have to upgrade our BlogEngine.NET 1.4.5 version from .NET Framework 2.0 to 3.5.  This is as simple as obtaining the source files from CodePlex and opening the solution in Visual Studio 2008.  If asked to upgrade all web applications, say Yes.  Once the solution fully loads we need to open the properties for the project BlogEngine.Core and change its Target Framework to .NET Framework 3.5.

BlogEngineUpgrade

Finally, re-compile the solution (and upload all the files to our hosting provider).

I'll be writing some articles soon on how to create some cool BlogEngine.NET Widgets and controls that will use Silverlight, WCF Services, LINQ and Lambda expressions, so this upgrade is necessary.  From what I understand, the next version of BlogEngine.NET will be upgrade to the .NET Framework 3.5 level.

 

Step 1

OK, let's create our WCF Service to return the current BlogEngine.NET version. Since we'll be using this WCF Service in a Silverlight application, we'll add a new Silverlight-enabled WCF Service to our BlogEngine.NET web application.  Using this type of WCF Service will automatically configure our web.config for use by Silverlight by ensuring such things as basicHttpBinding is set, etc.  Since I like to keep all my eggs in one basket, I add all "add-ons" to my current theme folder.  I named this as SampleSilverlightWCFService.svc.

AddNewItem 

By default, the SampleSilverlightWCFService.cs file will be located in the App_Code folder.  Remember this when its time upload your changes to your site.

Ok, here's the code for our service.  Pretty simple, it just returns the version as a string.

   1: using System.ServiceModel;
   2: using System.ServiceModel.Activation;
   3:  
   4: [ServiceContract(Namespace = "")]
   5: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   6: public class SampleSilverlightWCFService
   7: {
   8:     [OperationContract]
   9:     public string FetchBlogEngineVersion()
  10:     {
  11:         return BlogEngine.Core.BlogSettings.Instance.Version();
  12:     }
  13: }

 

and our SampleSilverlightWCFService.svc file looks like this:

   1: <%@ ServiceHost Language="C#" Debug="true" 
   2:                 CodeBehind="SampleSilverlightWCFService.cs" 
   3:                 Service="SampleSilverlightWCFService"
   4:                 Factory="CustomServiceFactory" %>

 

What's that Factory statement there?  Well during testing, I kept getting the error on my hosted site:

"This collection already contains an address with scheme http.  There can be at most one address per shceme in this collection."

According to a response on one of the MSDN forums, "WCF does not support multiple IIS bindings for the same protocol (HTTP) for the same web-site".

In most hosting environments, such as the one that 13sides.com resides at, there is possibility of multiple http endpoints, i.e. multiple ways to reach the same domain (like www.13sides.com or 13sides.com, etc).  WCF only supports single endpoint implementations so here is a solution.

This is the CustomServiceFactory class located in the App_Code folder:

   1: using System;
   2: using System.ServiceModel;
   3: using System.ServiceModel.Activation;
   4:  
   5: public class CustomServiceFactory : ServiceHostFactory
   6: {
   7:     /// <summary>
   8:     /// A custom method to eliminate multiple base 
   9:     /// addresses from the IIS host creation process
  10:     /// </summary>
  11:     /// <param name="serviceType">The service type to be created</param>
  12:     /// <param name="baseAddresses">A list of the base addresses</param>
  13:     /// <returns>A service host</returns>
  14:     protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
  15:     {
  16:         ServiceHost serviceHost;
  17:         if (baseAddresses.Length > 1)
  18:             serviceHost = new ServiceHost(serviceType, baseAddresses[1]);
  19:         else
  20:             serviceHost = new ServiceHost(serviceType, baseAddresses[0]);
  21:  
  22:         return serviceHost;
  23:     }
  24: }

 

Its a relatively simple piece of code, with all the business done in the overridden method CreateServiceHost.  What normally happens is that ServiceHosts would be created for all the baseAddresses passed in, which is where WCF dies.  By checking if there are multiple addresses and only choosing one of them, we are golden.  This even works locally when debugging (as there's only one http endpoint).

So now our WCF Service is complete.

We can test it by browsing to http://www.13sides.com/themes/13sides v2/SampleSilverlightWCFService.svc (of course, replace the relative path to your own).  You should see something to the effect of:

WCF

 

Step 2

Time to create our Silverlight application.

1) Add a new "Silverlight Application" project our solution.  I named mine "BlogEngine.UI" as it will eventually contain most of my UI elements for my implementation of BlogEngine.NET.  When creating a new Silverlight Application the wizard will ask if you would like to create a new ASP.NET Web project (and other options).  We'll choose the following:

AddSLProject

(its usually a good idea to automatically add a test page fro debugging purposes too)

2) Open the Page.xaml and add a new TextBlock as shown:

   1: <UserControl x:Class="BlogEngine.UI.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     Width="Auto" Height="Auto">
   5:     
   6:     <Grid x:Name="LayoutRoot" Background="BlanchedAlmond">
   7:  
   8:         <TextBlock x:Name="txtVersion" FontSize="24"  />
   9:  
  10:     </Grid>
  11: </UserControl>

 

3) Now lets add our service reference.  Right-click the BlogEngine.UI project and choose "Add Service Reference...".  When the "Add Service Reference" dialog box appears, click Discover to find all the available services in the solution.  We'll select our service and name it SampleSilverlightWCFServiceRef.

AddService

4) Open the Page.xaml.cs code file and add the following using statement.

   1: using BlogEngine.UI.SampleSilverlightWCFServiceRef;

 

5)  Now we need to wire up the service and call its method to populate our TextBlock.  Here is the final code.

   1: using System;
   2: using System.ServiceModel;
   3: using System.Windows;
   4: using System.Windows.Controls;
   5:  
   6: using BlogEngine.UI.SampleSilverlightWCFServiceRef;
   7:  
   8: namespace BlogEngine.UI
   9: {
  10:     public partial class Page : UserControl
  11:     {
  12:         public Page()
  13:         {
  14:             InitializeComponent();
  15:  
  16:             this.Loaded += new RoutedEventHandler(Page_Loaded);
  17:         }
  18:  
  19:         protected void Page_Loaded(object sender, RoutedEventArgs e)
  20:         {
  21:             BasicHttpBinding binding = new BasicHttpBinding();
  22:             EndpointAddress address = 
  23:                 new EndpointAddress(
  24:                     new Uri(Application.Current.Host.Source, 
  25:                             "../themes/13sides v2/SampleSilverlightWCFService.svc").ToString());
  26:             
  27:             SampleSilverlightWCFServiceClient client = 
  28:                 new SampleSilverlightWCFServiceClient(binding, address);
  29:  
  30:             client.FetchBlogEngineVersionCompleted += new EventHandler<FetchBlogEngineVersionCompletedEventArgs>(FetchBlogEngineVersionCompleted);
  31:             client.FetchBlogEngineVersionAsync();
  32:         }
  33:  
  34:         #region Asynch Methods
  35:         protected void FetchBlogEngineVersionCompleted(object sender, FetchBlogEngineVersionCompletedEventArgs e)
  36:         {
  37:             if (e.Error == null)
  38:                 txtVersion.Text = e.Result;
  39:             else
  40:                 txtVersion.Text = e.Error.InnerException.ToString();
  41:         }
  42:         #endregion
  43:     }
  44: }

 

I always create the binding and endpoint address in code, so I don't have to worry about changing config parameters when I promote to 13sides.com.  This should all work in development mode (localhost) and live -> www.13sides.com

6)  Now re-compile all your code.

 

Step 3

Our WCF service done.  Our Silverlight application is done.  You should now have a compiled xap (pronounced zap) in your BlogEngine.NET web application (under the ClientBin folder).

Let's create a ASP.NET User Control to contain this Silverlight application.

1) Add a new "Web User Control" under the folder "User controls".  We'll name it SampleSilverlightControl.ascx.

2) Add the following code:

   1: <%@ Control Language="C#" AutoEventWireup="true" CodeFile="SampleSilverlightControl.ascx.cs" Inherits="User_controls_ThirteenSides_SampleSilverlightControl" %>
   2:  
   3: <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>
   4:  
   5:  
   6:         <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
   7:  
   8:         <div style="width: 200px; height:50px; background-color: Purple;">
   9:             <asp:Silverlight ID="Xaml1" runat="server" 
  10:                              Source="~/ClientBin/BlogEngine.UI.xap" 
  11:                              MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
  12:         </div>

 

3) Now we need to create a new post in BlogEngine.NET to show this new user control.  Using the awesome code injection feature all we need is this one line:

 

"[ usercontrol : ~ / User controls / ThirteenSides / SampleSilverlightControl . ascx ] "

(please ignore the spaces shown here but BlogEngine.NET will actually render this line to the control if not)

 

That's it.  We're done.  I hope you can see the possibilities with Silverlight and BlogEngine.NET. 

I'm already working on a dedicated 100% Silverlight Theme.  Should be awesome.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

Comments are closed