Monday, 4 July 2011

Passing Objects between ASP.NET and Silverlight Controls.

This is Part –2 of my previous post “Passing parameters between Silverlight and ASP.NET – Part 1

In my previous post I have showed how to pass parameters between Silverlight and ASP.NET using Query Strings, Init Parameters and HtmlPage.Document. These techniques are good as long as you are dealing with small amount of data and have certain limitation. There are some scenario where we have to pass large number of data from asp.net to Silverlight and back from Silverlight to asp.net and our architecture design does not permit us to connect to Database directly from Silverlight component.

Today I am going to show you how we can use Object Serialization to achieve the same. but remember using this also poses some serious performance issues, so use this only when you really need this scenario. Internally this technique uses the HtmpPage.Document method only.

Just to give you a fair idea how I can do this I have created a sample Silverlight Application using Visual Studio Web Developer 2010, and added a class file called Employee.cs. This file just holds few entities of Employee and EmployeeDetails. Just to give you a feel of actual scenario I have created the Employee and EmployeeAddress as a separate class and written a method to return the sample data from this classes.

EmployeeAddress Class

   1: public class EmployeeAddress



   2: {



   3:     [XmlAttribute]



   4:     public string Address { get; set; }



   5:     



   6:     [XmlAttribute]



   7:     public string City { get; set; }



   8:  



   9:     [XmlAttribute]



  10:     public string PinCode { get; set; }



  11: }




Employee Class





   1: [XmlRoot("Employee")]



   2: public class Employee



   3: {



   4:     [XmlElement]



   5:     public string EmployeeName { get; set; }



   6:  



   7:     [XmlElement]



   8:     public EmployeeAddress EmployeeAddresses { get; set; }



   9:  



  10:     [XmlElement]



  11:     public int Age { get; set; }



  12:  



  13:     public List<Employee> GetEmployeeData()



  14:     { 



  15:         List<Employee> employees = new List<Employee>();



  16:         employees.Add(new Employee { EmployeeAddresses = new EmployeeAddress { Address = "V.B.Layout", City = "Bangalore", PinCode = "560076" }, Age = 33, EmployeeName = "Brij Mohan" });



  17:         employees.Add(new Employee { EmployeeAddresses = new EmployeeAddress { Address = "Beauty Layout", City = "Delhi", PinCode = "111111" }, Age = 33, EmployeeName = "Arun Dayal Udai" });



  18:         employees.Add(new Employee { EmployeeAddresses = new EmployeeAddress { Address = "Mumbai Filmcity Layout", City = "Mumbai", PinCode = "444444" }, Age = 33, EmployeeName = "Sarosh Kumar" });



  19:         employees.Add(new Employee { EmployeeAddresses = new EmployeeAddress { Address = "Dimna Road", City = "Jamshedpur", PinCode = "831018" }, Age = 33, EmployeeName = "Bharti Priyadarshini" });



  20:  



  21:         return employees;



  22:     }



  23:  



  24:     public string GetSerializedEmployeeData()



  25:     {



  26:         MemoryStream mem = new MemoryStream();



  27:         System.Xml.Serialization.XmlSerializer xs = new XmlSerializer(typeof(List<Employee>));



  28:         mem.Seek(0, SeekOrigin.Begin);



  29:         xs.Serialize(mem, GetEmployeeData());



  30:         byte[] data = mem.GetBuffer();



  31:         string xmlString = Encoding.UTF8.GetString(data, 0, data.Length);



  32:         return xmlString;



  33:     }



  34:  



  35:     public List<Employee> GetDesializedEmployeeObject(string xmlData)



  36:     {



  37:         StringReader sr = new StringReader(xmlData);



  38:         XmlSerializer xs = new XmlSerializer(typeof(List<Employee>));



  39:         object employees = xs.Deserialize(sr);



  40:  



  41:         return (List<Employee>)employees;



  42:     }



  43: }






In the employee class above I have also written few helper methods to Serialize and de-serialize the objects, using XMLSerializer.



Now coming back to the code behind of my default.aspx page, here I am only trying to simulate the actual scenario. On Page load I am getting my dummy data and putting this data into a Hidden Filed. In actual environment you may get this data from Database and then putting this into some hidden field.





   1: protected void Page_Load(object sender, EventArgs e)



   2: {



   3:     Employee emp = new Employee();



   4:     txtValue.Text = HttpUtility.HtmlEncode(emp.GetSerializedEmployeeData());



   5: }






You may notice that I have used HttpUtility.HtmlEncode, this is very important because we are passing XML Data during Postbacks, failing to use this may give you the following error, which you may not like to see.



Server Error in '/' Application.



A potentially dangerous Request.Form value was detected from the client (txtValue="<?xml version="1.0"?...").



image



Ok now my asp.net is ready to send data to Silverlight Control, its now Silverlight turn to get this data and parse it into Silverlight recognized format which Silverlight controls will understand.



First I am adding the same employee class to Silverlight project for de serializing the received serialized data from ASP.NET. To avoid duplication of data, I am adding the same class file to my Silverlight Project using Add as Link option from file dialogue.



First right click you Silverlight Project and Select Add –> Existing Item



image



Now, locate you Employee.cs file from the ASP.NET website project, and select Add As Link option from Add. This wil basically create a shortcut to Employee.cs from your ASP.NET Application to your Silverlight Project, basically both are same copy so before make any ASP.NET only specific changes to this file make sure this should compile in your Silverlight application too, or  Vice Versa.



image









Now once the shortcut of the Employee is created in your Silverlight Application, we can use this class just like the normal class file. Now coming back to my Silverlight Application open the MainPage.xaml, open the XAML View. To display the data I have added a DataGrid and ListView of the Address Item on the XAML Page.





   1: <Grid x:Name="LayoutRoot" Background="White">



   2:         <sdk:DataGrid AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" ItemsSource="{Binding}" Name="employeeDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="361" SelectionChanged="employeeDataGrid_SelectionChanged">



   3:         <sdk:DataGrid.Columns>



   4:             <sdk:DataGridTextColumn x:Name="ageColumn" Binding="{Binding Path=Age}" Header="Age" Width="SizeToHeader" />



   5:             <sdk:DataGridTextColumn x:Name="employeeNameColumn" Binding="{Binding Path=EmployeeName}" Header="Employee Name" Width="SizeToHeader" />



   6:         </sdk:DataGrid.Columns>



   7:     </sdk:DataGrid>



   8:     <Grid x:Name="employeeDetailList" HorizontalAlignment="Left" Margin="454,19,0,0" VerticalAlignment="Top">



   9:         <Grid.ColumnDefinitions>



  10:             <ColumnDefinition Width="Auto" />



  11:             <ColumnDefinition Width="Auto" />



  12:         </Grid.ColumnDefinitions>



  13:         <Grid.RowDefinitions>



  14:             <RowDefinition Height="Auto" />



  15:             <RowDefinition Height="Auto" />



  16:             <RowDefinition Height="Auto" />



  17:         </Grid.RowDefinitions>



  18:         <sdk:Label Content="Address:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />



  19:         <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="addressTextBox" Text="{Binding Path=EmployeeAddresses.Address, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />



  20:         <sdk:Label Content="City:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />



  21:         <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="cityTextBox" Text="{Binding Path=EmployeeAddresses.City, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />



  22:         <sdk:Label Content="Pin Code:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />



  23:         <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="3" Name="pinCodeTextBox" Text="{Binding Path=EmployeeAddresses.PinCode, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />



  24:     </Grid>



  25: </Grid>






In the code behind of MainPage.xaml I have just added few lines of code to load and bind the Data from the ASP.NET page hidden field where we have kept our employee Serialized data.





   1: public partial class MainPage : UserControl



   2: {



   3:     List<Web.Employee> employees = null;



   4:     public MainPage()



   5:     {



   6:         InitializeComponent();



   7:     }



   8:  



   9:     private void UserControl_Loaded(object sender, RoutedEventArgs e)



  10:     {



  11:         if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))



  12:         {



  13:             var result = HttpUtility.HtmlDecode(HtmlPage.Document.GetElementById("txtValue").GetProperty("value").ToString());



  14:  



  15:             SLAppCommunication.Web.Employee employee = new Web.Employee();



  16:             employees = employee.GetDesializedEmployeeObject(result.ToString());



  17:             employeeDataGrid.ItemsSource = employees;



  18:         }



  19:  



  20:     }



  21:  



  22:     private void employeeDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)



  23:     {



  24:         Web.Employee emp = ((DataGrid)sender).SelectedItem as Web.Employee;



  25:         employeeDetailList.DataContext = emp;



  26:     }



  27: }






Here after the Load event of Silverlight Control I am reading the Data from the HTML Page textbox and then using HttpUtility.HtmlDecode to decode the Encoded string from the textbox. This will give me the actual Serialized String. Now since we want our data into an Object format so we are actually doing the reverse of what we already did in ASP.NET application. We are going to pass this XML Data into our function  GetDesializedEmployeeObject this function will basically return me the List<Employee> which we can directly bind it to our DataGrid control. Now lets run the application.



image



Ok so this gives me all the data which we have created in our ASP.NET application, Just I have added a employeeDataGrid_SelectionChanged event so that when we select any rows in our Grid it displays the detailed information of the same. And yes using this method we can avoid any calls to DB directly from Silverlight component. Here Silverlight is just a component plugged in into our ASP.NET page container.



Hope you liked this Post, to get the proper formatted and running example to the source code, you can download from here.



Source Code.

Share:

Wednesday, 22 June 2011

Passing parameters between Silverlight and ASP.NET – Part 1

While working with Silverlight applications, we may face some scenarios where we may need to embed Silverlight as a component, like for e.g in Sharepoint Webpars or simple we can have the same with ASP.NET. The biggest challenge comes when we have to pass the parameters from ASP.NET to Silverlight components or back from Silverlight to ASP.NET.

We have lots of ways we can do this, like using InitParams, QueryStrings, using HTML objects in Silverlight, etc. All these different techniques have some advantages or disadvantages or limitations. Lets see one by one why we should choose one and what are the ways to achieve the same.

1. InitParams:

Lets start with InitParams, Start your Visual Studio 2010 IDE, and Create a Silverlight Application, give any name. Now go to the ASP.NET WebProject which is used to Host the Silverlight XAP component. You will find lots of different tags are used by Silverlight object as <params> tags. To use InitParams, Silverlight provides us with a tag called InitParams which we can use to pass parameters to Silverlight object from ASP.NET.

   1: <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">



   2:   <param name="source" value="ClientBin/SilverlightApp.xap"/>



   3:   <param name="onError" value="onSilverlightError" />



   4:   <param name="background" value="white" />



   5:   <param name="minRuntimeVersion" value="4.0.50826.0" />



   6:   <param name="initparams" id="initParams" runat="server" value=""/>



   7:   <param name="autoUpgrade" value="true" />



   8:   <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">



   9:        <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>



  10:   </a>



  11: </object>





Here in the code above I have included a initParam as a param tag (line 6), now in the page load I will add a line






   1: initParams.Attributes.Add("value", "key1=Brij, key2=Mohan");





This basically add a value parameter inside the initParam. So that's all we need in our ASP.NET side, now coming to the Silverlight Code open the code behind of App.xaml and add the following lines of code.





   1: private string firstKey, secondKey;



   2: private void Application_Startup(object sender, StartupEventArgs e)



   3: {



   4:     if (e.InitParams.ContainsKey("key1"))



   5:         this.firstKey = e.InitParams["key1"];



   6:     if (e.InitParams.ContainsKey("key2"))



   7:         this.secondKey = e.InitParams["key2"];



   8:     this.RootVisual = new MainPage(firstKey, secondKey);



   9: }






This code fetch the init params and pass it to our MainPage.xaml constructor, in the MainPage.xaml we can use these variables according to our requirement, here in this example I am simply displaying the variables in a Message Box.





   1: public MainPage(string param1, string param2)



   2: {



   3:     InitializeComponent();



   4:     MessageBox.Show("Welcome, " + param1 + " " + param2);



   5: }





imageThis will give you a sample output as









Limitations: Depending on the browsers you have some limitation on the overall string length of the parameters you can pass. To get more details on this limitation, you can refer to this link :http://www.boutell.com/newfaq/misc/urllength.html



2. QueryStrings



To show this example I am taking the scenario where we have a default.aspx page and we are going to the SIlverlightTestPage.aspx, and we have to work with the parameters which was passed by default.aspx in the SilverlightTestPage.aspx Silverlight Component.



So first I will add a new page in my application which contains a button with ID =btnNext, and on click of the button I will redirect my page to my SilverlightTestAppPage.aspx with the required query strings.



Code of Default.aspx





   1: protected void btnNext_Click(object sender, EventArgs e)



   2: {



   3:     Response.Redirect("~/SilverlightAppTestPage.aspx?FName=Brij" + "&LName=Mohan");



   4: }




Code of MainPage.xaml.cs





   1: public partial class MainPage : UserControl



   2: {



   3:     public MainPage()



   4:     {



   5:         InitializeComponent();



   6:         this.Loaded += new RoutedEventHandler(MainPage_Loaded);



   7:     }



   8:  



   9:     void MainPage_Loaded(object sender, RoutedEventArgs e)



  10:     {



  11:         IDictionary<string, string> qString = HtmlPage.Document.QueryString;



  12:         string firstName = string.Empty;



  13:         string lastName = string.Empty;



  14:         foreach (KeyValuePair<string, string> keyValuePair in qString)



  15:         {



  16:             string key = keyValuePair.Key;



  17:             string value = keyValuePair.Value;



  18:             if (key == "FName")



  19:                 firstName = value;



  20:             else if (key == "LName")



  21:                 lastName = value;



  22:         }



  23:         MessageBox.Show("Welcome, " + firstName + " " + lastName);



  24:     }



  25: }




Set the Start-up page as Default.aspx, now run the application. This will give you the following output:



imageSince here also you are using the Query Strings to pass your parameters, so you are depending on the browser capabilities of the length of the query strings it can pass. Here also you can refer the limitation which I have mentioned in my previous example for the length of parameters you can use.



 



3. Using HtmlPage.Document



Silverlight to ASP.NET <—> ASP.NET to Silverlight: To show this I setup a sample Silverlight Application with Buttons Get Data and Set Data with the Data Text Box. In ASP.NET page I keep a TextBox to Show how the values passed to and From Silverlight to ASP.NET reflects back. My page with Silverlight control looks like this.



image



When I Say Get Data it pulls the data from ASP.NET to Silverlight Control Text Box, and When I say Set data it basically Set the Value from Silverlight Control TextBox to ASP.NET TextBox. Now let see the code how it is doing.



This is my ASP.NET Source Code. Here I have just created a TextBox named : txtData





   1: <body>



   2:     <form id="form1" runat="server" style="height:100%">



   3:     <div id="silverlightControlHost">



   4:     ASP.NET TextBox:  <input type="text" runat="server" id="txtData" value="Some Data" />



   5:         <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">



   6:           <param name="source" value="ClientBin/SilverlightApplication1.xap"/>



   7:           <param name="onError" value="onSilverlightError" />



   8:           <param name="background" value="white" />



   9:           <param name="minRuntimeVersion" value="4.0.50826.0" />



  10:           <param name="autoUpgrade" value="true" />



  11:           <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">



  12:                <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>



  13:           </a>



  14:         </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>



  15:         </div>



  16:     </form>



  17: </body>




My actual logic for getting and setting the data lies in my Silverlight Control, this is my XAML code with TextBox and Buttons.





   1: <Grid x:Name="LayoutRoot" Background="White" Height="100" Width="450" VerticalAlignment="Top">



   2:     <Grid.ColumnDefinitions>



   3:         <ColumnDefinition Width="110" />



   4:         <ColumnDefinition Width="110" />



   5:         <ColumnDefinition Width="110" />



   6:         <ColumnDefinition Width="110" />



   7:     </Grid.ColumnDefinitions>



   8:     <TextBlock Text="Silverlight Text Box: " Grid.Column="0" VerticalAlignment="Center"></TextBlock>



   9:     <TextBox x:Name="DataText" Width="100" Grid.Column="1" Height="20"></TextBox>



  10:     <Button x:Name="GetData" Width="100" Click="GetData_Click" Grid.Column="2" Height="30" Content="Get Data"></Button>



  11:     <Button x:Name="SetData" Width="100" Click="SetData_Click" Grid.Column="3" Height="30" Content="Set Data"></Button>



  12: </Grid>




Now we have to write few lines of Button Events for Get Data and Set Data which basically make use of Windows.System.Browser namespace.





   1: private void GetData_Click(object sender, RoutedEventArgs e)



   2: {



   3:     DataText.Text = HtmlPage.Document.GetElementById("txtData").GetProperty("value").ToString();



   4: }



   5:  



   6: private void SetData_Click(object sender, RoutedEventArgs e)



   7: {



   8:     HtmlPage.Document.GetElementById("txtData").SetProperty("value", DataText.Text);



   9: }




That’s it so when we run this application my Form will look like this.



image



4. Using Object Serialization.



This is a useful when we want to pass Objects of Data from our ASP.NET application to Silverlight Controls and back. This basically uses the above technique I mentioned in Part 3 above. Since this itself is a lengthy topic so details of this I am going to cover in Part 2 of this Post with Sample Code Example very soon.

Share:

Thursday, 16 June 2011

Sunday, 12 June 2011

Article Published On – Electronics For You June 2011 Issue Vol. 43 No. 6

I am happy to announce that my article has been published on Electronics For You June 2011 Issue Vol. 43 No. 6 magazine.

You can Get an Overview of the Article (AVR Programmer Using AVR910 Protocol ) on http://www.efymag.com/currentissue.asp?id=12

EFY-June11-tilted

You can grab your copies from the newsstand.

Source codes for this article can be downloaded from the link: Download source code

Thanks to Arun Dayal Udai (Co-Author) for his extended support and providing me an opportunity to write the VB.NET Source codes supporting his concepts. Also thanks to all my readers/well wishers who has inspired me to post/write useful content. I will try my best to provide useful articles in upcoming days as well.

Share: