Using the ASP LinqDataSource Control
With ASP.NET LinqDataSource Control we can bind Web Pages to retrieves or modify data by using the advantages of the unified programming model that provided by LINQ.
My goal is to create Articles site using ASP.NET, on which all the articles are stored in SQL Server tables.
Articles Database Schema
Starting with the schema, for simplicity, the site will use two level of categories: main and secondary.
- Table Categories - Contains all the main categories and their descriptions.
- Table SubCategories - Contains all the secondary categories, linked to their parents.
- Table Authors - Contains the names of the authors.
- Table Articles - This is the main table containing all the information related to the articles, and connected to Authors and SubCategories.
Creating ASP.NET Web Site
The UI is a set of aspx pages, so for that we can create ASP.NET Web Site, which will contains all your aspx pages.
Lets Add New Item into our Articles Web Site, of type LINQ to SQL Classes, and call it Articles.dbml.
After we have a database schema, and Articles.dbml in our web site, we want to create Data Classes. For that, we open the Server Explorer, Connect to the database, and dragging items onto the design surface.
The following figure show the result we have so far:
Configure Linq Data Source
From the toolbox, drag into Default.aspx web page the LinqDataSource Control, founded at data category, and then press link to configure it.

Add Form View
Add new FormView Control from the Data Controls in the toolbox, and choose data source the the linq data source you have created above.
Override the Result
Now, you can view page Default.aspx, and look for the default results.
Lets say we want to display information not only from articles tables, but also from the Authors tables which connected to it with foreign key.
Double clicking on the LinqDataSource Control will create for us a new method in file _Default, so lets do some overrides:
public partial class _Default : System.Web.UI.Page
{
private Int32 m_id;
protected void Page_Load(object sender, EventArgs e)
{
String x = ClientQueryString;
if (ClientQueryString.ToUpper().StartsWith("ID="))
{
m_id = Int32.Parse(ClientQueryString.Substring(3));
}
}
protected void LinqDataSource1_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
ArticlesDataContext dataContext = new ArticlesDataContext();
e.Result = from article in dataContext.Articles
where article.Id == m_id
select new
{
article.CreatedOn,
article.CreatedBy,
article.Title,
article.Text,
AuthorName = article.Author.Name,
AuthorDescription = article.Author.Description,
article.SubCategory.Category,
article.SubCategory.ParentCategory,
CategoryUrl = GetCategoryUrl(article.SubCategory.ParentCategory),
SubCategoryUrl = GetSubCategoryUrl(article.SubCategory.Category)
};
}
private String GetCategoryUrl(String category)
{
return "../" + GetSubCategoryUrl(category);
}
private String GetSubCategoryUrl(String category)
{
return category.ToLower().Replace(" ", "-") + ".aspx";
}
}
As I have changed the result set for the control, I will change in the Default.aspx code:
After removing DataKeyNames="Id" from the FormView, and update the fields as the result set,
<asp:LinqDataSource ID="LinqDataSource1" runat="server"
ContextTypeName="ArticlesDataContext" onselecting="LinqDataSource1_Selecting"
TableName="Articles">
</asp:LinqDataSource>
<asp:FormView ID="FormView1" runat="server"
DataSourceID="LinqDataSource1">
<ItemTemplate>
Category:
<asp:Label ID="CategoryLabel" runat="server" Text='<%# Bind("Category") %>' />
<br />
CreatedOn:
<asp:Label ID="CreatedOnLabel" runat="server" Text='<%# Bind("CreatedOn") %>' />
<br />
CreatedBy:
<asp:Label ID="CreatedByLabel" runat="server" Text='<%# Bind("CreatedBy") %>' />
<br />
Title:
<asp:Label ID="TitleLabel" runat="server" Text='<%# Bind("Title") %>' />
<br />
Text:
<asp:Label ID="TextLabel" runat="server" Text='<%# Bind("Text") %>' />
<br />
Author Name:
<asp:Label ID="AuthorLabel" runat="server" Text='<%# Bind("AuthorName") %>' />
<br />
Author Description:
<asp:Label ID="AuthorDescriptionLabel" runat="server" Text='<%# Bind("AuthorDescription") %>' />
<br />
Sub Category Url:
<asp:Label ID="SubCategoryLabel" runat="server"
Text='<%# Bind("SubCategoryUrl") %>' />
<br />
Category Url:
<asp:Label ID="CategoryUrlLabel" runat="server"
Text='<%# Bind("CategoryUrl") %>' />
<br />
</ItemTemplate>
</asp:FormView>
Using the following URL: http://.../ArticlesWebSite/Default.aspx?id=3 you can access the article with id = 3.
Conclusion
With LinqDataSource Control and FormView or ListView you can bind web pages to the database in a very simple and powerfull way, using data retrieved from some tables related each other.
You can download the source code: LinqDataSource.zip
Download the script to create the database schema: ArticlesTables.zip
WCF Quick Start - Designing Service Contracts
The first step in creating WCF service is to define the Service Contract. Each service in WCF consists of endpoints, and each endpoint consists of an address, a binding, and a contract.
Contracts of web services consists from set WSDL and XSD documents. In WCF, contract are a set of .NET type definitions annotated with special attributes, which can be turned into a set of WSDL and XSD documents.
There are three types of contracts in WCF:
-
Service Contract
-
Data Contract
-
Message Contract
Service Contracts
Service Contract describe the service itself. The following image show how to create new WCF Application Program (named ArticleService):
By taking a simple interface (can be also class) and by annotating it with attributes, we can influence the mapping between the worlds of .NET types and operations to SOAP. With this information, WCF can perform the dispatching and the serialization (of Data Contracts).
Each method in a service contract is assigned an action value based on service namespace and operation name, for example, the action of GetArticle operation contract is:
http://WcfQuickStart.org/ArticleService/GetArticle
You can override the Action and the Name as done with the two GetArticle methods.
Since interfaces seperating the contract from implementation, it is highly recommended to define service contract as an interface.
[ServiceContract(Namespace = "http://WcfQuickStart.org/ArticleService/")]
public interface IArticleService
{
[OperationContract]
String GetArticleAuthor(Int32 id);
[OperationContract(Action = "GetArticleByAuthorAndTitle")]
Article GetArticle(String author, String title);
[OperationContract(Name = "GetArticleById")]
Article GetArticle(Int32 id);
[OperationContract(IsOneWay = true)]
void RateArticle(Int32 id);
}
Data Contracts
The Data Contract is defined by the type used in the method signature. When a type which is different than Message is used, WCF performs serialization to map between .NET types to the body of the message.
[DataContract(Namespace = "http://WcfQuickStart.org/DT/Article/")]
public class Article
{
[DataMember]
public Int32 Id
{
get;
set;
}
[DataMember]
public String CreatedBy
{
get;
set;
}
[DataMember]
public String Category
{
get;
set;
}
[DataMember]
public String Title
{
get;
set;
}
[DataMember(Name = "Body", IsRequired = false)]
public String Text
{
get;
set;
}
[DataMember]
public DateTime CreatedOn
{
get;
set;
}
}
Message Contracts
If you need to support headers, you can create a class on which you have that models the structure of the entire SOAP envelope for a particular operation.
With [MessageBody] and [MessageHeader] attributes, you have more control on the content of the serialized data than a data contract, you can specify which field map to header versus body.
Lets add operation to IArticleService interface, including two message contracts:
[OperationContract]
GetArticlesResponse GetArticles(GetArticlesRequest message);
[MessageContract]
public class GetArticlesRequest
{
[MessageHeader]
public String CreatedBy;
[MessageHeader]
public DateTime CreatedAfter;
}
[MessageContract]
public class GetArticlesResponse
{
[MessageHeader]
public String CreatedBy;
[MessageBodyMember]
public List<Article> Articles;
}
Download the source code of WCF Quick Start: Contracts.
Silverlight Chart User Control
In the last month I was creating a simple Silverlight Application which display a Financial Chart. It was in the following post: Displaying Chart using Silverlight 2.0 User Control
In this post I have a better version of the previous chart, which includes:
-
Handling large amount of data
-
Displaying the tags (x-y values) correctly
-
Supporting of resizing
-
Using RESTfull Web Service
The result of this project is as showed in the following image:
Stock Quote Service Contract
The Stock Quote Service is a WCF RESTfull Service, which can be called using HTTP Get method, with three arguments:
The Service and Data Contracts are defined below:
[ServiceContract]
public interface IStockQuoteService
{
[OperationContract, WebGet(UriTemplate = "HistoricalPrices?ticket={ticket}&fromDate={fromDate}&toDate={toDate}", ResponseFormat = WebMessageFormat.Xml)]
List<StockQuote> GetStockQuoteData(String ticket, String fromDate, String toDate);
}
[DataContract(Namespace = "http://www.finance.com/StockQuote")]
public class StockQuote
{
[DataMember]
public String Ticket { get; set; }
[DataMember]
public System.DateTime Date { get; set; }
[DataMember]
public Decimal Open { get; set; }
[DataMember]
public Decimal High { get; set; }
[DataMember]
public Decimal Low { get; set; }
[DataMember]
public Decimal Close { get; set; }
[DataMember]
public Int32 Volume { get; set; }
}
For learn how to implement WCF REST Services read HTTP Web Programming with WCF 3.5: Creating a Template based URI.
Stock Quote Service Implementation
The Stock Quote Service Implementation is used Linq to Sql in order to retrieve the data from the database, and send it back into the Silverlight Client Application:
public class StockQuoteService : IStockQuoteService
{
public List<StockQuote> GetStockQuoteData(String ticket, String fromDate, String toDate)
{
List<StockQuote> quotesList = new List<StockQuote>();
DateTime fromDate_ = DateTime.Parse(fromDate);
DateTime toDate_ = DateTime.Parse(toDate);
QuotesDataContext dataContext = new QuotesDataContext();
var quotes = from q in dataContext.Quotes
where (q.Ticket == ticket) && (q.Date >= fromDate_) && (q.Date <= toDate_)
select q;
foreach (var quote in quotes)
{
StockQuote stockQuote = new StockQuote()
{
Ticket = quote.Ticket,
Low = (Decimal)quote.Low,
High = (Decimal)quote.High,
Close = (Decimal)quote.Close,
Date = quote.Date,
Volume = (Int32)quote.Volume,
Open = (Decimal)quote.Open
};
quotesList.Add(stockQuote);
}
return quotesList;
}
}
Accessing the Stock Quote Service
For accessing this Stock Quote Service, using the following url (depends on the data inside Quotes table):
http://localhost:4958/ChartingApplication_Web/StockQuoteService.svc/HistoricalPrices?ticket=msft&fromDate=1/1/2000&toDate=1/1/2008
You can see the appropriate result:
<ArrayOfStockQuote
xmlns="http://www.finance.com/StockQuote"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<StockQuote>
<Close>58.28</Close>
<Date>2000-01-03T00:00:00</Date>
<High>59.31</High>
<Low>56.00</Low>
<Open>58.69</Open>
<Ticket>MSFT</Ticket>
<Volume>53228400</Volume>
</StockQuote>
<StockQuote>
<Close>56.31</Close>
<Date>2000-01-04T00:00:00</Date>
<High>58.56</High>
<Low>56.12</Low>
<Open>56.78</Open>
<Ticket>MSFT</Ticket>
<Volume>54119000</Volume>
</StockQuote>
<StockQuote>
...
Call Web Service from Silverlight Application
For getting the data inside a Silverlight Application, I use the following two methods:
-
GetStockQuoteDataAsync - Marked as ScriptableMember, which means can be called from javascript.
-
client_DownloadStringCompleted - The callback - each call outside from Silverlight is called asynchronously:
[ScriptableMember]
public void GetStockQuoteDataAsync(String ticket, String fromDate, String toDate)
{
try
{
WebClient client = new WebClient();
String address =
String.Format(
"http://localhost:4958/ChartingApplication_Web/StockQuoteService.svc/HistoricalPrices?ticket={0}&fromDate={1}&toDate={2}", ticket, fromDate, toDate);
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(
client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri(address));
m_headerElement.SetAttribute(
"innerHTML", String.Format("<b>{0}</b> {1} - {2}", ticket, fromDate, toDate));
}
catch (Exception ex)
{
}
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
XDocument xmlQuotes = XDocument.Parse(e.Result);
XNamespace ns = xmlQuotes.Root.GetDefaultNamespace();
var quotes = from quote in xmlQuotes.Descendants(ns + "StockQuote")
select new DataPoint
{
Date = DateTime.Parse(quote.Element(ns + "Date").Value),
Value = Decimal.Parse(quote.Element(ns + "Close").Value)
};
DataPoint[] data = quotes.ToArray<DataPoint>();
DisplayChart(data);
}
else
{
String errorMessage = e.Error.Message;
}
}
Cross Domain Calls
If you call remote one of the following from Silverlight 2 application:
-
REST
-
SOAP-WS*
-
RSS
-
JSON
-
XML HTTP Services
-
System.Net.Socket
Silverlight will throw "Download Failure" exception if the URI is not to the same domain of the Silverlight server (which the Silverlight control downloaded).
Silverlight 2 application can optionally make cross-domain calls (calls from different URL's that of the Silverlight downloaded domain) by setting XML policy file in the web server, that enables the clients to make these cross-domain calls.
Data Access Layer
The Data Access Layer is based on SQL Server 2005 with table Quotes.
To create the table Quotes, you can use the following script:
USE [FinancialData]
GO
/****** Object: Table [dbo].[Quotes] Script Date: 04/10/2008 16:35:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Quotes](
[Ticket] [varchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Date] [datetime] NOT NULL,
[Open] [decimal](12, 2) NULL,
[High] [decimal](12, 2) NULL,
[Low] [decimal](12, 2) NULL,
[Close] [decimal](12, 2) NULL,
[Volume] [bigint] NULL,
CONSTRAINT [PK_Quotes] PRIMARY KEY CLUSTERED
(
[Ticket] ASC,
[Date] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
Conclusion
Although I have a lot of work to do, for the chart only I'm going to add zooming, tooltip and more functionality, but it showed here how simple is to create an end-to-end application, using these technologies.
I have declared on this project My new Innovative Project and after creating this chart connected to a database, the next missions will be to design the web pages, menues, and start manipulating some analysis on this chart...
I hope you enjoyed, and you can download the source code here: Silverlight 2 Chart User Control
Using DragPanelExtender to Drag and Drop Silverlight Control
In previous post ASP.NET AJAX DragPanelExtender I was displaying how to use ASP.NET AJAX DragPanelExtender Control to drag and drop content in your ASP.NET web pages.
In order to drag and drop a Silverlight Control you need to:
The html content of your web page should contain something like:
<body style="height:100%;margin:0;">
<form id="form1" runat="server" style="height:100%;">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<cc1:DragPanelExtender ID="DragPanelExtender1" runat="server" TargetControlID="PanelContainer" DragHandleID="PanelHeader">
</cc1:DragPanelExtender>
<asp:Panel ID="PanelContainer" runat="server" style="width: 200px;" BorderStyle="Double">
<asp:Panel ID="PanelHeader" runat="server" style="width: 100%; height: 21px;">
<div style="text-align: center">Panel Header...</div>
</asp:Panel>
<asp:Panel ID="PanelBody" runat="server" style="width: 200px; height: 100px; background-color: yellow">
<div style="height:100%;">
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication1.xap" Version="2.0" Width="100%" Height="100%" />
</div>
</asp:Panel>
</asp:Panel>
</form>
</body>
Then, you can drag your Silverlight Control.

You can download the source code here.
ASP.NET AJAX DragPanelExtender
Hi,
In this post, I will show you how to create and use the DragPanel Control of ASP.NET AJAX.
The DragPanel Control allow you to move the panel around your web page in your ASP.NET application.
So lets start with creating new AJAX Control Toolkit Web Site in your Visual Studio. In previous post Using the ASP.NET AJAX Calendar Control you can see how to install the AJAX Control Toolkit.
The Panel Control
Lets drag a Panel Control into our page and call it PanelContainer, and in this panel drag another two panels: PanelHeader for the header, and PanelBody for the body.
The following html from specify how the Panel Container contains two embedded panels: one for the header and one for the body.
<body style="height: 100%;">
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:Panel ID="PanelContainer" runat="server" style="width: 200px;" BorderStyle="Double">
<asp:Panel ID="PanelHeader" runat="server" style="width: 100%; height: 100%;">
<div style="text-align: center">Panel Header...</div>
</asp:Panel>
<asp:Panel ID="PanelBody" runat="server" style="width: 100%; height: 100%; background-color: yellow">
<br />
Hello<br />
There<br />
!!<br />
</asp:Panel>
</asp:Panel>
</div>
</form>
</body>
Implement the DragPanelExtender Control
Drag a DragPanelExtender Control into the page, and specify the TargetControlID to the entire container - PanelContainer.
Also, we don't want to enable dragging from every point inside the container, but just from the header, so lets specify the DragHandleID to the PanelHeader.
The html page with the DragPanelExtender:
<body style="height: 100%;">
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
<div>
<ajaxToolkit:DragPanelExtender ID="DragPanelExtender1" runat="server" TargetControlID="PanelContainer" DragHandleID="PanelHeader">
</ajaxToolkit:DragPanelExtender>
<asp:Panel ID="PanelContainer" runat="server" style="width: 200px;" BorderStyle="Double">
<asp:Panel ID="PanelHeader" runat="server" style="width: 100%; height: 100%;">
<div style="text-align: center">Panel Header...</div>
</asp:Panel>
<asp:Panel ID="PanelBody" runat="server" style="width: 100%; height: 100%; background-color: yellow">
<br />
Hello<br />
There<br />
!!<br />
</asp:Panel>
</asp:Panel>
</div>
</form>
</body>
Changing the Mouse Icon
For changing the mouse icon when dragging, we can use the following style:
<head runat="server">
<title>Untitled Page</title>
<style type="text/css">
.dragIcon
{
text-align: center;
cursor: move;
font-weight: bold;
}
</style>
</head>
And add the drag icon into the div of the PanelHeader.
<asp:Panel ID="PanelHeader" runat="server" style="width: 100%; height: 100%;">
<div class="dragIcon" style="text-align: center">Panel Header...</div>
</asp:Panel>
Conclusion
In this post you have seen how easy to add drag and drop functionality on your web page using ASP.NET AJAX DragPanelExtender.

You can download the source code here.