Sunday, December 6, 2009

Beginner's Guide to Work With Azure Table Storage and Silverlight Episode 2

In the last post we started a project with cloud Service and ASP.net MVC 2 Application then we connected this Application with a Silverlight Client using WCF Service. Now in this post we will create an Entity in Azure Table and a Silverlight application to Insert Students in Azure Table.

  • Open the Project we Created in last post and in MVC Project add a class and name it Student.cs.
  • Add a using statement in Student.cs
using Microsoft.WindowsAzure.StorageClient;

Now derive class Student.cs from TableServiceEntity now add following properties in Student.
      
public string StudentClass {
            get {
                return PartitionKey;
            }
            set {
                PartitionKey = value;
            }
        }

        public string StudentID {
            get {
                return RowKey;
            }
            set {
                RowKey = value;
            }
        }
        public int Age { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }

  • This class represents the logical model of the Azure Table. We have assigned PartitionKey value of variable named Class, so that Students Studying in a Class will be available on the same node and RowKey is assigned value of StudentID because StudentID is always unique field in a Class.
  • Now we need another class extending TableServiceContext. This class provides the functionality to access the table Storage.
  • Add another class in MVC Project and name it StudentContext.cs and add using statements

using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure;

  • Now derive StudentContext.cs from TableServiceContext and add following constructor in it.
public StudentContext(string BaseAddress, StorageCredentials credentials)
            : base(BaseAddress, credentials)
        {
       
        }

  • Add an assembly named System.Data.Services.Client and a using statement;

                     using System.Data.Services.Client; 

  • Add a Property named StudentsTable which returns IQueryable of type Student:

public IQueryable<Student> StudentsTable
        {
            get {
                return this.CreateQuery<Student>(“StudentsTable”);
            }       
        }

  • In Cloud project Under The Folder Roles right click on StudentRole and select properties. In the Dialog shown click Settings Tab in Side bar then press Add Setting button. Name it DataConnectionString select ConnectionString  in Type Field. Press Browse button at next shown dialog Press OK to select local development account; Save settings (Ctrl+S) and close it.

  • Now Add these statements in WebRole.cs File in MVC Project in OnStart() function before the return statement.

Microsoft.WindowsAzure.CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                configSetter(Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(configName));
            });

  • Now Although we are done and we can start working on Table Storage in our WCF Service but it would good to use a Repository for each Table. So defining a repository for Student Entity. Create a new class in MVC Project Name it StudentRepository.cs.
  • Add following code in it.

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace StudentRole
{
    public class StudentRepository
    {
        private static CloudStorageAccount storageAccount;
        static StudentRepository()
        {
            storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
            CloudTableClient.CreateTablesFromModel(
                            typeof(StudentContext),
                            storageAccount.TableEndpoint.AbsoluteUri,
                            storageAccount.Credentials);
        }

        public void AddStudent(Student newStudent)
        {
            StudentContext ctx = new StudentContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
            ctx.AddObject("StudentsTable", newStudent); //String literal must be the name given to property in StudentContext
            ctx.SaveChanges();
        }

        public IEnumerable<Student> GetAllStudents()
        {
            StudentContext ctx = new StudentContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
            var students = from s in ctx.StudentsTable
                           orderby s.StudentID
                           select s;
            return students.ToList();
        }

        public void UpdateStudent(Student newStudent)
        {
            StudentContext ctx = new StudentContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
            Student oldStudent = ctx.StudentsTable.Where(
                                        s => s.StudentClass == newStudent.StudentClass
                                                        &&
                                             s.StudentID == newStudent.StudentID).FirstOrDefault();
            if (oldStudent != null)
            {
                oldStudent.Name = newStudent.Name;
                oldStudent.Address = newStudent.Address;
                oldStudent.Age = newStudent.Age;
                oldStudent.StudentClass = newStudent.StudentClass;
                oldStudent.StudentID = oldStudent.StudentID;
                ctx.UpdateObject(oldStudent);
                ctx.SaveChanges();
            }
        }

        public void DeleteStudent(string StudentClass, string StudentID)
        {
            StudentContext ctx = new StudentContext(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials);
            Student student = ctx.StudentsTable.Where(s => s.StudentID == StudentID && s.StudentClass == StudentClass).FirstOrDefault();
            if (student != null)
            {
                ctx.DeleteObject(student);
                ctx.SaveChanges();
            }
        }
    }
}

  • Now Add following function definitions in IStudentService.cs file.

[OperationContract]
List<Student> GetAllStudents();
[OperationContract]
void InsertStudent(Student st);
[OperationContract]
void UpdateStudent(Student newStudent);
[OperationContract]
void DeleteStudent(string StudentClass, string StudentID);

  • Add following code in StudentService.svc

public class StudentService : IStudentService
    {
        #region IStudentService Members

        public List<Student> GetAllStudents()
        {
            StudentRepository repo = new StudentRepository();
            return repo.GetAllStudents().ToList();
        }

        public void InsertStudent(Student st)
        {
            StudentRepository repo = new StudentRepository();
            repo.AddStudent(st);
        }

        public void UpdateStudent(Student newStudent)
        {
            StudentRepository repo = new StudentRepository();
            repo.UpdateStudent(newStudent);
        }

        public void DeleteStudent(string StudentClass, string StudentID)
        {
            StudentRepository repo = new StudentRepository();
            repo.DeleteStudent(StudentClass, StudentID);
        }
        #endregion
    }

  • Finally All the work at server side is done we have created Entity, Context, Repository and WCF Service having CRUD Functions now we need a client.
  • Open Home.xaml in Silverlight Project replace the Contents with these markup.

<navigation:Page x:Class="AzureTableClient.Home"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
    Title="Home"
    Style="{StaticResource PageStyle}" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data">

  <Grid x:Name="LayoutRoot">
    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">

      <StackPanel x:Name="ContentStackPanel" Orientation="Vertical">

        <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
                           Text="Home"/>
                <data:DataGrid AutoGenerateColumns="False" Height="100" Name="StudentsDisplay" Width="Auto" IsReadOnly="True" Margin="10,20,10,10" />
                <StackPanel Name="PanelBtns" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20">
                    <Button Content="List All Students" Height="23" Name="btnListAll" Width="100" Background="#FF25DE25" Margin="5" />
<Button Content="Insert Student" Height="23" Name="btnInsert" Width="100" Background="#FF25DE25" Margin="5" Click="btnInsert_Click" />                    <Button Content="Delete Student" Height="23" Name="btnDelete" Width="100" Background="#FF25DE25" Margin="5" />
                    <Button Content="Update Student" Height="23" Name="btnUpdate" Width="100" Background="#FF25DE25" Margin="5" />
                </StackPanel>
            </StackPanel>

    </ScrollViewer>
  </Grid>

</navigation:Page>

  • Now move to Code behind file and add a using statement:

using AzureTableClient.StudentSvc;

  • Add following code in code behind File.

private void btnInsert_Click(object sender, RoutedEventArgs e)
        {
            StudentServiceClient proxy = new StudentServiceClient();
            proxy.Endpoint.Address = new System.ServiceModel.EndpointAddress("
http://localhost:81/StudentService.svc");
            Student st = new Student{ Address = txtAddress.Text,
                                      Age = Convert.ToInt32(txtAge.Text),
                                      Name = txtName.Text,
                                      StudentClass = txtClass.Text,
                                      StudentID = txtID.Text};
            proxy.InsertStudentCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(proxy_InsertStudentCompleted);
            proxy.InsertStudentAsync(st);
        }

        void proxy_InsertStudentCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Error == null)
                MessageBox.Show("Insertion Completed Successfully");
        }

  • Hit F5 and fill all the Student details and Pressing Insert Button will Insert the Student Record in Azure Table, on Successful return it will pop up a message dialog with Success full Insertion Message.

13 Insertion Completed Screen

  • To make sure that Entity has been inserted in Azure Table, Open SQLExpress Management Console.  This snap shows SQLExpress 2008 Management Console in the Tables section 02 tables are circled they contain data for every Azure Table Entity.

13 SQLExpressView

14 SQLExpressView

This Snap is the result of select Query on Last Table named TableRow, This is the Place where all the Entities are stored.

  • In this post we have covered
    • How to create Entity for Azure Table
    • Creating Context for Entity
    • Creating Repository for Bridging WCF Service and EntityContext
    • A Simple Silverlight Client to Insert Student Object.
  • what we will cover in next Post
    • Update, Delete and Retrieve Operations from Silverlight Client.

Download Complete code of Episode 2 from Here

Friday, December 4, 2009

Beginner's Guide to Work With Azure Table Storage and Silverlight Episode 1




In This Tutorial we will Create a Single Entity Azure Table named Student with Silverlight Client performing CRUD Operation on the table.

  • In the First Step Create a Cloud Service with an ASP.net MVC 2 Project:



  • As you Press OK following Dialog Will be displayed.
    • Double Click on ASP.NET MVC 2 Web Role this will add ASP.NetMVC role in right Pane. Rename it to StudentRole.



  • On the next Screen Select "No Do not Create Test Project" Option on the next Screen. As the Project Creation Completed Test it by hitting key F5. Following Screen will be displayed which is part of MVC Template and Created by the wizard as you chose MVC project.



  • Now  Add Silverlight Navigation Application Project into the solution and name it AzureTableClient.

 

  • When you will press OK button following dialog will be displayed Uncheck the Option "Make it the Start Page".



  • As you further press OK button two files will be Added in MVC Project named "AzureTableClientTestPage.aspx and AzureTableClientTestPage.html". Open file AzureTableClientTestPage.html and Press Ctrl + A to Select all then Ctrl + C to Copy.
  • Now in  Expand Views folder in MVC Project and then expand Home Folder.




  • Now open Index.aspx file and except first line delete every code it have now paste the code you copied from AzureTableClientTestPage.html
  • Now in the first line of Index.aspx Delete "MasterPageFile" Attribute since our Client Application will be in Silverlight therefore we don't need master page. Also change the path of Silverlight.js file in Script Tag to
<script type="text/javascript" src="../../Silverlight.js"></script>



  • Now we are good to Test Our Project as Silverlight Application is embedded in default View of MVC Application. Hit F5 to Test the Application.




  • As Silverlight runs on client machine it needs a web service to communicate with web server. Add a WCF Service in MVC Project and name it "StudentService".
  • Open "Web.config" and find Endpoint definition Tag and change  value of binding attribute from wsHttpBinding to basicHttpBinding.
  
  • In "IStudentService.cs" change the return type of function definition DoWork() to string. e.g string DoWork();
  • And change the Implementation of DoWork function in "StudentService.svc" to:
       public string DoWork()
        {
            return "WCF Responded......";
        }

  • Press F6 to Build Solution.
  • Right Click on Silverlight Project and Select "Add Service Reference" in the dialog press discover button. Enter StudentSvc in Namespace field.


  • Add using statement in App.xaml.cs
using AzureTableClient.StudentSvc;

  • Add a factory method in App.xaml.cs to create Student Service Client Proxy Object.
         public static StudentServiceClient CreateStudentClient()
        {
            StudentServiceClient svc = new StudentServiceClient();
            svc.Endpoint.Address = new System.ServiceModel.EndpointAddress(new Uri("http://127.0.0.1:81/StudentService.svc"));
            return svc;
        }
  • Open Home.xaml.cs in Silverlight Project and add a using statement 
using AzureTableClient.StudentSvc;
  • Add these lines in constructor of Home.xaml.cs to Access WCF Service.
            StudentServiceClient svc = App.CreateStudentClient();
            svc.DoWorkCompleted += new EventHandler(svc_DoWorkCompleted);
            svc.DoWorkAsync();


  • Add function svc_DoWorkCompleted in Home.xaml.cs.
        void svc_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                ContentText.Text = e.Result;
            }
        }

  •  To Access WCF from the Cloud Project we need "ClientAccessPolicy.xml" file in the Project where WCF Service is hosted this file can be downloaded from here
  • Now Hit F5 to Run The Application.

  •  In this post We have covered:
    • Silverlight Navigation Application hosted in MVC Application.
    • Silverlight WCF Communication tested.
  • In the next post we will cover 
    • Azure Table Entity Creation
    • Azure Table Creation
    • Operations on Azure Table from Silverlight Client.
Download complete code from here