Databinding Anonymous Types
Some interesting startups got blown up when the stock market bubble burst, such as PointCast. PointCast searched the web—based on criteria the user provided—and displayed stock prices on a ticker and news in a browsable environment. One of the possible kinds of data was streaming stock prices. (Thankfully, the 1990s day-trading craze is over, but the ability to get such data is still interesting.)
This section looks at how you can combine cool technologies, such as anonymous types, AJAX, HttpWebRequests, HttpWebResponses, and queries to Yahoo!'s stock-quoting capability, and assemble a web stock ticker. Aside from the code, a demonstration of data-binding anonymous types, and a brief description of what role the various technology elements are playing, this book doesn't elaborate in detail on features like AJAX (because of space and topic constraints). (For more information on web programming, see Stephen Walther's ASP.NET 3.5 Unleashed.)
The sample (in Listing 1.11) is actually very easy to complete, but uses some very cool technology and plumbing underneath. In the solution, a website project was created. The application contains a single .aspx web page. On that page, a ScriptManager, UpdatePanel (both AJAX controls), a DataList, Label, and AJAX Timer are added. The design-time view of the page is shown in Figure 1.4 and the runtime view is shown in Figure 1.5. (Listing 1.12 shows the settings for the Web controls.)
Figure 1.4 Just five controls and you have an asynchronous AJAX page.
Figure 1.5 A very simple design but the code is actually updating the stock prices every 10 seconds with that postback page flicker.
Because of anonymous types, the code to actually query the stock process from Yahoo! is very short (see Listing 1.11).
Listing 1.11. This Code Uses HttpWebRequest and HttpWebResponse to Request Stock Quotes from Yahoo!
using System; using System.Data; using System.Diagnostics; using System.Configuration; using System.Collections; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Xml.Linq; using System.Web.Services ; using System.Net; using System.IO; using System.Text; namespace DataBindingAnonymousTypes { public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Update(); } private void Update() { var quote1 = new {Stock="DELL", Quote=GetQuote("DELL")}; var quote2 = new {Stock="MSFT", Quote=GetQuote("MSFT")}; var quote3 = new {Stock="GOOG", Quote=GetQuote("GOOG")}; var quotes = new object[]{ quote1, quote2, quote3 }; DataList1.DataSource = quotes; DataList1.DataBind(); Label3.Text = DateTime.Now.ToLongTimeString(); } protected void Timer1_Tick(object sender, EventArgs e) { //Update(); } public string GetQuote(string stock) { try { return InnerGetQuote(stock); } catch(Exception ex) { Debug.WriteLine(ex.Message); return "N/A"; } } private string InnerGetQuote(string stock) { string url = @"http://quote.yahoo.com/d/quotes.csv?s={0}&f=pc"; var request = HttpWebRequest.Create(string.Format(url, stock)); using(var response = request.GetResponse()) { using(var reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII)) { return reader.ReadToEnd(); } } } } }
The method InnerGetQuote has a properly formatted uniform resource locator (URL) query for the Yahoo! stock-quoting feature. Next, an HttpWebRequest sends the URL query to Yahoo! Then, the HttpWebResponse—returned by request.GetResponse—is requested and a StreamReader reads the response. Easy, right?
All of this code is run by the Update method. Update creates anonymous types containing a Stock and Quote field (which are populated by the GetQuote and InnerGetQuote methods). An anonymous array of these quote objects is created and all of this is bound to the DataList. The DataList itself has template controls that are data bound to the Stock and Quote fields of the anonymous type. Figure 1.6 shows the template design of the DataList. The very easy binding statement is shown in Figure 1.7.
Figure 1.6 The template view of the DataList is two Label controls and the | character.
Figure 1.7 The binding statements for bound template controls have been very short (as shown) since Visual Studio 2005.
All of the special features, such as template editing and managing bindings, are accessible through the DataList Tasks button, which is shown to the right of the DataList in Figure 1.4. You can also edit elements such as binding statements directly in the ASP designer. Listing 1.12 shows the ASP/HTML for the web page.
Listing 1.12. The ASP That Creates the Page Shown in Figure 1.4 (Design Time) and Figure 1.5 (Runtime)
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DataBindingAnonymousTypes._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <div> </div> <asp:UpdatePanel ID="UpdatePanel1" runat="server" EnableViewState="False"> <ContentTemplate> <asp:DataList ID="DataList1" runat="server" RepeatDirection="Horizontal"> <itemtemplate> <asp:Label ID="Label1" runat="server" Text='<%# Bind("Stock") %>'> </asp:Label> <asp:Label ID="Label2" runat="server" Text='<%# Bind("Quote") %>'> </asp:Label> | </itemtemplate> </asp:DataList> <asp:Label ID="Label3" runat="server" Text="Label"></asp:Label> </ContentTemplate> <triggers> <asp:asyncpostbacktrigger ControlID="Timer1" EventName="Tick" /> </triggers> </asp:UpdatePanel> <asp:Timer ID="Timer1" runat="server" Interval="10000" ontick="Timer1_Tick"> </asp:Timer> </form> </body> </html>
The really neat thing about this application (besides getting stock quotes) is that the postbacks happen transparently with AJAX. The way AJAX works is that an asynchronous postback happens and all of the code runs except the part that renders the new page data. Instead, text is sent back and JavaScript updates small areas of the page.
The underlying technology for AJAX is an XHTMLRequest, and this technology in its raw form has been around for a while. But, the raw form required wiring up callbacks and spinning your own JavaScript. You can still handcraft AJAX code of course, but now there are web controls, such as the UpdatePanel and Timer, that take care of the AJAX plumbing for you.
The elements that initiate the AJAX behavior are called triggers. Triggers can really be any postback event. Listing 1.12 uses the AJAX Timer's Tick event. (And, if you want this to actually look like a ticker, play with some styles and add some color.)