Creating a "What I'm Reading" WidgetBy Scott Mitchell
A number of personal websites and blogs have a "What I'm Reading" section, where the site owner lists books he's currently reading. Typically these widgets include a cover image of the book, the title and author, and a link the web visitor can click to buy the book or learn more about it. I recently needed to create a similar sort of widget for a website I was working on. This website did not require anything overly fancy, it just needed a simple administrative interface where the website administrator could enter book information and a User Control that he could drop on a web page that would display his current reading queue.
The solution I created uses an XML file to store information about the books displayed in the "What I'm Reading" User Control. The User Control uses a ListView and an XmlDataSource
to display the books in the XML file in a series of
<div> elements. And the administration page use a ListView control and the LINQ to XML library to
provide a web-based interface for adding, updating, and deleting data from this XML file.
This article looks at how I built the User Control and administration interface. The complete source code (in C#) and a demo application is available for download. Read on to learn more!
An Overview of the "What I'm Reading" User Control and Administrative Interface
The first design decision I faced when creating this widget was how to store the book information. I usually prefer storing data in a database, but decided against it in this case for a few reasons. First, the person I created this widget for wanted to be able to re-use this widget on other ASP.NET sites by simply uploading a few files to his web host provider. He did not want to have to worry about adding database tables, configuring database connection strings, and the like. He also wanted the ability to be able to have several different web properties use the same book data without having to maintain the information in all sites.
Given these requirements I decided to store the data in an XML file. By using an XML file the person using this widget doesn't need to bother creating a database table, and this widget can be used on sites that don't use a database. But it was the second requirement - the ability to have multiple websites all pull from the same data source - that cemented my decision to use XML. A single XML file can be maintained on one site (say, www.mainsite.com) and the other sites, which could be located on different web servers or even at different web host providers, can display this data by pulling the information from www.mainsite.com/ReadingList.xml (or whatever you name the XML file). The one potential downside of choosing XML in a hosted scenario is that if the XML file is going to be modified from an ASP.NET page, as it is in this case, then the user account that the ASP.NET engine operates under must be given modify permissions to the XML file. The good news is that most every web host provider offers a tool in their Control Panel that lets you adjust file system permissions.
In the past, XML was not always the easiest data store to work with. However, today it is incredibly easy to display, edit, update, and delete XML data. ASP.NET's XmlDataSource control can be used to display data in a data Web control without having to write a line of code. And the LINQ to XML framework that was introduced in ASP.NET version 3.5 allows for XML data to be queried, edited, and deleting a matter of a few lines of code. This was another reason why I decided to store the data in an XML file.
The entire "What I'm Reading" widget is composed of an XML file, a User Control, and an administrative web page, all of which are available for download at the end of this article
(along with a demo application that shows these features in action). In the demo application the XML file is located named
ReadingList.xml and is located in the
App_Data folder. (Note: ASP.NET prohibits HTTP access to the
App_Data folder, meaning that any files in this directory are not accessible
from an HTTP request. Consequently, if you plan on sharing a single XML file across multiple websites, as I mentioned earlier, then you will have to move this XML file out
ReadingList.xml has the following structure:
<books> is the root element; it contains a
<book> child element for each book that will appear in the "What I'm Reading" User Control.
<book> element has four children elements that supply the values for the four book attributes noted earlier: the book's title, the author(s), a URL
for more information about the book, and a URL for the book's cover image. All of these fields are required.
The User Control,
WhatImReading.ascx, essentially transforms the XML in the
ReadingList.xml XML file into HTML. Specifically, it generates a
<div> elements with anchor and image elements that show the book cover image, the title, and the author, linking the image and title to the
URL specified in the book's
<link> element. The screen shot on the right shows the User Control's output when there are three
elements in the XML file and produces the following (abbreviated) markup:
The final piece of the "What I'm Reading" widget is an administrative interface,
~/Admin/EditReadingList.aspx. This page uses a ListView control and some LINQ to
XML code in the code-behind class to provide an interface for adding new books to the XML file and for editing and deleting existing books. The user interface for this page
is quite intuitive and doesn't need a lot of explanation.
Displaying the Books in the User Control
WhatImReading.ascxUser Control displays the books in the XML file using an XmlDataSource control and a ListView. The XmlDataSource control returns the contents of a local or remote XML file returns a set of nodes in the XML document; you can use an optional XPath expression to narrow down the nodes returned. While not shown in the demo application available for download, you could configure the XmlDataSource to reference a remote XML file, such as www.mainsite.com/ReadingList.xml. The XmlDataSource control's
DataFileproperty indicates the location of the XML file, and it can point to a local file, like "~/ReadingList.xml", or a remote file, like "http://www.mainsite.com/ReadingList.xml".
The XmlDataSource in the User Control pulls in the XML content from the
ReadingList.xml file and returns the set of
book nodes by specifying the
/books/book. This data source control is bound to a ListView control, which renders the cover image as a hyperlink along with the title and
The XmlDataSource control returns one "record" for each
<book> element in the XML document. Each
<book> element's content can be accessed
via data binding syntax,
<%# XPath("expression") %>. For example, to retrieve the value of the
element the syntax
<%# XPath("title") %> is used.
For more information on using the ListView control refer to Using ASP.NET 3.5's ListView and DataPager Controls. For a deeper look at working with the XmlDataSource control, see Retrieving XML Data with XmlDataSource Control.
Managing the XML File Contents Through a Web-Based Interface
The XmlDataSource control is a handy tool for displaying XML data, but it does not offer built-in functionality for editing and deleting content from the XML document (like the SqlDataSource does). The good news is that it is quite easy to modify XML data using the LINQ to XML library, which was introduced in the .NET Framework version 3.5. A previous article on 4Guys by Miroslav Kadera, Working with XML Data Using LINQ, a TreeView, and a ListView, showed how with a few dozen lines of code you could build a page that provided a web-based interface for adding, updating, and deleting nodes from an XML document. I took Miroslav's code and example, tweaked it a bit, and used it to craft the administrative interface for this widget.
~/Admin/EditReadingList.aspx page contains a ListView that defines an
ItemTemplate displays a read-only interface that lists the title, author, link, and image URL for each
<book> element in the XML file.
InsertItemTemplate replicate this interface, but replace the read-only text with TextBoxes from which the user can specify
the value for these book fields. The
InsertItemTemplate is shown at the top of the ListView control, while the
EditItemTemplate is shown only when
a book's "Edit" button is clicked.
The ListView is populated via a few lines of LINQ to XML code. Likewise, LINQ to XML code is used to add a new node to the document, edit an existing node, or delete a node. I'm not going to go into an in-depth look at the markup and code in the administration page, as the nuts and bolts of the code and markup is already covered Working with XML Data Using LINQ, a TreeView, and a ListView. For a detailed look at how the administration page works and to see how LINQ to XML can be used to help build such a versatile web page, be sure to check out Miroslav's article.
|Be Sure to Secure the Administration Page!|
While the administrative page is in a folder named |
This article showcased a "What I'm Reading" widget that you are welcome to add to your website or extend in any way you like. The widget pulls its data from an XML file and includes a User Control that displays the list of books in the XML file as well as an administrative web page that offers a web-based interface for managing the XML data. Thanks to ASP.NET's XmlDataSource control and the LINQ to XML library, displaying and modifying XML data is a walk in the park.