Thursday, September 19, 2024

Displaying the Details for a Particular News Item

This is Part 5 of a 5 part article “Creating An Online RSS News Aggregator With ASP.NET”.

All that remains left to do is to display the detailed information for the particular news item the user selected. This detailed information will be displayed in the bottom right frame, and will show the title of the news item entry, its description, and a link to the news item. As with the DisplayNewsItem.aspx Web page, DisplayItem.aspx starts by retrieving the remote RSS syndication feed based on the passed-in FeedID querystring parameter. It then uses an XML Web control to display the detailed information. In fact, the Page_Load event handler for the DisplayItem.aspx Web page is identical to the DisplayNewsItem.aspx Web page’s Page_Load event handler save for two minor differences:

  • DisplayItem.aspx needs to read in the value of the ID querystring parameter, and
  • DisplayItem.aspx uses an XSLT parameter, but one different from DisplayNewsItem.aspx.
  • As with DisplayNewsItem.aspx, DisplayItem.aspx needs to pass in a parameter into the XSLT stylesheet. Whereas DisplayNewsItem.aspx passed in the querystring parameter for FeedID, DisplayItem.aspx needs to pass in the ID querystring parameter, which indicates what news item the XSLT stylesheet should display. These minor changes are shown in the Page_Load event handler below in a bold font; code identical to the Page_Load event handler from DisplayNewsItems.aspx has been omitted:

    private void Page_Load(object sender, System.EventArgs e)
    {
    &nbsp // See if the news items for this feed are in the Data Cache
    &nbsp int feedID = Int32.Parse(Request.QueryString["FeedID"]);
    &nbsp int ID = Int32.Parse(Request.QueryString["ID"]);

    ...

    &nbsp // Now that we have the feed URL, load it in into an XML document
    &nbsp XmlDocument feedXML = new XmlDocument();
    &nbsp feedXML.Load(feedURL);

    &nbsp xmlNewsItems.Document = feedXML;

    &nbsp this.xmlItem.Document = feedXML;

    &nbsp // Add the ID parameter to the XSLT stylesheet
    &nbsp XsltArgumentList xsltArgList = new XsltArgumentList();
    &nbsp xsltArgList.AddParam("ID", "", ID);
    &nbsp xmlItem.TransformArgumentList = xsltArgList;
    }

    The XSLT stylesheet to transform the XML data can be seen below:

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:stylesheet version="1.0"
    &nbsp&nbsp&nbsp xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    &nbsp <xsl:output method="html" omit-xml-declaration="yes" />
    &nbsp <xsl:param name="ID" />

    &nbsp <xsl:template match="/rss/channel">
    &nbsp&nbsp <b><xsl:value-of select="item[$ID]/title"
    &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp disable-output-escaping="yes" /></b>
    &nbsp&nbsp <p>
    &nbsp&nbsp&nbsp <xsl:value-of select="item[$ID]/description"
    &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp disable-output-escaping="yes" />
    &nbsp&nbsp </p>
    &nbsp&nbsp <a>
    &nbsp&nbsp <xsl:attribute name="href"><xsl:value-of
    &nbsp&nbsp select="item[$ID]/link" /></xsl:attribute>
    &nbsp&nbsp&nbsp <xsl:attribute name="target">_blank</xsl:attribute>
    &nbsp&nbsp&nbsp Read More...
    &nbsp&nbsp </a>
    &nbsp </xsl:template>
    </xsl:stylesheet>

    Note that an <xsl:param> element is used to declare the ID XSLT parameter. Then, in the various <xsl:value-of> elements, the ID parameter is used to grab just the specific <item> element from the list of item elements. Realize that in XPath the syntax elementName[i] accesses just the Ith element with the appropriate element name. For example, item[1] would retrieve just the first <item> element, while item[2] would retrieve just the second. Therefore, item[$ID] retrieves just the <item> element as specified by the ID XSLT parameter.

    Finally, note that the Read More hyperlink, outputted near the end of the XSLT stylesheet, has its target attribute set to blank, thereby causing a new window to be opened when a user clicks on the Read More link.

    Future Enhancements and Current Shortcomings

    One glaring shortcoming with the code we examined in this article is that each time the user clicks on a syndication feed from the left frame, or clicks on a news item title from the top right frame, the remote RSS syndication feed is loaded and parsed. Clearly this is inefficient since once you click on a syndication feed all of the items are loaded; it is wasteful to reload the entire remote syndication feed each time the user clicks on one of the feed’s news item titles. Not only is this approach inefficient, but impolite to the person or company providing the syndication service, as these incessant and needless requests are placing an unnecessary load on their Web server.

    This shortcoming is overcome in the source code you can download with this article. Specifically, the .NET Data Cache is used to store the XmlDocument object for the various feeds. The cache duration is set to the value of the feed’s UpdateInterval field in the Feeds table. (Of course, the feed’s XmlDocument object could be evicted from the cache at an earlier point in time for a variety of reasons.)

    Another shortcoming of the system is that there is no state between the top right and bottom right frames. To see where this can lead to trouble, consider the following actions:

    1. A user clicks on a syndication feed link from the left frame, loading the feed’s news items in the top right frame. Assume that this syndication has an UpdateInterval value of 30, meaning that is expires in 30 minutes.

    2. In loading the news items in the top right frame, the feed is cached in the data cache.

    3. The user leaves for lunch.

    4. The Web site providing the syndication service adds a new news item.

    5. Our user returns from an hour lunch, meaning the XmlDocument for this feed in the data cache has expired.

    6. The user clicks on the first news item from the top right frame. This loads DisplayItem.aspx in the bottom frame, passing in an ID parameter value of 1.

    7. DisplayItem.aspx cannot find the XmlDocument in the cache, so it request the syndication feed from the remote source. In response it gets the new syndication feed (remember, a new news item was added back in step 4) and displays the first item (since the ID parameter equals 1).

    8. The user is displayed the new news item, which is a bit perplexing to the new news item is not displayed in the top right frame and was not the one they thought they clicked on.

    This problem arises because the ID parameter does not uniquely identify each news item; rather, it is only an offset of the news item from a list of news items at a particular point in time. A good way of fixing this would be to stop using the data cache to store each syndication feed, and start using a database, or some other means of persistent storage (such as XML files on the Web server’s local file system). By using a database, each news item can be given a unique identifier, which can then be passed down to the bottom right frame. This approach guarantees against the problem outlined above. Of course this adds some additional complexities, such as deciding when to clear old items out of the database.

    The existing application also lacks any exception handling. This should definitely be added. In particular, exception handling needs to be added for retrieving and loading the remote RSS syndication file into the XmlDocument object. The file might not exist, or might be malformed.

    There are a plethora of enhancements that one could easily add to this online news aggregator. One obvious one would be an administration page to allow the user to add, remove and edit their existing syndication feeds. Also, it would be nice to allow the user to group their syndication feeds by user-created categories. The user interface is a bit hard on the eyes, but this could be quickly fixed by either augmenting the HTML generated by the XSLT stylesheets or adding stylesheets to the various frames to allow for a more aesthetic appearance. Finally, it would be worthwhile to add some HTML tags to cause the top right frame to refresh periodically so that the user can see new news items for a particular syndication feed without having to manually refresh the Web page.

    Note (August 4, 2003): After publication of this article, a few people emailed me informing me of two potential issues with displaying the of a particular RSS syndication item the way I show in the article:

    1. Disable-output-encoding, which is used in the , is not uniformly implemented by all XSLT parsers. The .NET XSLT parser supports disable-output-encoding, but just be aware of this in case you attempt to port this application to other platforms.

    2. The HTML content in the <description> element is blindly emitted. This HTML might contain malicious code, such as <script> or <embed> blocks which should, ideally, be stripped out. In order to strip out these potentially offensive HTML elements, you would likely need to use extension functions (See Extending XSLT with JScript, C#, and Visual Basic .NET). For more information on the need for stripping HTML content from an RSS feed, refer to this ‘Dive Into Mark’ blog entry.

    Summary

    In this article we examined building not only a syndication engine, but an online news aggregator as well. In building both products we worked with displaying XML data in an ASP.NET Web page. With the syndication engine, we displayed database data in an XML format using a Repeater control. In the news aggregator, we used XML Web controls with XSLT stylesheets.

    I invite you to download the online news aggregator and make enhancements to it as you see fit. If you have any questions with regards to the application or the concepts discussed in this article, don’t hesitate to shoot me an email; I can be reached at mitchell@4guysfromrolla.com.

    Happy Programming!

    Recommended Links

  • Displaying XML Data in an ASP.NET Web Page
  • ASP.NET XML Web Control Technical Documentation: reference for the XML Class
  • XSLT Tutorial
  • XPath Tutorial
  • The XML Forum at the ASP.NET Forums
  • Caching with ASP.NET

    *This article originally appeared on the ASP.NET Dev Center at MSDN

    Scott Mitchell, author of five ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies for the past five years. An active member in the ASP and ASP.NET community, Scott is passionate about ASP and ASP.NET and enjoys helping others learn more about these exciting technologies. For more on the DataGrid, DataList, and Repeater controls, check out Scott’s book ASP.NET Data Web Controls Kick Start (ISBN: 0672325012). Read his blog at : http://scottonwriting.net

    Related Articles

    LEAVE A REPLY

    Please enter your comment!
    Please enter your name here

    Latest Articles