So the situation is this… I have a Silverlight LOB application that I need hosted in the Windows Azure cloud. The Silverlight application hits a series of WCF Services that provide data from a SQL Database. So for this project I needed to accomplish the following goals:
1) Deploy a SQL Server 2008 database to the SQL Azure cloud.
2) Deploy and configure my WCF Services to the Windows Azure cloud such that they hit the SQL Azure database.
3) Deploy and configure the Website application that hosts the Silverlight 3 LOB application such that it hits the WCF Services running on the Windows Azure Cloud.
Publish your SQL Server Database to SQL Azure
Follow the steps outlined here:
http://msdn.microsoft.com/en-us/library/ee621790.aspx
There are some great resources for working with SQL Azure here:
http://msdn.microsoft.com/en-us/library/ee621784.aspx
Once complete, you should be able to query your SQL Azure database from SQL Server Management Studio and retrieve your data from the cloud. This does in fact work with the Nov. 2009 release of SQL Azure. Note that SSMS can NOT currently show you any of the DB Meta info in the GUI, you can simply query your db with a new query window.
Also, be sure to add your public IP to the SQL Azure Database Firewall settings.
Converting the WCF Services to an Azure WCF Role
Since this is an existing application I did not want to mess around with my source controlled and working application code. I decided to create an Azure version of my project and copy my source files in.
I started by creating a new Windows Azure Cloud Service in Visual Studio 2010 b2.
I added a Web Role and a WCF Service Role.
Note that when you add these roles you can hover over the role and click the pencil link. This will let you rename the Role. This is important because it is a royal pain to rename everything after the fact.
Now that you have your new roles. Copy your service code and resolve your references so that your WCF service compiles.
Decorate your WCF Service Class with the ServiceBehavior attribute and set the AddressFilterMode to Any. This is needed to get your WCF Service to work in the cloud. You can read up more about it online here.
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class DataService : IDataService
Add your Silverlight Application To the Web Role
I am actually considering simplifying my deployment a bit by including the Silverlight application and the Default.aspx web page all in the same Role. If I decide to do this I will update this posting.
So now you have your Database and WCF Service set up you need to Add your Silverlight application to the Web Role that will display the Silverlight application. To do this make sure your Silverlight project is included in the new Azure solution. Open the Default.aspx page in the new Azure Web Role project and insert the necessary HTML and Javascript to display your Silverlight application. You can cut and past this from the Silverlight test page if you like.
Now, link the Azure Web Role project to the Silverlight project so that every time you build, your XAP file (the Silverlight bits) is updated in the Azure Web Role project.
Right click on your Azure Web role project and choose Properties. Click the Silverlight Applications tab. Here you can link a Silverlight application to this web app so that it is updated when the Silverlight project is built.
Test the Web Role project and it should build and display your Silverlight application. Once this is working we need to tie all of these applications together.
CSCFG Cloud Service Configuration
You need some way of telling the Silverlight application where the WCF Service is located. Modifying a Web.config file is not a viable option. With an application deployed to the Azure Cloud you need to be able to configure the Silverlight application outside of the Web Application and Outside of the ServiceReferences.ClientConfig file.
I will post another blog entry about dynamically configuring Silverlight for WCF. Here I will give you the ingredients:
Add the initParams tag to the Silverlight ActiveX Control definition in the HTML page that hosts your Silverlight application. In the initParams you must pass in the base URL for your WCF Service(s). My init params looks like this:
<param name="initParams" value="reportserverurl=http://reportserver/ReportServer,wcfservicebase=http://mywcfservice.cloudapp.net" />
This allows the HTML page to pass in configuration parameters to the Silverlight application. The Silverlight application needs to read these values in the App.xaml.cs file like this:
private void Application_Startup(object sender, StartupEventArgs e)
{
IDictionary<string, string> parameters = e.InitParams;
VMRSilverlight.ViewModel.State.WCFServiceBaseURL = parameters["wcfservicebase"];
VMRSilverlight.ViewModel.State.ReportServerURL = parameters["reportserverurl"];
this.RootVisual = new MainPage();
}
I use a Proxy Factory to create the instance of my WCF Service Proxies so I have only one place to update the construction of my WCF Proxies like this:
public static Proxy.AdminService.AdminServiceClient CreateAdminService()
{
string url = string.Format("{0}/AdminService.svc", State.WCFServiceBaseURL);
return new Proxy.AdminService.AdminServiceClient("CustomBinding_IAdminService", url);
}
Once you have done all this, your Silverlight application is now properly plumbed to allow you to pass in the WCF Service Url. There is one more step here and that is to read the WCF Service url from the Cloud Service Configuration File.
First, You need to define a configuration setting in the ServiceDefinition.csdef file:
<ConfigurationSettings>
<Setting name="DiagnosticsConnectionString" />
<Setting name="WcfBaseUrl" />
</ConfigurationSettings>
Next, actually define the value for the new Setting in the .cscfg file:
<ConfigurationSettings>
<Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
<Setting name="WcfBaseUrl" value="http://YourWcfServiceURL.cloudapp.net"/>
</ConfigurationSettings>
Now, you need to update your HTML/ASP.NET website so that it will read the config setting from the .cscfg file and pass that value to your silverlight application. I did this by defining a public method on my Default.aspx.cs code behind file that retreives the value for me.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string getWcfUrl()
{
return Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue("WcfBaseUrl");
}
}
Now a quick update to my .ASPX page that displays the Silverlight application and we are set!
<param name="initParams" value="reportserverurl=http://ReportServername/ReportServer,wcfservicebase=<%= getWcfUrl() %>" />
So now you are all wired up. You can now deploy the application to the Azure Cloud. After deployment use the configure button to configure the .cscfg file to point to the staging or production URL of your WCF Service.