Creating
applications for Windows Azure is something that affects a big plethora
of scenarios, because you can generally build and deploy any kind of
Web applications. This article provides an example of a Silverlight Web
application to show how different technologies (ASP.NET, Silverlight,
and Azure) can coexist in the cloud development. With that said, run
Visual Studio 2010 and open the New Project dialog.
To test your Windows Azure applications locally, Visual Studio needs to be run with elevated privileges (Run as Administrator).
This is required because Visual Studio needs to launch the Development
Fabric, which also needs to be run with elevated privileges.
|
Click the Cloud Service folder and select the Windows Azure Cloud Service project template. Name the new project as AzureBookstore. See Figure 1 for details.
After you click OK, another dialog displays requesting you to specify the application type. In this dialog select the ASP.NET Web Role option and press the right arrow so that everything appears as in Figure 2.
It is possible to
select different kinds of projects, such as ASP.NET MVC 2 or WCF
projects. The ASP.NET Web Role is the most common template for classic
ASP.NET applications. After this, Visual Studio generates a new
solution storing two projects: The first project is the Cloud service
that stores information for the Windows Azure hosting service. The
second project is the ASP.NET Web application that you actually work
on. Before putting hands on the code, an explanation about both
projects is required.
Understanding Web Roles and Web Configuration
A key concept in Windows Azure development is the role,
which is typically a single component running in the Azure environment
and built in managed code. Roles can be of two types: web roles and
worker roles. A Web role is generally an ASP.NET Web application, like
the case of our sample scenario. As you may remember from Figure 2,
additional Web roles are available for WCF and FastCGI applications.
You may instead think of worker roles as of services running behind the
scenes, like in the case of Windows services, in the cloud. An Azure
project can have multiple roles and multiple instances of one role;
moreover, you can configure roles as required. When you create new
Cloud projects, the new solution will contain a Web role project
(simply an ASP.NET Web project) and a service project where you can
configure role properties. To access roles configuration, in Solution
Explorer right-click the WebRole1 role and select Properties. At this point a special implementation of the My Project designer will pop up. Figure 3 shows what you will see on the screen.
The Configuration tab enables first setting the .NET trust level for roles. By default the trust level is Full Trust.
The Windows Azure partial trust level has instead some limitations and
denies your role access to some resources, such as the Registry,
isolated storage, printing, and OleDb connections. The full
restrictions list is available here: http://msdn.microsoft.com/en-us/library/dd573355.aspx. The Instance Count field enables setting how many instances of the role are permitted, whereas VM Size
enables specifying the size of the virtual machine hosting your
service. Small means one CPU core, 1.7 gigabytes of memory, and 250
gigabytes of hard disk space. Medium means two CPU cores, 3.5 gigabytes
of memory, and 500 gigabytes of hard disk space. Large means four CPU
cores, 7 gigabytes of memory, and 1 terabyte of hard disk space;
finally, ExtraLarge means eight CPU cores, 15 gigabytes of memory, and
2 terabytes of hard disk space. The Startup action group enables
specifying if debugging should be launched via an HTTP or and HTTPS
endpoint (which must be defined in the Endpoints tab). In the Settings
tab you can define settings that you can access via the Windows Azure
SDK Runtime API. By default each role has a DiagnosticsConnectionString
that defines whether you need access to the local storage or the online
services. In the Endpoints tab you can define endpoints for your
application. Deciding to apply for an HTTPS endpoint also requires a
valid SSL certificate. You add certificates to your deployment via the
Certificates tab. Finally, the Local Storage tab enables configuring
the file system storage resources local for each instance. All the
preceding options and settings are reflected into the
ServiceConfiguration.cscfg and ServiceDefinition.csdef files that you
can see in Solution Explorer and that are basically XML representations
of settings.
You
can add multiple web roles and worker roles by right-clicking the Roles
folder in Solution Explorer. Another consideration that you need to
keep in mind is that Windows Azure is a 64-bit operating system, so
take care of this if you plan to invoke unmanaged code that might fail.
|
The default role for the
new project is associated with the ASP.NET project that will actually
run the application. You can therefore build your application directly
within the Web project or add a Silverlight project, as explained in
next section.
Adding a Silverlight 3 Project
A web project can host
Silverlight applications, as you may remember from previous discussions
about this technology. This also true in Windows Azure scenarios. The
goal of this chapter is building a Silverlight application capable of
showing and editing a list of books within a DataGrid
control, also providing the ability of reading and saving data to Xml
taking advantage of the isolated storage. At this point right-click the
web project name in Solution Explorer and click Add New Item. Notice that we are not adding a new project, but simply an item. When the Add New Item dialog appears, click the Silverlight folder on the left and select the Silverlight Application item template, naming the new item as BookStore.vbproj (see Figure 4 for details).
When
you add the new project, a dialog asks for specifying the Silverlight
version, the project path, and other information such as enabling
debugging. Leave the default settings unchanged, as shown in Figure 5, and continue.
Because we use LINQ to Xml for
listing and saving books, and because this will be accomplished using a
DataGrid control, add references to the System.Xml.dll,
System.Xml.Linq.dll and System.Windows.Controls.Data.dll assemblies.
Now there is the need of implementing a Book class representing one book and a BooksCollection class representing a typed collection of books, so add a new code file to the Silverlight project named Book.vb. Code in Listing 1 demonstrates this.
Listing 1. Implementing Classes for Representing Books
Imports System.Collections.ObjectModel
Public Class Book
Public Property Title As String Public Property Author As String Public Property DatePublished As Date Public Property ISBN As String
End Class Public Class BooksCollection Inherits ObservableCollection(Of Book)
Public Sub New(ByVal source As IEnumerable(Of Book)) For Each b As Book In source Me.Add(b) Next End Sub
Public Sub New()
End Sub End Class
|
For the sake of clarity, implement just a DataGrid and a Button for saving data. The following XAML code must replace the Grid definition:
<Grid x:Name="LayoutRoot" Background="Green">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<data:DataGrid Name="BooksGrid" Grid.Row="0" ItemsSource="{Binding}"
AutoGenerateColumns="True" />
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Width="100" Height="40" Margin="5"
Content="Save" Name="SaveButton"/>
</StackPanel>
</Grid>
The DataGrid is defined within the System.Windows.Controls.Data namespace; because of this, you need to add the following Xml namespace declaration at page level to use it:
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
Now it is time to write
Visual Basic code. Our goal is reading data from an Xml file containing
books’ definitions and that is stored in the Silverlight’s isolated
storage. If the file is not found, which is the case of the first run,
an empty books collection is defined. Finally the code provides the
ability of saving data to the isolated storage. Listing 2 shows all these operations (read comments within code for explanations).
Listing 2. Defining Code for Retrieving, Showing, and Saving Books Definitions
Imports System.Xml.Linq Imports System.IO, System.Text Imports System.IO.IsolatedStorage
Partial Public Class MainPage Inherits UserControl
'Declaring a books collection Private MyBooks As BooksCollection
'Required for understanding if the DataGrid 'is in edit mode Private isEditing As Boolean = False
Public Sub New()
InitializeComponent() End Sub
'Used to generate data if the data file is not 'found Private Function CreateData() As BooksCollection Dim b As New Book With {.ISBN = "0000000"}
Dim bc As New BooksCollection bc.Add(b) Return bc End Function
'Attempts to read the data file from the isolated storage 'If found, with a LINQ to Xml query a new books collection 'is returned. If not found, a new empty collection is 'generated and returned Private Function GetBooks() As BooksCollection Try Dim doc As XDocument
Using store As IsolatedStorageFile = IsolatedStorageFile. GetUserStoreForApplication Dim st As IsolatedStorageFileStream = _ store.OpenFile("Books.xml", FileMode.Open) doc = XDocument.Load(st) st.Close() End Using
Dim query = From pbook In doc...<Book> Select New Book With {.Author = pbook.@Author, .Title = pbook.@Title, .DatePublished = Date. Parse(pbook.@DatePublished), .ISBN = pbook.@ISBN }
Return New BooksCollection(query)
Catch ex As Exception Return CreateData() End Try End Function
Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows. RoutedEventArgs) Handles Me.Loaded 'Populates data Me.MyBooks = GetBooks() 'Sets data-binding Me.DataContext = Me.MyBooks End Sub
'Saves data to the isolated storage. The Xml data is generated 'with LINQ to Xml embedded-expressions Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.Windows. RoutedEventArgs) Handles SaveButton.Click Dim data = <?xml version="1.0" encoding="utf-8"?> <Books> <%= From b In MyBooks Select <Book Author=<%= b.Author %> Title=<%= b.Title %> ISBN=<%= b.ISBN %> DatePublished=<%= b.DatePublished. ToString %>/> %> </Books>
Using store As IsolatedStorageFile = IsolatedStorageFile. GetUserStoreForApplication Dim st As IsolatedStorageFileStream = _ store.OpenFile("Books.xml", FileMode.Create) data.Save(st) st.Close() End Using End Sub Private Sub BooksGrid_BeginningEdit(ByVal sender As Object, ByVal e As System.Windows.Controls. DataGridBeginningEditEventArgs) _ Handles BooksGrid.BeginningEdit isEditing = True End Sub
'Allows DataGrid editing Private Sub BooksGrid_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Input. KeyEventArgs) Handles BooksGrid.KeyDown If isEditing = False Then 'If the user press Delete, removes the selected item If e.Key = Key.Delete Then
If Me.BooksGrid.SelectedItem IsNot Nothing Then Me.MyBooks.Remove(CType(Me.BooksGrid.SelectedItem, Book)) End If 'If the user press Insert, adds a new empty item to the collection ElseIf e.Key = Key.Insert Then Dim b As New Book With {.DatePublished = Today} Dim index As Integer = MyBooks.IndexOf(CType(Me.BooksGrid. SelectedItem, Book))
MyBooks.Insert(index + 1, b) BooksGrid.SelectedIndex = index BooksGrid.BeginEdit() End If End If End Sub
Private Sub BooksGrid_RowEditEnding(ByVal sender As Object, ByVal e As System.Windows.Controls. DataGridRowEditEndingEventArgs) _ Handles BooksGrid.RowEditEnding isEditing = False End Sub End Class
|
Now right-click the BookStoreTestPage.Aspx
file in Solution Explorer and set it as the start page. Our application
is now ready to be started. One of the biggest benefits of the Windows
Azure SDK tools is that you can test your application locally before
you deploy it to the cloud. This is possible because of the Windows
Azure Simulation Environment that is a full-featured environment
reproducing locally the cloud system.
Testing the Application Locally
When you run an Azure
application locally for the first time, the environment needs to be
initialized. Fortunately Visual Studio and the Windows Azure SDK will
do the work for you. The first thing you notice is that the tools
generate a new database on your machine; this is required for storing
blobs, tables, and queues. This step also reserves local ports for
reaching the previously mentioned contents locally. You can see this
when you press F5.
The Windows Azure Simulation Environment is started, and a dialog shows
the progress of the database generation and IPs initialization, as
represented in Figure 6.
This also creates a
local developer account that replicates on your local machine what you
can activate on the online services. After you click OK, you can see the application correctly running in your web browser. Figure 7 demonstrates this.
You can now try to add or
delete other books and finally save changes. So we reached our
objective locally. The next step should be deploying the application to
the cloud, but doing making this, here’s some brief information about
the Simulation Environment tools. The Simulation Environment is
essentially composed of two main tools: the Development Storage, which
is used for locally storing blobs, tables, and queues, and the
Development Fabric that is useful for monitoring running services. The
Simulation Environment provides a tray bar icon that you can
right-click to access both tools. Figure 8 displays how the Development Fabric gives information about the running application.
It is worth mentioning that the Development Fabric can show information about multiple running Azure services. Figure 9
shows instead the Development Storage UI. Notice that here you can just
enable or disable endpoints for blobs, tables, and queues, but the
suggestion is to leave unchanged the default settings.
Because the application runs correctly, we can now deploy it to the cloud environment of Windows Azure.