Azure Managed Disk VS AWS EBS
Recently Microsoft has added Managed Disk services to Azure Services which is a kind of reduced version as compared to Amazon Web Services (AWS) Elastic Block Store.
Some of the current limitations of Azure Managed Disk Service are
- Dependency on port 8443. Provisioning a VM with extensions will fail without the availability of this port. Also, the deployment status of an extension will be unknown if it is installed on a running VM. If you cannot unblock port 8443, you must use unmanaged disks
- Un-availability of incremental Snapshots. That means you are forced to take full disk copy, which means additional cost and more time to complete the copy.
Apart from these limitation below is the differential matrix between two
Feature | AWS EBS | Azure Managed Disk |
Backup | Implicit | Via Azure Backup Service |
Availability | Auto HA across Availability Zones | Auto HA within the region |
Scalability | Elastic Scaling limited to Storage Type gp2, io1, st1, sc1 | Fixed Size. Add another disk to meet additional storage requirements. |
Pricing | Depends on storage type, size, & IOPS | Depends on Disk Type and size. |
IOPS | Configurable for magnetic and io1 volume types | Fixed |
Encryption | Via AWS Key Management Service | Azure Storage Service Encryption & BitLocker |
Access | Via AWS Identity And Access Management | Azure Role Based Access Control Service |
Snapshot | Both full and incremental | Only full backup |
ProtocolException: The remote server returned an unexpected response: (405) Method Not Allowed.(Resolved)
ProtocolException: The remote server returned an unexpected response: (405) Method Not Allowed.(Resolved)
Last week I face this error while accessing the WebGet method of a restful service. Thanks to Pedrams post for providing the solution.
So here it is.
Solution
The error shows up because without creating a new context, proxy ends up using the POST verb which will eventually cause the above exception
To resolve it we need to create a new OperationContextScope everytime we make a call to a WebGet method.
Sample code:
[ServiceContract]
public interface ITwitterStatus
{
[OperationContract]
[WebGet(UriTemplate = “/statuses/friends.xml”)]
Message GetFriends();
}
public partial class _Client
{
protected string GetFriends()
{
WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
binding.MaxReceivedMessageSize = 99999999;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Transport.Realm = “Twitter API”;
using (WebChannelFactory<ITwitterStatus> cf = new WebChannelFactory<ITwitterStatus>(binding, new Uri(“http://www.twitter.com”)))
{
cf.Credentials.UserName.UserName = “username”;
cf.Credentials.UserName.Password = “password”;
ITwitterStatus proxy = cf.CreateChannel();
using((IDisposable)proxy)
using (new OperationContextScope((IContextChannel)proxy))
{
Message m = proxy.GetFriends();
return(XDocument.Load(m.GetReaderAtBodyContents()).ToString());
}
}
}
Multi Paged Silverlight application consuming ADO.Net Data services
Multi Page Silverlight Application with ADO.NET Data Services – Insert, Update, Delete operations
This article demonstrates how to create a multiple paged Silverlight Application for Insert, Update and Deletion of data exposed by ADO.Net Data Services.
Step 1: We will first create an ADO.Net Data Services application and expose the Northwind DataBase.
Step 2: Create a Multiple Page application with the button to move Next and Previous pages.
Step 3: Orders and Order_Details table will be loaded in the DataGrid in the first page.
Step 4: Clicking “Insert” button will move to next page that will contain a blank form to insert the new row in Order or Order_Details table.
Step 1
- Create a new ASP.Net web site.
- Select to add a new item and select “ADO.Net Data Entities”.
- Select Data from the SQL Server and select all the Tables from Northwind database.
- Again add a new item and select “ADO.Net Data Services”.
- Expose all the Tables of Northwind database by changing the DataContext type to “NorthwindEntities” and set the config.SetEntitySetAccessRule(“*”, EntitySetRights.All)
- Host this web site in IIS.
Step 2
- Create a new Silverlight application and add an ASP.Net web site to host the Silverlight application.
- Select to add a new item and select new user control. Name it, Switcher.xaml.
- Repeat step 2 and this time provide a name, “Page2.xaml”.
- Open App.Xaml.VB file and in the Application startup event, change the instance from New Page1() to New Switcher();
- Open the Switcher.Xaml.vb file and in the initialize method, set me.content=new Page1()
- In the same file, add a new public method called SwitchPage which accepts UserControl as a parameter.
- In this method, set me.content = parameterName;
- Add a button to Page1.Xaml as well as Page2.xaml. In the click event of these buttons, make a call to the SwitchPage method of the Switch Class. We can get the reference of the Switch class by using Me.Parent as Switcher is the parent of both Page1 and Page2. In the SwitchPage method pass the instance of the other page.
Below is the listing of the App.Xaml.Vb Switcher.Xaml.Vb, Page1.Xaml.Vb and Page2.Xaml.Vb files
App.Xaml.Vb
Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
‘Me.RootVisual = New Page()
Me.RootVisual = New Switcher()
End Sub
Switcher.Xaml.Vb
Public Sub New
InitializeComponent()
If Me.Content Is Nothing Then
Me.Content = New Page1()
End If
End Sub
Public Sub PageSwitcher(ByVal Nextpage As UserControl)
Me.Content = Nextpage
End Sub
Page1.Xaml.Vb
Private Sub Button_Click(ByVal sender As System.Object, ByVal e As RoutedEventArgs)
Dim swtch As Switcher = Me.Parent
swtch.PageSwitcher(New Page2())
End Sub
Page1.Xaml.Vb
Private Sub Button_Click(ByVal sender As System.Object, ByVal e As RoutedEventArgs)
Dim swtch As Switcher = Me.Parent
swtch.PageSwitcher(New Page1())
End Sub
Step 3
- Open Page1.xaml and from the toolbox drag and drop the DataGrid.
- Set the AutoGenerateColumns of DataGrid to true.
- Set x:Name to GridEmployees
- Set ItemsSource to “{Binding}”
- Add a Button in the Page1.Xaml and name it btnAdd, set the content to “Add New Employee” and add a click event handler named Button_Click
- Open Page1.Xaml.Vb.
- Define a global level variable
Dim NwindService As NorthwindEntities
Dim curApp As App
- In the Constructor, after the InitializeComponent(), initialize the NwindService and curApp
curApp = Application.Current
NwindService = curApp.NwindService
- Define a DataServiceQuery to fetch the EmployeeSet
Dim dsq As DataServiceQuery(Of Employee) = From emp In NwindService.EmployeeSet Select emp
10. Make a call to the BeginExecute method of the DataServiceQuery
dsq.BeginExecute(New AsyncCallback(AddressOf DataLoadComplete), dsq)
11. Declare the DataLoadComplete method
Private Sub DataLoadComplete(ByVal ar As IAsyncResult)
Dim dsq As DataServiceQuery(Of Employee) = ar.AsyncState
GridEmployees.DataContext = dsq.EndExecute(ar).ToList()
End Sub
12. Define the Button_click event to PageSwitcher method of the Switecher class. For this, first get the reference of the Switcher class by using Me.Parent . Also generate the next employee id to be passed as a parameter to the constructor of the Page2 class.
Dim swtch As Switcher = Me.Parent
Dim emps As List(Of Employee) = CType(GridEmployees.DataContext, List(Of Employee))
Dim EmpIDs As Integer = (From id In emps Order By id.EmployeeID Select id.EmployeeID).Last()
swtch.PageSwitcher(New Page2(EmpIDs + 1))
13. Open Page2.Xaml and place the 4 TextBlock and 4 TextBoxes for EmployeeId, FirstName, LastName and Country. Place a button and attach a click event.
14. Open the Page2.Xaml.Vb. Declare the global label variables NwindService and curApp similar to Page.Xaml.Vb and declare a new constructor that takes NewEmployeeId as Integer as parameter.
Public Sub New(ByVal NewEmpId As Integer)
InitializeComponent()
TxtEmploeeID.Text = NewEmpId.ToString()
curApp = Application.Current
NwindService = curApp.NwindService
End Sub
15. In the Button’s click event define the code to call the AddToEmloyeeSet method of the NwindService and call the BeginSaveChanges method.
Private Sub AddEmp_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
NwindService.AddToEmployeeSet( _
New Employee() With {.EmployeeID = TxtEmploeeID.Text, _
.FirstName = TxtFirstName.Text, _
.LastName = TxtLastName.Text, _
.Country = TxtCountry.Text})
NwindService.BeginSaveChanges(New AsyncCallback(AddressOf Employee_added), Nothing)
End Sub
16. Define the Employee_added method and call the EndSaveChanges method of the NwindService in the try catch block. Finally make a call to the PageSwitcher method of the Switcher class to go back to Page1
Public Sub Employee_added(ByVal res As IAsyncResult)
Try
NwindService.EndSaveChanges(res)
Catch ex As Exception
End Try
Dim swtch As Switcher = Me.Parent
swtch.PageSwitcher(New Page())
End Sub
ADO.Net DataServices and Silverlight
This post describes the complete steps to create an ADO.Net DataServices exposing the SQL Data, using Visual Studio 2008 Professional version and also describes the steps to be taken to create a Silverlight client application to access the data exposed by ADO.Net Data Services. In case, if you’ve got any specific requirement, please feel free to write to me at HarishSuhanda@Gmail.com
Creating the ADO.Net Data Services to expose the PUBS database.
- Open VS2008 and select a ASP.Net Web Site, name it “PubsADOService”.
- Remove the Default.Aspx that is already added in the project.
- Right click on the web site in the “Solution Explorer” and select “Add New Item”.
- Select “ADO.Net Entity Data Model”. Name it, Pubs.edmx
- Click “Yes” to place the code in “ASP_Code” folder.
- Select “Generate from DataBase”, click “Next”.
- Select/create the Connection.
- Clik “Next”.
- Select the Name of the Tables that you want to expose via ADO.Net Data Service. For this demo select all the tables.
10. Rename the Entity Set Names of all the tables by adding “Set”. Thus, the entitis name and Entity Set Name should be, Titles and TitlesSet, author and authorSet like wise…
11. Click “Save All”.
12. Open the Solution Explorer and repeat step 3 to add “New Item”.
13. Select “Ado.Net Data Service”. Name it “PubsDataService.svc”. Click “Add” button.
14. In the “PubsDataService.svc.vb” or “PubsDataService.svc.cs”, whichever application (.vb is for Visual Basic and .cs is for C#). Replace the code,
Inherits DataService(Of [[class name]])
With
Inherits DataService(Of pubsModel.pubsEntities)
15. In the InitializeService method, un comment the code to SetEntityAccessRule. (By default all the entities defined in the EntitiyModel has restrictsions. The will be blocked by default unless the EntitiyAccessRule is not defined)
16. Replace “MyEntitySet” with the name of the entityset that you want to expose. To expose all the entities, set
config.SetEntitySetAccessRule(“*”, EntitySetRights.All)
17. Click “Save All”. Now the PubsDataService is avalable to be hosted.
18. Run the PubsDataService web site.
Create the Silverlight client to access the PubsDataService created above.
- Create a new Silverlight project in VS2008. Name it, “Client_PubsDataService”.
- Click “Yes” to add an asp.net project to host the Silverlight application.
- Right click on the Client_PubsDataService in the solution explorer and select “Add Service Reference….”.
- Switch to PubsDataService created in above steps and run it.
- Copy the URL of the PubsDataService.svc file, which is something like (except the port number will be different) http://localhost:49165/PubsADOService/PubsDataService.svc/
- Keep this application running and switch to “Client_PubsDataService” application.
- Pate the copied URL in the “Address” field of the “Add Service Reference….” Dialog box and click “Go”.
- The “PubsDataService” will be identified and on expanding it, you will see all the entities that are exposed by the service.
- Change the name of the service to “PubsServiceReference” and click “OK”
10. Open Page.xaml and add a ComboBox to the “LayoutGrid”.
11. Add 2 Rows to grid, using
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
12. Place a “DataGrid” from toolbox below the ComboBox.
13. Assign a name to the ComboBox, bind the itemssource and attach the SelectionChanged event. <ComboBox x:Name=”lstEntities” ItemsSource=”{Binding}” SelectionChanged=”lstEntities_SelectionChanged”></ComboBox>
14. Assign a name to the DataGrid and bind the itemssource property. <data:DataGrid x:Name=”GridDisplayData” Grid.Row=”1″ ItemsSource=”{Binding}”></data:DataGrid>
15. Switch to code view of the Page.Xaml. Define a global variable named “PubsService” of type PubsServiceReference.pubsEntities
16. In the constructor, after the InitializeComponents method, initialize the PubsService by passing the Uri object. The Uri object should be created using two parameters, the url of the PubsDataService ie, http://localhost:49165/PubsADOService/PubsDataService.svc/ and Uri type which is Absolute.
17. Add the name of the entities to the lstEntities that you disposed via the Service. Using lstEntities.Items.Add(“SalesSet”), lstEntities.Items.Add(“StoreSet”) like wise all the entities.
18. In the lstEntities_SelectionChanged event, put a Select Case statement, Select Case lstEntities.SelectedIndex. For each selectedIndes write the code to fetch the data from the EntitySet using the code below:
Like for Authors:
Case 1
Dim dsq As System.Data.Services.Client.DataServiceQuery(Of PubsServiceReference.author)
dsq = CType(PubsService.authorSet, System.Data.Services.Client.DataServiceQuery(Of PubsServiceReference.author))
dsq.BeginExecute(New AsyncCallback(AddressOf Authors_LoadComplete), dsq)
- Define the Authors_LoadComplete event using following code and bind the result to the Grid.
Private Sub Authors_LoadComplete(ByVal ar As IAsyncResult)
Dim qry As System.Data.Services.Client.DataServiceQuery(Of PubsServiceReference.author) = _
CType(ar.AsyncState, System.Data.Services.Client.DataServiceQuery(Of PubsServiceReference.author))
Dim Authors = qry.EndExecute(ar).ToList
GridDisplayData.DataContext = Authors
GridDisplayData.AutoGenerateColumns = True
End Sub
OutPut:
Accessing ScriptableType objects of Silverlight from JavaScript
This post describes, how to access the custom objects defined in Silverlight via Javascript. It also shows how to access the content of Silverlight TextBox from Javascript.
Creating a ScriptableType object in Silverlight Application
The ScriptableType attribute and ScriptableMember attribute defined in the System.Windows.Browser interface is used to make an object available to the client side.
Thus, we will declare a Person class with two properties, FName and LName and implement the INotifyPropertyChanged Interface so that the changes made to these properties can be reflected to all the objects that are accessing it.
Use the below code to define the Person Class.
Imports System.Windows.Browser
<ScriptableType()> _
Public Class Person
Implements System.ComponentModel.INotifyPropertyChanged
Public Sub New()
End Sub
Private Sub PropertyChangedCaller(ByVal PropertyName As String)
RaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs(PropertyName))
End Sub
Private _FName As String
<ScriptableMember()> _
Public Property FName() As String
Get
Return _FName
End Get
Set(ByVal value As String)
_FName = value
PropertyChangedCaller(“FName”)
End Set
End Property
Private _LName As String
<ScriptableMember()> _
Public Property LName() As String
Get
Return _LName
End Get
Set(ByVal value As String)
_LName = value
PropertyChangedCaller(“LName”)
End Set
End Property
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
Creating Person Object in XAML and Binding the values to Silverlight TextBox controls
We will now create the object of Person class under the UserControl.Resources, declared above and then bind it to the TextBoxes. Use the following code for the same:
<UserControl.Resources>
<local:Person x:Name=”PersonObject” FName=”FirstName” LName=”LastName” />
</UserControl.Resources>
Use the code below to create the grid with text boxes and labels and bind them to above created resources:
<Grid x:Name=”LayoutRoot” Background=”White” DataContext=”{StaticResource PersonObject}”>
<Grid.ColumnDefinitions>
<ColumnDefinition/><ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/><RowDefinition/><RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Column=”0″ Grid.Row=”0″ Text=”First Name:”/>
<TextBlock Grid.Column=”0″ Grid.Row=”1″ Text=”Last Name:”/>
<TextBox Grid.Row=”0″ Grid.Column=”1″ Text=”{Binding FName, Mode=TwoWay}” />
<TextBox Grid.Row=”1″ Grid.Column=”1″ Text=”{Binding LName, Mode=TwoWay}” />
<TextBlock Text=”{Binding FName}” Grid.Row=”2″ Grid.Column=”0″/>
<TextBlock Text=”{Binding LName}” Grid.Row=”2″ Grid.Column=”1″/>
</Grid>
Registering the Person Object
To make the PersonObject available to clientside, we need to register the object, using the Browser.HtmlPage.RegisterScriptableObject. We may do this in the Page_Loaded event of the Silverlight application:
Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
‘Access the PersonObject defined under the UserControl.Resources
Dim personObject As Person = Me.Resources(“PersonObject”)
Browser.HtmlPage.RegisterScriptableObject(“PersonObject”, personObject)
End Sub
Accessing the PersonObject from JavaScript
The PersonObject created above is now ready to be accessed from the JavaScript. Create a variable referencing the SilverlightPlugin in the ASPX Page. Next, access the Content of the SilverlightPlugin using the Content property. Finally, access the PersonObject from the Content of the SilverlightPlugin
var silverlightplugin = $get(“Xaml1”);
var content = silverlightplugin.content;
var personObject = content.PersonObject;
Using the personObject, we may access it public properties. Thus,
alert(“Name = ” + personObject.FName + ” ” + personObject.LName);
will show the current content from the TextBoxes in the Silverlight TextBoxes as displayed below:
Sending Objects from .ASPX page to Silverlight
Sending Simple User Defined Objects from ASPX page to Silverlight Application.
This article describes how to send a user defined object created in ASP.Net application across Silverlight application. We will walk though creating a Simple User Defined object in ASPX page called Person and another object called People containing the list of Person.
We will use XMLSerializer to serialize the People class and add the xml content to the InitParametes of the <ASP:Silverlight /> object.
We will then extract the xml from InitParameters in the StartUp_Application event of the Silverlight and fill the data back in the People Class defined in Silverlight application as well.
Creating ASP.Net application to create a list of CustomObject
- Create a Silverlight application and choose ASP.Net Web Site to host the Silverlight application.
- Open the ProjectName.Web project and open the Silverlight test page.
- Add a server tag in the .aspx page and add the code to define the Person.
- Mark the class Serializable.
- Create another class People which contains the list of Person.
- Mark this class as Serializable too.
- Create an object of People and add the Person to list of Person.
<Serializable()> _
Public Class Person
Implements System.ComponentModel.INotifyPropertyChanged
Public Sub New()
End Sub
Private Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(info))
End Sub
Private _FirstName As String
Public Property FirstName() As String
Get
Return _FirstName
End Get
Set(ByVal value As String)
_FirstName = value
NotifyPropertyChanged(“FirstName”)
End Set
End Property
Private _LastName As String
Public Property LastName() As String
Get
Return _LastName
End Get
Set(ByVal value As String)
_LastName = value
NotifyPropertyChanged(“LastName”)
End Set
End Property
Private _Age As Integer
Public Property Age() As Integer
Get
Return _Age
End Get
Set(ByVal value As Integer)
_Age = value
NotifyPropertyChanged(“Age”)
End Set
End Property
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
<Serializable()> _
Public Class People
Private _Persons As System.Collections.Generic.List(Of Person)
Public Sub New()
Persons = New System.Collections.Generic.List(Of Person)
End Sub
Public Property Persons() As System.Collections.Generic.List(Of Person)
Get
Return _Persons
End Get
Set(ByVal value As System.Collections.Generic.List(Of Person))
_Persons = value
End Set
End Property
End Class
Serializing the list of CustomObject and setting it to InitParameters
- Serialize it using XMLSerializer.
- Using the StringWriter class, write the serialized string to a Serialized variable.
- Set the InitParameters of Silverlight object to “People=” + StringWriterObject.ToString
Dim xmlFrmtr As New System.Xml.Serialization.XmlSerializer(ppl.GetType)
Dim txtWrt As New System.IO.StringWriter()
xmlFrmtr.Serialize(txtWrt, ppl)
Xaml1.InitParameters = “People=” + txtWrt.ToString
Accessing the InitParameters in the Silverlight application.
- Open the Silverlight application and open the App.Xaml.Vb file
- In the App Class, add a public property called InitParams as Dictionary of string, string.
- In the Application_Startup event set the InitParams equal to e.InitParams
- In the Page_Loaded event of Siliverlight in “Page.Xaml.Vb”, create an instance of Application class and assign Application.Current to it.
- Create a StringReader and read all the content of People, which is a XML document.
- Use the XML Reader to read the xml from the String Reader.
- Extract the values from XmlReader and parse it into the People/Person class defined in the Silverlight Application.
Dim app As App = Application.Current
Dim xrDr As XmlReader = XmlReader.Create(New System.IO.StringReader(app.InitParams(“People”)))
Dim ppl As New People()
While xrDr.Read()
If xrDr.IsStartElement And xrDr.Name = “Person” Then
Dim prsn As New Person()
xrDr.ReadToFollowing(“FirstName”)
prsn.FirstName = xrDr.ReadElementContentAsString()
xrDr.ReadToFollowing(“LastName”)
prsn.LastName = xrDr.ReadElementContentAsString()
xrDr.ReadToFollowing(“Age”)
prsn.Age = xrDr.ReadElementContentAsInt
ppl.Persons.Add(prsn)
End If
End While
Silverlight2.0 Nested DataGrid using Silverlight-enabled WCF Services and LINQ to SQL
Create new project.
- Create a new Silverlight project in Visual Studio 2008 or Visual Web Developer 2008 and select a new Web Site to host the Silverlight application. Name it “Silverlight_MasterDetailsGrid”
- When the IDE opens, we have 2 projects listed. Silverlight_MasterDetailsGrid and Silverlight_MasterDetailsGrid.Web. The Web application has a Silverlight_MasterDetailsGrid.TestPage.aspx which hosts the .zap file created by Silverlight_MasterDetailsGrid.
Add Linq to SQL Classes
- Select Silverlight_MasterDetailsGrid.Web project in Solution Explorer and right click to add new item.
- Select “LINQ to SQL Classes”.
- Name the File to “Nwind.dbml” and click OK
- Drag and Drop the Orders and Order_Details table from Server Explorer.
- Right click on any blank space in Nwind.dbml file and select “Properties”.
- Set SerializationMode to “Unidirectional”. [Currently, WCF does not support Cyclic Reference Serialization (like in dbml file the Order Table contains a Order_Detail filed and Order_Detail Table contains the Order field. Setting the SerializationMode to Unidirectional will serialize only tables excluding the referential table/fields)
- Click Save. [The Nwind.Designer.VB file will have all the classes with the DataContract attribute applied to Order and Order_Detail tables and DataMember attribute to the properties of these tables. This will make these classes serializable thus ready to be used in WCF Services]
Add WCF Service.
- Select Silverlight_MasterDetailsGrid.Web project in Solution Explorer and right click to add new item.
- Select “Silverlight-enabled WCF Service”
- Name the file “WCFService.svc” and click “OK”
- The Visual Studio will open the WCFService.svc.vb file with a class with dummy Service Contract and Operation Contract.
- Click “Project” menu and select “Add New Item”.
- Select Interface and Name it “IWCFService.vb”. Click “OK”
- Imports two Interfaces, System.ServiceModel and System.ServiceModel.Activation
- Add ServiceContract attribute to IWCFService Interface and define two OperationContracts GetOrders and GetAllOrderDetails. Thus the IWCFService.vb should look like:
Imports System.ServiceModelImports System.ServiceModel.Activation<ServiceContract()> _
Public Interface IWCFService <OperationContract()> _ Function GetOrders() As IEnumerable(Of Order) <OperationContract()> _ Function GetAllOrderDetails() As IEnumerable(Of Order_Detail) End Interface |
9. Open WCFService.svc.vb and delete all content of the Class and its ServiceContract attribute.
10. Implement IWCFService Interface in the WCFService Class. This class will have only one attribute [AspNetCompatibilityRequirements].
11. Implement the GetOrders and GetAllOrderDetails functions
12. The WCFService.svc.vb should now look like:
Imports System.ServiceModelImports System.ServiceModel.Activation<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)> _
Public Class WCFService Implements IWCFService Public Function GetOrders() As IEnumerable(Of Order) Implements IWCFService.GetOrders Dim DC As New NwindDataContext() Return DC.Orders.AsEnumerable() End Function Public Function GetAllOrderDetails() As IEnumerable(Of Order_Detail) Implements IWCFService.GetAllOrderDetails Dim DC As New NwindDataContext() Return DC.Order_Details.AsEnumerable End Function End Class |
13. Open Web.Config file and change the Contract in Endpoint section from Silverlight_MasterDetailsGrid.Web.WCFService to Silverlight_MasterDetailsGrid.Web.IWCFService
This finalizes our WCF service and makes it ready to be hosted.
Defining the Service Reference in client to consume the above created WCFService
- In the Solution Explorer, expand the “Silverlight_MasterDetailsGrid” project. Right click on it and click “Add Service Reference”.
- Click “Discover” to locate the WCFService automatically.
- Name the Service “NwindWcfReference”
Adding DataGrid to Silverlight application
- Open Page.xaml and drag and drop the DataGrid from ToolBox to the Code window, under LayoutRoot grid.
- Name the DataGrid by adding x:Name attribute to “GrdOrders”.
- Set AutoGenerateColumns to True.
- Set ItemsSource to “{Binding}”. This will bind the DataGrid to its DataContext.
Thus, the DataGrid definition should look like:
<data:DataGrid x:Name=”GrdOrders” AutoGenerateColumns=”True” ItemsSource=”{Binding}”/>
Binding GrdOrders DataGrid to Orders
- Open Page.xaml.vb.
- Imports Silverlight_MasterDetailsGrid.NwindWcfReference
- Imports System.Collections.ObjectModel
- Add a class level variable Orders of type ObservableCollection(Of Order)
- Add another class level variable wcfClient of type WCFServiceClient
- In the constructor initialize the Orders and wcfClient variables after InitializeComponent()
- In the Page_Loaded event add the event handler to the wcfClient, using AddHandler WcfClient.GetOrdersCompleted, AddressOf GetOrdersCompleted
- Call the WcfClient.GetOrdersAsync() method
- Define the GetOrdersCompleted method Public Sub GetOrdersCompleted(ByVal sender As Object, ByVal e As GetOrdersCompletedEventArgs)
- Set Orders = e.Result
- Set GrdOrders.DataContext = Orders
Run the application and see the all records with all the columns of Orders table are displayed in the DataGrid.
Defining RowDetailsTemplate to create nested DataGrid
- Open the Page.xaml and add the RowDetailsTemplate to GrdOrders.
- Define the DataTemplate.
- Add DataGrid to DataTemplate and name it GrdDetails.
- Set it’s AutoGenerateColumn property to “True”
Thus the resulting XAML of Complete DataGrid should look like:
<data:DataGrid x:Name=”GrdOrders” AutoGenerateColumns=”True” ItemsSource=”{Binding}”> <data:DataGrid.RowDetailsTemplate> <DataTemplate> <data:DataGrid x:Name=”GrdDetails” AutoGenerateColumns=”True” ItemsSource=”{Binding Order_Details}”></data:DataGrid> </DataTemplate> </data:DataGrid.RowDetailsTemplate> </data:DataGrid> |
Calling the GetAllOrderDetailsAsync and binding the inner DataGrid to Order_Detail
- Add another class level variable allOrder_Detais of type ObservableCollection(Of Order_Detail)
- In the Page_Loaded event, add the WcfClient.GetAllOrderDetailsCompleted handler.
- In the GetOrdersCompleted event, make a call to WcfClient.GetAllOrderDetailsAsync()
- Define the GetAllOrderDetailsCompleted and add following code that
- Fetches all the rows and columns of the Order_Details table and store it in allOrder_Detais variable.
- Loop through all the Order in Orders and using LINQ query find all the OrderDetails from allOrder_Detais whose OrderId is equal to Order.OrderID
- Create a temporary ObservalbleCollection(of Order_Detail) and insert items of Order_Detail fetched in steps b.
- Assign the temporary collection created in steps c to Order.Order_Details
- Set the GrdOrders.DataContext to Orders
The resulting GetAllOrderDetailsCompleted function should be:
Public Sub GetAllOrderDetailsCompleted(ByVal sender As Object, ByVal e As GetAllOrderDetailsCompletedEventArgs)
allOrder_Detais = e.Result
For Each o As Order In Orders
Dim tempOrder_Details = From allDetails In allOrder_Detais Where allDetails.OrderID = o.OrderID Select allDetails
Dim tempDetails As New ObservableCollection(Of Order_Detail)
For Each item In tempOrder_Details
tempDetails.Add(item)
Next
o.Order_Details = tempDetails
Next
GrdOrders.DataContext = Orders
End Sub