Introduction
There are so many exciting new technologies and features that have just been released or are soon-to-be-released: Visual Studio 2008, LINQ, MVC Framework, Entity Framework, AJAX, WCF, just to name a few. This is great news but there is a price to pay. There is more to read, more to learn and more to keep up with; but I believe it is worthwhile.
The first problem I ran into writing this article was “what to write about?” After hours of thinking, I decided to write a small application that covers many of these topics and then concisely discusses each one. So, don’t expect an in-depth analysis of all these topics. Instead, I will show you how powerful all these technologies are when combined together.
For my sample application, I will create a simple web-based feed/RSS reader. In this application, I will explore the following technologies:
- ListView – a new web control for ASP.NET 3.5
- LINQ
- Syndication API – part of Windows Communication Foundation (WCF)
- AJAX and AJAX Toolkit
I will also point out some of the new features of the Visual Studio 2008 throughout the article.
The Beginning
Let's start by creating a new web site
This will automatically create a website that has full support for Microsoft AJAX - but NOT the AJAX toolkit. To use the AJAX Toolkit, you need to download and install the version targeting the 3.5 .NET Framework.
Now, let's create the UI. The main components in the user interface are a tree view and a list view. The tree view will contain all your feeds and the list view will display the feed items for the selected feed.
Syndication API
A feed reader is no good, if you cannot add feeds to it. So, the first thing we need to do is add feeds. There is a text box and an add button at the top of the page. You simply type the feed URL and click the add button. Here is where the new and powerful Syndication API comes in play. You don’t have to parse XML, make HTTP calls and write messy code. All you have to do is write two lines of code. Yes, this is not a typo TWO lines of code.
Dim xmlReader = System.Xml.XmlReader.Create(feedUrl)
Dim feed = SyndicationFeed.Load(xmlReader)
The first line creates an XML reader using the feed URL supplied by the user. The second line retrieves the feed and feed items. Remember to import the System.ServiceModel.Syndication
namespace to easily use the syndication API. That’s all we have to do. Now we have a strongly typed feed of type SyndicationFeed
with a collection of SyndicationItem
. Let’s display it.
User Interface and ListView
When the user selects a feed from the tree view, we need to display the feed items in the list view. You can of course use any data control you want like a DataList or Repeater. But since we are exploring new things, let's use the ListView control. There are two important steps you need to take to render a ListView:
- Add a
LayoutTemplate
- Add an
ItemTemplate
The LayoutTemplate
must contain an element named “itemPlaceholder” that has the attribute runat=”server”
. This – as the name implies – acts as a placeholder.
<LayoutTemplate>
<table runat="server" id="table1" runat="server">
<tr runat="server" id="itemPlaceholder"> </tr>
</table>
</LayoutTemplate>
The ItemTemplate
should contain an element of the same type as the itemPlaceholder defined in the layout template. In this case the placeholder is a TR element.
<ItemTemplate>
<tr runat="server">
<td id="Td1" runat="server">
<asp:Panel ID="lblTitle" runat="server" BackColor="#000066"
ForeColor="white" Width="100%">
<%#Eval("Title.Text") %>
[<a href='<%#Eval("Links(0).Uri.AbsoluteUri") %>'
target="_blank">link</a>]</asp:Panel>
<asp:Panel ID="pnlContent" runat="server">
<asp:Label ID="lblContent" runat="server"
Text='<%#Eval("Summary.Text") %>' /></asp:Panel>
</td>
</tr>
</ItemTemplate>
The ListView will basically replace the itemPlaceholder item in the layout template with the code in the ItemTemplate. You could pretty much do the same thing in a DataList or Repeater, but the ListView control can let you edit, insert, delete, sort, page and group data without code. I would strongly recommend looking into this new and powerful control.
Now that all the UI elements are in place, let’s display the information. We simply loop through a list of SyndicationFeeds
and add each feed title to the tree nodes list. When a user clicks on a node then we get that feed’s items and bind them to the ListView.
Private Sub BindListView(ByVal feed As SyndicationFeed)
Me.ListView1.DataSource = feed.Items
Me.ListView1.DataBind()
End Sub
AJAX
To make the webpage more useable, I wrapped the entire page in an AJAX UpdatePanel and associated it with an UpdateProgress panel.
<asp:UpdateProgress ID="UpdateProgress2" runat="server"
AssociatedUpdatePanelID="UpdatePanel2"
DisplayAfter="0" DynamicLayout="True">
<ProgressTemplate>
<div class="progresspanel">
Loading…
</div>
</ProgressTemplate>
</asp:UpdateProgress>
I applied a neat style to the progress panel that gives it the same look and feel as the “Loading” message you get on Gmail. It is a red rectangle with "Loading..." displayed in white at the top right hand corner of the page.
.progresspanel
{
background-color: RED;
color: White;
top: 1px;
color: white;
position: absolute;
right: 16px;
z-index: 999;
}
I also wanted to make the items in the ListView expand/collapse when the feed title is clicked. To do that, I used the CollapsiblePanelExtender
from the AJAX Toolkit. Since the items in the ListView are dynamically generated, I had to create the extender in code. I did that in the ItemCreated
event of the ListView. I assigned the item content panel to the TargetControlID
property of the extender and the title panel to the ExpandControlID
and CollapseControlID
properties. I also set all items to default to the collapsed state.
Protected Sub ListView1_ItemCreated(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles
ListView1.ItemCreated
If e.Item.ItemType = ListViewItemType.DataItem Then
Dim lblTitle As WebControl = e.Item.FindControl("lblTitle")
Dim pnlContent As WebControl = e.Item.FindControl("pnlContent")
Dim cpx As New AjaxControlToolkit.CollapsiblePanelExtender()
cpx.ID = "cpx"
cpx.TargetControlID = pnlContent.UniqueID
cpx.CollapseControlID = lblTitle.UniqueID
cpx.ExpandControlID = lblTitle.UniqueID
cpx.Collapsed = True
e.Item.Controls.Add(cpx)
End If
End Sub
In order to make the first item expand, I added an event handler to the ListView PreRender
event.
Protected Sub ListView1_PreRender(ByVal sender As Object,
ByVal e As System.EventArgs) Handles ListView1.PreRender
If ListView1.Items.Count > 0 Then
Dim cpx As AjaxControlToolkit.CollapsiblePanelExtender =
ListView1.Items(0).FindControl("cpx")
If Not IsNothing(cpx) Then cpx.Collapsed = False
End If
End Sub
I also used a couple of TextWatermarkExtender
to display a watermark on the text boxes.
LINQ
I love so many things about the new framework and Visual Studio but if I had to pick one feature/technology that I am very excited about, it would have to be LINQ – Language Integrated Query. This is a pretty big topic on its own and I am barely scratching the surface here.
I wanted to let the user search the title of the feed items for a specific text. Without LINQ, I would have to loop through the items and search the title. But now that I have LINQ, I can just write a simple query that looks very familiar to anyone who has ever written a SQL statement.
Dim matches = From item In CurrentFeed.Items _
Where item.Title.Text.ToUpper _
Like String.Format("*{0}*", txtFilter.Text.ToUpper)
The above statement, I am simply running a "select" statement against the feed items with a condition that it returns only items where the title contains the filter/search text. As you can see, this looks very similar to SQL but it is so much more. First of all the returned results are strongly typed as you can see from the tooltip below:
Second, you cannot really make syntax error here because the compiler wouldn’t let you. Compare that with SQL where you will not find out that your SQL statement had a problem until you compile and run the application. Third, you get full IntelliSense support in the IDE as you type your query – take a look at the series of screenshots below:
Honorable Mentions
There are a few things worth mentioning in the LINQ query above that are new the framework.
Implicit Types
As you can see in the IntelliSense "matches" is strongly typed based on the results of the query. This is the equivalent of:
Dim matches As IEnumerable(Of SyndicationItem)
Keep in mind that implicit types are not the same as Dim x as object. These are strongly typed objects, but instead of being explicitly declared as a specific type, the compiler and IDE deduce the type based on the assignment.
For example, these two statements are identical:
And
But these are not equivalent to:
Extension Methods
LINQ is only possible because of the miracle of extension methods. Extensions methods are simply a way of "injecting" a static/shared method into a class without inheriting it. Let's say for example, that we wanted to write the query above as a Search method inside the class IEnumerable(Of SyndicationItem)
and we want to do it easily. The first thing to do is create the extension method:
<Extension()> _
Function Search(ByVal Items As IEnumerable(Of SyndicationItem), _
ByVal SearchTerm As String) As IEnumerable(Of SyndicationItem)
Return From item In Items _
Where item.Title.Text.ToUpper _
Like String.Format("*{0}*", SearchTerm.ToUpper)
End Function
The steps to create an extension method are:
- Create a Module
- Create a method and add the <Extension> attribute to it - make sure to import the System.Runtime.CompilerServices namespace
- The first argument of the method must be the class you want to extend
To use the extension method you simply call it like any other method on the object:
If this is not awesome then I don't know what is!!!
Conclusion
Although, I didn't go in depth in any specific technology or feature, I wanted to show how fast and easy you can create interesting applications using the .NET 3.5 framework and Visual Studio 2008 with very little code. We covered WCF's syndication API, ListView web control, AJAX, AJAX Toolkit, LINQ, extension methods and implicit types.
What do you think?
I would like to hear your opinions on these new technologies and on this article. I hope you find it mildly useful. Let me know what you think through comments, email or on my website at www.emadibrahim.com