Tuples in .NET Framework 4.0

Posted: August 25, 2010 in .Net Framework

Another new feature in the .NET 4 Framework is support for tuples,which are similar to anonymous classes that you can create on the fly. A tuple is a data structure used in many functional and dynamic languages, such as F# and Iron Python. By providing common tuple types in the BCL, we are helping to better facilitate language interoperability. Many programmers find tuples to be convenient, particularly for returning multiple values from methods.

Here is a code which uses a function that returns two values.

class Program
{
static void Main(string[] args)
{
//Getting the values from the Tuple Function
Tuple details = GetDetails();
Console.WriteLine("FirstName : {0}, LastName :{1}", details.Item1, details.Item2);
Console.Read();
}

//Tuple function, which reads two values from
//user and returns to the main
static Tuple GetDetails()
{
Console.Write("Enter First Name:");
string _firstName = Console.ReadLine();
Console.Write("Enter Last Name:");
string _lastName = Console.ReadLine();
return new Tuple(_firstName, _lastName);
}
}

Printing a datagrid

Posted: August 19, 2010 in ASP.NET

Hi,

Here I would like to share the code to print a datagrid in ASP.NET

Put the given code in tag

function CallPrint(strid) {
var prtContent = document.getElementById(strid);
var WinPrint = window.open('', '', 'letf=0,top=0,width=1,height=1,t oolbar=0,scrollbars=0,status=0');
WinPrint.document.write(prtContent.innerHTML);
WinPrint.document.close();
WinPrint.focus();
WinPrint.print();
WinPrint.close();
//prtContent.innerHTML = strOldOne;
}

Put your datagrid in a

tag. Here I use a div named “divPrint”.

Put this code in your print button

OnClientClick="javascript:CallPrint('divPrint');"

or

OnClick="javascript:CallPrint('divPrint');"

:) Coding !!

Hi friends,

Session clearing is a very important issue after the user has logged out from his dashboard. After his/her logging out, the pages meant for the user should not be displayed. When we try to access these through links login page or any other respective pages are displayed. For the same we remove the sessions for the user when the user logs out.

Session.RemoveAll();

Above code will remove all the sessions created for the user. After this process when we try to access the user pages through URLs it will show the user has not logged in.

I would like to discuss a scenario where user logs out and we hits the browser back button, even if the sessions are cleared it shows the previous page, i.e, the user page. Is there a solution for this? Of course !!

Put this code in the Page_Load of the user page in addition to the session clearing code in the log out button.

Response.Buffer = true;
Response.ExpiresAbsolute = DateTime.Now.AddDays(-1);
Response.Expires = -1500;
Response.CacheControl = "no-cache";

Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1));
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetNoStore();

When developing a Silverlight application one of the main challenge we would face is to change the url/endpoint address of the WCF service. I just wanted to share how I have solved this problem in one of my project.

First, besides thesolution is able to change the url/endpoint dynamically, it’s also able (or actually required) to take the path to the WCF in as a InitParameter. Please note, that we are taking a relative path from the root here. Which means something like /Services/PeopleService.svc. Somethings that start with a /. This tells the browser that we want to start from the root of the current domain.

Here you can also see how we can send in the relative path for the service as a InitParameter.

Let’s start in App.cs
private void Application_Startup(object sender, StartupEventArgs e)
{
//Insert InitParams into Global Resources
foreach (string key in e.InitParams.Keys)
{
this.Resources.Add(key, e.InitParams[key]);
}

this.RootVisual = new Page();
}

We start out by taking all the potential InitParams and put them into the global Resources for the application. You could also just pass the Dictionary to the Page class, but I’ll do it like this in this case as I need to access the resources from different places in the application.

If we look in the web project in the HTML we see how and what we pass in here: Default.aspx
asp:Silverlight ID="Xaml1" runat="server"
Source="~/ClientBin/Dummy_WCF_Application.xap"
MinimumVersion="2.0.31005.0" Width="100%" Height="100%"
InitParameters="DummyServicePath=/Services/DummyWCFService.svc"

Ok, so now we have the initparams inside our silverlight application inside the resources. Let’s use it to set the endpoint of our application. This can be done anywhere you like, in my case I just have a DataProvider class and this is where my code is: DataProvider.cs

public class DataProvider
{
public event EventHandler GetDataCompleted;

private WCFServiceClassName service;
private const string DummyServicePathKeyName = "DummyServicePath";

public DataProvider()
{
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress;

if (App.Current.Resources.Contains(DummyServicePathKeyName )
&& !String.IsNullOrEmpty
(App.Current.Resources[DummyServicePathKeyName ] as string))
{
string relativePath =
App.Current.Resources[DummyServicePathKeyName ] as string;
string completePath = App.Current.Host.Source.Scheme
+ "://" + App.Current.Host.Source.Host
+ ":" + App.Current.Host.Source.Port + relativePath;
endpointAddress = new EndpointAddress(completePath);
service = new ChannelFactory
(basicHttpBinding, endpointAddress).CreateChannel();
}
else
throw new Exception("Missing init param named: \""
+ MapServicePathKeyName
+ "\" which is a relative Url to the WCF service.");
}
}

This is not a completely working sample, as I have removed curtain things to keep it simple. The most important part if the code above is actually this:

string relativePath = App.Current.Resources[DummyServicePathKeyName] as string;
string completePath = App.Current.Host.Source.Scheme
+ "://" + App.Current.Host.Source.Host
+ ":" + App.Current.Host.Source.Port + relativePath;

Here we create the actual complete url used to access to WCF service with.

App.Current.Host.Source.Scheme: Returns https or http

App.Current.Host.Source.Host: Returns the host ex. “laumania.net” or “silverlight.laumania.net” if you were on a subdomain.

App.Current.Host.Source.Port:
Returns the port number, typically 80, but could be anything actually. If the scheme were https the port would normally be 443 etc.

The code above would generate a url, if ran on this actual page:

Now you should be able to make your own WCF service that you can change the endpoint of, in code.

Hope you find this useful.

Populating the ListBox
We want to load all the customers into the listbox lstCustomers, for which we are using the Loaded event of the ListBox. Note that all service calls in Silverlight need to be asynchronous, so we will register a callback function where we will bind the incoming data to the ListBox. Notice how we use the txtStatus textbox (recall we placed this in the bottom row of LayoutGrid to provide updates to the user).

private void lstCustomers_Loaded(object sender, RoutedEventArgs e)
{
DataServiceClient svc = new DataServiceClient();
this.txtStatus.Text = "Loading customers...";
svc.GetCustomersCompleted += new
EventHandler(svc_GetCustomersCompleted);
svc.GetCustomersAsync();
}

void svc_GetCustomersCompleted(object sender, GetCustomersCompletedEventArgs e)
{
if (e.Error == null)
{
this.lstCustomers.ItemsSource = e.Result;
this.txtStatus.Text = string.Empty;
}
else
{
this.txtStatus.Text =
"Error occurred while loading customers from database";
}
}

Displaying the Orders of a Customer
Now, we will try to display the orders when a customer in the listbox is selected. In the SelectionChanged event handler, we will call our WCF service and bind the data to dgOrders when it is retrieved. This time, we will use anonymous methods to be more compact.

private void lstCustomers_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Customer selectedCustomer = this.lstCustomers.SelectedItem as Customer;
if (selectedCustomer != null)
{
DataServiceClient svc = new DataServiceClient();
this.txtStatus.Text = "Loading orders...";
svc.GetOrdersCompleted +=
delegate(object eventSender, GetOrdersCompletedEventArgs eventArgs)
{
if (eventArgs.Error == null)
{
this.dgOrders.ItemsSource = eventArgs.Result;
this.txtStatus.Text = string.Empty;
}
else
{
this.txtStatus.Text =
"Error occurred while loading orders from database";
}
};
svc.GetOrdersAsync(selectedCustomer.CustomerID);
}
}

Displaying the Order Details when an Order is Selected
Similar to the listbox SelectionChanged event, we add the following code to the SelectionChanged event of dgOrders.
private void dgOrders_SelectionChanged(object sender, EventArgs e)
{
Order selectedOrder = this.dgOrders.SelectedItem as Order;
if (selectedOrder != null)
{
DataServiceClient svc = new DataServiceClient();
this.txtStatus.Text = "Loading order details...";
svc.GetOrderDetailsCompleted +=
(eventSender, eventArgs) =>
{
if (eventArgs.Error == null)
{
this.dgOrderDetails.ItemsSource = eventArgs.Result;
this.txtStatus.Text = string.Empty;
}
else
{
this.txtStatus.Text =
"Error occurred while loading order details from database";
}
};
svc.GetOrderDetailsAsync(selectedOrder.OrderID);
}
}

Now, our small application is ready to be viewed. Run it. Select some customers, view orders, edit the data displayed in the DataGrid, sort the DataGrid data by clicking on the column headers, resize the DataGrid columns or resize the browser window.

Creating the UI
A Silverlight page/control consists of a layout XAML file and a code-behind xaml.cs file. Typically, similar to an ASP.NET page, the XAML file contains the layout definition (like a *.aspx file where we define our UI), while the xaml.cs file contains the logic and event handlers (like our aspx.cs file).

Adding the Assembly to Use a DataGrid Control
We will display our data using the DataGrid control, but Silverlight does not include a reference to the DataGrid control by default, so we need to add one. This process is very similar to using a custom control in ASP.NET. Recall that we add a reference to the appropriate DLL in the project and then add a register tag in the aspx page. To achieve this in Silverlight, add a new reference (right click on References and select New Reference) and locate System.Windows.Controls.Data in the list (this is the assembly that contains the DataGrid).

After this reference is added, we need to assign a namespace to this assembly in our XAML markup. To do this, add the following to the namespace declaration of the file Page.Xaml.
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

UI Layout
Create a Grid named LayoutRoot with three rows: the first one for our Application Title (width=50), the third one for a status bar (width=20), and the middle row acting as the main content holder (width=*, takes all the space that is left). Add a title TextBlock to the first row, and an empty TextBlock named txtStatus to the bottom row of the LayoutRoot grid. In the middle row (the one we identified as the content holder) of the LayoutRoot grid, add another Grid named ContentRoot with two columns and two rows; the left column with width 200 and the right column taking the rest. The rows should be divided in the ratio 60% and 40%. In the left column of this ContentRoot grid, add a ListBox that spans in both rows. In the right column, add a DataGrid for the customer orders in the first row and another DataGrid for the order details in the second row.

UserControl xmlns:basics=”clr-namespace:System.Windows.Controls;
assembly=System.Windows.Controls”
x:Class=”DataApplication.Page”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:data=”clr-namespace:System.Windows.Controls;
assembly=System.Windows.Controls.Data”
Width=”Auto” Height=”Auto”

Grid x:Name=”LayoutRoot” Background=”White”
Grid.RowDefinitions
RowDefinition Height=”55″ x:Name=”HeaderRow”
RowDefinition Height=”*” x:Name=”ContentRow”
RowDefinition Height=”20″ x:Name=”FooterRow”
Grid.RowDefinitions
Grid.ColumnDefinitions
ColumnDefinition Width=”*”
Grid.ColumnDefinitions

Heading
TextBlock x:Name=”txtHeader” Grid.Row=”0″
FontSize=”20″ Margin=”5,5″ Foreground=”Blue”
Text=”My First Data Application in Silverlight”
TextBlock

A textblock in the footer to be used as an Status bar
TextBlock x:Name=”txtStatus” Grid.Row=”2″
FontSize=”10″ Margin=”5,0″ Foreground=”Red”
TextBlock

Content Holder
Grid x:Name=”ContentGrid” Grid.Row=”1″ Margin=”5″
Grid.RowDefinitions
RowDefinition Height=”.6*”
RowDefinition Height=”.4*”
Grid.RowDefinitions
Grid.ColumnDefinitions
ColumnDefinition Width=”200″
ColumnDefinition Width=”*”
Grid.ColumnDefinitions

Listbox for displaying customers
ListBox x:Name=”lstCustomers” Grid.Column=”0″ Grid.RowSpan=”2″
DisplayMemberPath=”ContactName”
Loaded=”lstCustomers_Loaded”
SelectionChanged=”lstCustomers_SelectionChanged”
ListBox

DataGrid for displaying orders of a customer
(with autogenerated columns)

data:DataGrid x:Name=”dgOrders” Grid.Row=”0″ Grid.Column=”1″
AutoGenerateColumns=”True”
SelectionChanged=”dgOrders_SelectionChanged”
data:DataGrid

DataGrid for displaying orderdetais for an order
data:DataGrid x:Name=”dgOrderDetails” Grid.Row=”1″ Grid.Column=”1″
AutoGenerateColumns=”True”
AutoGeneratingColumn=”dgOrderDetails_AutoGeneratingColumn”
data:DataGrid

Grid

Grid
UserControl

ListBox
The listbox lstCustomers will be used for displaying the list of customers in the database. We will be binding this listbox inside the Loaded event for which we have registered. Note that if a ListBox is bound to some object source, it will display the value object.ToString() for each of its items collection. If we want to display any other value (typically a string member of the object), we have three apparent choices:

* Override the object.ToString() method (We are not going to do this just for displaying the correct values in a ListBox).
* Define some Data Template (this is the most flexible approach, and we will briefly look at DataTemplates in this article when we will manually define the columns for our DataGrid, but for now, we will skip this choice).
* Define the property to be used in the DisplayMemberPath property of the ListBox (fairly simple, so we will keep ourselves to this for now).

Since we want the ListBox to show the ContactName property of the Customer object to which it is bound, we use DispalyMemberPath=”ContactName”. Also, we have registered for the SelectionChanged event which we will handle in our code-behind file to update the DataGrid with the selected customer’s orders.

DataGrids
We have just configured DataGrids to auto-generate their columns when they are data bound. Note that we also subscribed for the AutoGeneratingColumns event in dgOrderDetails. This is a common practice, and used in conjunction with auto-generating columns if we want to remove certain unwanted columns quickly.

Generating LINQ Classes

To start generating LINQ data classes, we need to add a new LINQ Data Classes object in our ASP.NET application.

Now, using the Server Explorer, create a new data connection to the your database (either using SQLExpress, or SQL Server if you have it), and then drag the tables Customer, Orders, and OrderDetails into the LINQ designer. One important thing is to allow serialization of our LINQ generated data classes since we will be transferring these objects to our Silverlight application. To achieve this, click on some empty space in the LINQ designer and change the property Serialization to UniDirectional using the Properties window.

Creating a Silverlight WCF Service
Now, we are about to add a service to our server project for retrieving data. For that we have to add a new Silverlight-enabled WCF Service named DataService to our ASP.NET project.

We will write three methods in our service, one that returns all the customers, one that returns orders of a customer, and finally, one that returns order details of a particular order. Note that the methods must be marked with the attribute [OperationContract] (this attribute is similar to a [WebMethod] attribute for an ASMX service). Here is a quick implementation of the data retrieval methods using very basic LINQ.

Add the following to the DataService.svc.cs file.

[OperationContract]
public List GetCustomers()
{
DataClasses1DataContext datacontext = new DataClasses1DataContext();
return datacontext.Customers.ToList();
}

[OperationContract]
public List GetOrders(string customerID)
{
DataClasses1DataContext datacontext = new DataClasses1DataContext();
return (from order in datacontext.Orders
where order.CustomerID == customerID
select order).ToList();
}

[OperationContract]
public List GetOrderDetails(int orderID)
{
DataClasses1DataContext datacontext = new DataClasses1DataContext();
return (from orderdetail in datacontext.Order_Details
where orderdetail.OrderID == orderID
select orderdetail).ToList();
}

Adding a Service Reference to the Silverlight Project
That’s all that was required on the server-side ASP.NET project. We have created LINQ data classes to get data from the database and a WCF service to return those LINQ objects. Now, we are ready to consume the service in our client-side Silverlight project. For this, we need to add a service reference in the DataApplication project. We can click Discover in the Add Service Reference popup to have Visual Studio automatically find the newly created WCF service for us.