Buy My Account


Basics
Overview
Video Demos
Pricing & Ordering
Sample Applications
Customers
News & Reviews
Download Now!

Product Tour
Product Tour
Web Applications
Mobile Applications
SharePoint Applications
Charts and Reports
Security
Architecture & Code
Team Development

Technical Materials
Training Courses
Online Help
Technical Forums
White Papers
What's New in V9.0
One Day Web Apps E-book
System Requirements
Product Roadmap
Version History

Enabling RSS and MediaRSS in Iron Speed Designer Applications


Learn how to disply information from your Iron Speed Designer application in RSS format.
- Neil Ennis, Director of Expert1 Pty Ltd

November 30, 2009
Iron Speed Designer V6.X

Introduction

Every business has a story to tell. New products you’ve created, staff promotions, interest rate changes, new clients -- these are all newsworthy items that happen in a business every day, and you should let others know about them. That’s what Real Simple Syndication (RSS) is about.

RSS and its extension, Media RSS (an RSS feed with media such as photos, video and sound), are ways of publishing news in a format that can be easily used multiple ways. They are invaluable tools to promote your business. This article shows how you can use your Iron Speed Designer application to take the information in your database and publish it in the RSS format.

If you’ve never heard of RSS or Media RSS, you might be interested in the following articles:

http://en.wikipedia.org/wiki/Rss
http://en.wikipedia.org/wiki/Media_RSS

Emma's Bears Example

Emma makes beautiful bears. Every time she completes a bear, she adds it to her inventory via an Iron Speed Designer application I wrote for her. Shortly after she adds the new bear, a fresh picture appears on her Bear slideshow, and news of it percolates to all her followers on Twitter.

Media RSS Essentials

As you can see from the examples above, the main components of a Media RSS feeds are:
    1. A title
    2. A link
    3. A description of the feed
    4. And other items, each of which contain:
        4.1. Item title
        4.2. Item description
        4.3. Item link
        4.4. Item publication date
        4.5. Item content
        4.6. A set of "media" tags required by MediaRSS applications
You can find out more about the format and rules regarding these specifications via the links I gave you at the start of this article.

Making it Happen

There are many ways of implementing this, but I’ve implemented MediaRSS for Emmas Bears by simply adding an ASPX page to the main folder of the application using Visual Studio.

Rss.aspx contains the following code:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="rss.aspx.vb" Inherits="rss" %>
<%@ OutputCache Duration="900" VaryByParam="none" %>
<% RenderXML() %>

The OutputCache tag tells the server to cache the feed contents for 900 seconds (15 minutes). If anyone requests to view the feed during a 15-minute period, they’ll always see the same feed. The server won’t render a new feed, it will just show whatever was available 15 minutes ago.

This is important. If your feed is popular, thousands of people might start following it. They might tell their feed readers to check for new content every 5 minutes. If a thousand people do this, your server will be hit with a thousand hits per minute. If you implement OutputCache, your server can take a vacation for 15 minutes and serve up the same thing 5,000 times.

The RenderXML function call does all the work and spits out the XML code of the feed. Here’s part of what’s in the code-behind, rss.aspx.

Visual Basic:

Imports System
Imports System.Configuration
Imports System.Data
Imports System.Data.SqlClient
Imports System.Text
Imports System.Web
Imports System.Xml
Partial Class rss
  'Inherits System.Web.UI.Page
  Inherits BaseApplicationPage
  Protected Sub RenderXML()
    Dim X As New X1
    ' start with a clean response stream
    Response.Clear()
    ' set the type to xml
    Response.ContentType = "text/xml"
    ' create a new XML document for the response
    Dim objX As New XmlTextWriter(Response.OutputStream, Encoding.UTF8)
    objX.WriteStartDocument()
    ' create header info for the xml doc
    objX.WriteStartElement("rss")
    objX.WriteAttributeString("version", "2.0")
    objX.WriteAttributeString("xmlns:media", "http://search.yahoo.com/mrss/")
    objX.WriteStartElement("channel")
    objX.WriteElementString("title", "EmmasBears.com Picture Feed")
    objX.WriteElementString("link", "http://EmmasBears.com/rss.aspx")
    objX.WriteElementString("description", _
    "Quality hand crafted Teddy Bears from EmmasBears.com")
    objX.WriteElementString("copyright", "(c) 2009, Emma Braiden. " & _
    "All rights reserved.")
    objX.WriteElementString("ttl", "15")
    objX.WriteRaw(vbNewLine)
 
    ' Do we want to just show a single picture?
    Dim ShowSingle As Boolean = False
    If Not IsNothing(Request.QueryString("single")) Then
        ShowSingle = True
    End If
 
    ' get latest 10 rows in the table
    Dim ob As New BaseClasses.Data.OrderBy(False, False)
    ob.AddColumn(ItemsTable.LastUpdated, BaseClasses.Data.OrderByItem.OrderDir.Desc)
    Dim irecs() As ItemsRecord = ItemsTable.GetRecords("1=1", ob, 0, 10)
    ' spin through each item
    For Each irec As ItemsRecord In irecs
        ' if we've got a photo, display it
        If Not IsNothing(irec.Photo1) Then
            RenderPhotoXML(Me.Page, irec, objX, 1)
        End If
        ' only show more photos of the same item if we're not in single-view mode
        If Not ShowSingle Then
            ' show second photo if we have one
            If Not IsNothing(irec.Photo2) Then
                RenderPhotoXML(Me.Page, irec, objX, 2)
            End If
            ' show third photo if we have one
            If Not IsNothing(irec.Photo3) Then
                RenderPhotoXML(Me.Page, irec, objX, 3)
            End If
            ' show fourth photo if we have one
            If Not IsNothing(irec.Photo4) Then
            RenderPhotoXML(Me.Page, irec, objX, 4)
            End If
        End If
    Next
 
    objX.WriteEndElement()
    objX.WriteEndElement()
    objX.WriteEndDocument()
    objX.Flush()
    objX.Close()
    Response.End()
  End Sub
  ' RenderPhotoXML is below, don’t forget to add it!
 
End Class

This sets the content type of the response stream to XML, builds an XML document, and then appends that document to web page’s response stream.

objX.WriteElementString adds XML elements to the document. You can see I’ve added "<title>", "<link>" "<description>", "<copyright>" and "<ttl>" elements. The "<ttl>" element specifies the "Time to Live" of the feed. It’s basically saying, "This feed isn’t going to change for the next 15 minutes, so if you come back during that time you won’t notice any change." Smart RSS readers will then override attempts by users to get the information more frequently.

The next bit of code fetches the most recent 10 items from the items table. In this example, I use the "LastUpdated" column in the items table. If Emma updates the description or information on any of her existing bears, it will generate a new article in the feed.

Notice I look at the query string parameter "single". I do this because each item in this database has up to four photos. That’s handy for slideshows, but if you’re just publishing the item description to a text-only news feed, you don’t want it to repeat four times.

Also notice that each time I add a photo and its description to the feed, I call the "RenderPhotoXML" function which is also part of the code-behind:

Public Sub RenderPhotoXML(ByVal MyPage As Page, ByVal iRec As ItemsRecord, _
ByVal objX As XmlTextWriter, ByVal PhotoNumber As Integer)
    Dim x As New X1  
    ' build a link to the item
    Dim strURL As String = x.AppendToURL(Me.Page, "Items/ShowItems.aspx?Items=" & _
    System.Web.HttpUtility.UrlEncode(iRec.GetID.ToXmlString()))
 
    ' build a link to the image
    ' note the & in the url. XML chokes on naked ampersands in some readers.
    Dim strImageURL As String = x.AppendToURL(Me.Page, "Items/ShowImage.aspx?ItemID=" & _
    CStr(iRec.ItemID)) & "&p=" & PhotoNumber
 
    ' start a new item
    objX.WriteStartElement("item")
 
    ' make the title the item name
    objX.WriteElementString("title", CStr(iRec.Name))
 
    ' add in the mediaRSS content
    objX.WriteRaw("<media:group>")
 
    objX.WriteRaw("<media:content")
    objX.WriteRaw(" url=""" & strImageURL & """")
    objX.WriteRaw(" type=""image/" & "jpeg" & """")
    objX.WriteRaw(" medium=""image""")
    objX.WriteRaw(" /> ")
    objX.WriteRaw(vbNewLine)
 
    objX.WriteElementString("media:title", CStr(iRec.Name))
 
    objX.WriteElementString("media:description", strURL)
    objX.WriteRaw(vbNewLine)
 
    ' note that in this example, the thumbnail is just the same the original image.
  ' For completeness, we should probably scale down the image size to thumbnail
  ' dimensions (say 50 x 50). Maybe next version?
    objX.WriteStartElement("media:thumbnail")
    objX.WriteAttributeString("url", strImageURL)
    objX.WriteEndElement()
    objX.WriteRaw(vbNewLine)
    objX.WriteRaw("</media:group>")
    objX.WriteRaw(vbNewLine)
 
    ' add in a normal <description> tag for normal RSS readers that don't understand
  ' the MediaRSS specification.
    ' this makes the feed useful for both RSS and MediaRSS readers
    ' build a <a href=[url]><img src=[url]/></a> construct
    Dim strLinkedImageUrl As String = x.Linkify("<img src='" & strImageURL & "' />", strURL)
    ' output the <description> node for this item
    objX.WriteElementString( _
        "description", _
        strLinkedImageUrl _
        & "<br/>" _
        & CStr(iRec.DescriptionHTML) _         & "<br/> On " _

        & CDate(iRec.DateEntered).ToString("R"))
    ' compelte the rest of the stuff for this item
    objX.WriteElementString("link", strURL)
    objX.WriteElementString("pubDate", CDate(iRec.LastUpdated).ToString("R"))
    objX.WriteEndElement()
    objX.WriteRaw(vbNewLine)
 
End Sub

This method adds a new "<item>" element to the XML, and then populates it with information about the photo: "<title>", "<media:group>", "<description>", "<link>" and "<pubDate>".

The "<media:group>" tag, and all tags starting with "<media:", are part of the Yahoo MediaRSS specification, which will be sought by any readers who take advantage of MediaRSS.

I add the "<description>" tag as well for standard RSS readers who don’t know anything about MediaRSS.

The code-behind also uses the following utilities that I place in a separate X1 object. I use this in several different projects. X1.vb lives in the app_code folder.

Imports Microsoft.VisualBasic
Imports System.Net
Imports System.IO
Imports System.Data
 
Public Class X1
    Public Function AppendToURL(ByVal MyPage As Page, ByVal NewPage As String) As String
        ' strip out the current page, and add a new page to a url
        Dim sUrl As String = MyPage.Request.Url.ToString
        Dim x As Integer = sUrl.Length
        While Mid(sUrl, x, 1) <> "/" And x > 0
            x -= 1
        End While
        Return Left(sUrl, x) & NewPage
    End Function
    Public Function AppendToURL(ByVal MyPage As String, ByVal NewPage As String) As String
        ' strip out the current page, and add a new page to a url
        Dim sUrl As String = MyPage
        Dim x As Integer = sUrl.Length
        While Mid(sUrl, x, 1) <> "/" And x > 0
            x -= 1
        End While
        Return Left(sUrl, x) & NewPage
    End Function
    Public Function Linkify(ByVal strText As String, ByVal strUrl As String) As String
        Return Linkify(strText, strUrl, 0, True)
    End Function
    Public Function Linkify(ByVal strText As String, ByVal strUrl As String, ByVal MaxLinkLength As Integer) _
As String
        Return Linkify(strText, strUrl, MaxLinkLength, True)
    End Function
    Public Function Linkify(ByVal strText As String, ByVal strUrl As String, _
ByVal MaxLinkLength As Integer, ByVal isPopup As Boolean) As String
        ' add a link to text
        '<a href="../html/find-a-cruise.cfm">Find A Cruise</a>
        If MaxLinkLength <= 0 Or strText.Length <= MaxLinkLength Then
            Return "<a href=" & strUrl & IIf(isPopup, " target=""_blank""", "") & " >" & strText & "</a>"
        Else
            strText &= " "
             Dim ix As Integer = strText.IndexOfAny(New Char() {" ", ",", ".", "(", ")", "?", "!"}, _
        MaxLinkLength)
            If ix > 0 Then
                Return "<a href=" & strUrl & IIf(isPopup, " target=""_blank""", "") & " >" & _
                RTrim(Left(strText, ix)) & "</a>" & Mid(strText, ix + 1)
            Else
                Return "<a href=" & strUrl & IIf(isPopup, " target=""_blank""", "") & " >" & _
            Left(strText, MaxLinkLength) & "</a>" & RTrim(Mid(strText, MaxLinkLength + 1))
            End If
        End If
    End Function
End Class
Finally, notice the "<img src=[url/>" tag refers to a "ShowImage.aspx" page. This is so I can render a database image in the feed via a unique URL. If I wanted, I could add more query string parameters to this page to allow scaling for thumbnails. For now, I’m just going to use one image size.

Here’s the ShowImage.aspx page:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ShowImage.aspx.vb" Inherits="Items_ShowImage" %>
<!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>Show Image</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    </div>
    </form>
</body>
</html>

As you can see, it’s a plain ASP.NET page with nothing much on it. The Page_Load event does all the work.

Here’s the code-behind:

Option Strict On
Imports System.IO
Imports System.Net
Imports BaseClasses
Imports BaseClasses.Utils
Imports BaseClasses.Web.UI.WebControls
Imports Bears.Business
Imports Bears.Data
 
Partial Class Items_ShowImage
  Inherits System.Web.UI.Page
 
  Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 
    ' this page is for inserting images from the database into the response stream
 
    ' for retrieving items if necessary
    Dim iRec As ItemsRecord = Nothing
 
    ' Cache images for up to 60 minutes.
    ' Recycling is kinder to the database server
    Dim CacheKey As String = "ShowImage.aspx?"
    CacheKey &= "ItemID=" & Request.QueryString("ItemID") & "&p=" & Request.QueryString("p")
 
    ' is this image in the cache?
    If Cache(CacheKey) Is Nothing Then
        ' not in the cache
        ' get the item from the database
        iRec = ItemsTable.GetRecord("ItemID=" & Request.QueryString("ItemID"))
        ' put it in the cache
        Cache.Insert(CacheKey, iRec, Nothing, DateTime.Now.AddMinutes(60), TimeSpan.Zero)
    Else
        ' it's in the cache, so recycle it.
        iRec = CType(Cache(CacheKey), ItemsRecord)
    End If
 
    ' have we got an item record?
    If Not IsNothing(iRec) Then
        ' convert Image to a memory stream
        Dim stream As MemoryStream = Nothing
        ' decide which photo to used, based on the "p" query string param
        Select Case CInt(Request.QueryString("p"))
          Case 1
            stream = New MemoryStream(iRec.Photo1)
          Case 2
            stream = New MemoryStream(iRec.Photo2)
          Case 3
            stream = New MemoryStream(iRec.Photo3)
          Case 4
            stream = New MemoryStream(iRec.Photo4)
        End Select
 
        ' put the stream into an image
        Dim img As System.Drawing.Image = System.Drawing.Image.FromStream(stream)
        ' output as JPG
        Response.ContentType = "image/jpeg"
        img.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
    End If
 
  End Sub
End Class

This page retrieves the item record based on the parameters passed in the query string. It then copies the data from that image into the response stream. The end result is that I can use ShowImage.aspx as the "src" of any "<img>" tag that needs to display images from the database.

To reduce the load on the database, image requests are cached for up to an hour. Since I’m only displaying the most recent 10 items, I don’t need to go back to the database for them each time. It’s more efficient to keep them in a cache.

What does it look like? Here’s a sample of some of the XML data that gets output:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>EmmasBears.com Picture Feed</title>
    <link>http://EmmasBears.com/rss.aspx</link>
    <description>Quality hand crafted Teddy Bears from EmmasBears.com</description>
    <copyright>(c) 2009, Emma Braiden. All rights reserved.</copyright>
    <ttl>15</ttl>
    <item>
        <title>Atticus and Rangle </title>
        <media:group>
            <media:content url="http://localhost:2067/Bears/Items/ShowImage.aspx?ItemID=4&p=1" type="image/jpeg" medium="image" />
            <media:title>Atticus and Rangle </media:title>
            <media:description>http://localhost:2067/Bears/Items/ShowItems.aspx?Items=%3ckey%3e%3ccv%3e%3cc%3eName%3c%2fc%3e%3cv%3eAtticus+and+Rangle+%3c%2fv%3e%3c%2fcv%3e%3c%2fkey%3e</media:description>
            <media:thumbnail url="http://localhost:2067/Bears/Items/ShowImage.aspx?ItemID=4&amp;p=1" />
        </media:group>
        <description><a href=http://localhost:2067/Bears/Items/ShowItems.aspx?Items=%3ckey%3e%3ccv%3e%3cc%3eName%3c%2fc%3e%3cv%3eAtticus+and+Rangle+%3c%2fv%3e%3c%2fcv%3e%3c%2fkey%3e target="_blank" ><img src='http://localhost:2067/Bears/Items/ShowImage.aspx?ItemID=4&amp;p=1' /></a><br/><p>Just showing Atticus and Rangle snuggled together.<br /><br />(Atticus is adopted - Rangles is currently still available)&nbsp;.<br />&nbsp;</p><br/> On Sat, 18 Apr 2009 10:31:09 GMT</description>
        <link>http://localhost:2067/Bears/Items/ShowItems.aspx?Items=%3ckey%3e%3ccv%3e%3cc%3eName%3c%2fc%3e%3cv%3eAtticus+and+Rangle+%3c%2fv%3e%3c%2fcv%3e%3c%2fkey%3e</link>
        <pubDate>Wed, 20 May 2009 20:11:13 GMT</pubDate>
    </item>
    <item>
        <title>Bethany </title>
        <media:group>
            <media:content url="http://localhost:2067/Bears/Items/ShowImage.aspx?ItemID=6&p=1" type="image/jpeg" medium="image" />
            <media:title>Bethany </media:title>
            <media:description>http://localhost:2067/Bears/Items/ShowItems.aspx?Items=%3ckey%3e%3ccv%3e%3cc%3eName%3c%2fc%3e%3cv%3eBethany+%3c%2fv%3e%3c%2fcv%3e%3c%2fkey%3e</media:description>
            <media:thumbnail url="http://localhost:2067/Bears/Items/ShowImage.aspx?ItemID=6&amp;p=1" />
        </media:group>
        <description><a href=http://localhost:2067/Bears/Items/ShowItems.aspx?Items=%3ckey%3e%3ccv%3e%3cc%3eName%3c%2fc%3e%3cv%3eBethany+%3c%2fv%3e%3c%2fcv%3e%3c%2fkey%3e target="_blank" ><img src='http://localhost:2067/Bears/Items/ShowImage.aspx?ItemID=6&amp;p=1' /></a><br/><p>Meet Bethany... <br /><br />Bethany is a lovely big girl made from a luxurious rich old-<br />gold brown dense curly mohair with a real shine to the pile. <br />She has big black deluxe glass eyes and ultra-suede whites. <br /><br />Bethany is fully and firmly lock-nut jointed, and stuffed <br />quite firmly with a heap of polyfill making her rather chunky <br />and naturally heavy (no need for weighting!). <br /><br />Bethany has black faux suede paw pads to match her over-sized <br />hand embroidered black perle thread nose. She wears a simple <br />baby-blue satin wire-edged ribbon bow around her head. <br /><br />Bethany has a little rag doll friend that comes with her as <br />well, it has been handmade by another Australian artist. <br /><br />Bethany is a one of a kind bear. Her adoption fee includes <br />registered post anywhere in the world, so no nasty surprises <br />of massive postage amounts due to her large size and weight. <br />&nbsp;</p><br/> On Sun, 19 Apr 2009 11:33:47 GMT</description>
        <link>http://localhost:2067/Bears/Items/ShowItems.aspx?Items=%3ckey%3e%3ccv%3e%3cc%3eName%3c%2fc%3e%3cv%3eBethany+%3c%2fv%3e%3c%2fcv%3e%3c%2fkey%3e</link>
        <pubDate>Wed, 20 May 2009 19:57:01 GMT</pubDate>
    </item>
... some data was deleted to improve readability...
  </channel>
</rss>

Using this Example in your Iron Speed Designer Application

Your Iron Speed Designer application will probably have different table and column names to those used in this example. My table name is "Items". When you incorporate the changes into your application, you’ll need to adjust the changes to suit your table and column names.

The above example has three main components. Here’s how to use them in your Iron Speed Designer application:

    1. ShowImage.aspx (and ShowImage.aspx.vb)
    Place this in the "Items" folder where all the existing Iron Speed Designer pages for the "Items" table reside. The example uses ItemsTable.GetRecord to retrieve info by the ItemID column about the items to publish. It displays images from the Photo1, Photo2, Photo3 and Photo4 columns. You’ll need to change the "ItemsTable", "ItemsRecord", "Items", "ItemID" and "Photo..." names to match those in your application.

    2. x1.vb .utilities class
    This contains general purpose utilities that can be reused throughout your application. You probably already have a utilities class or module containing useful tools. If so, just add the functions in x1.vb to your existing toolkit. Otherwise, save x1.vb in your App_Code\Business Layer folder. The functions are general purpose and won’t need altering.

    3. RSS.aspx (and RSS.aspx.vb)
    This is accessed by your subscribers, so place it where it’s easy to access - in the root folder of your application (at the same level as default.aspx and web.config. Alter the header text (title, link, description, and copyright nodes) to match the info about your feed.
    "title" – A General title for the feed. E.g. "Emma’s Bears. Picture Feed"
    "link" – The URL of feed.
    "description" – A short explanation of the function of the feed.
    "copyright" – copyright information about the feed.

As mentioned above, the example refers to the "Items" table, but you’ll need to alter this to use your table name.

In the "RenderPhotoXML" function, alter the following things about a specific item:

Variable "strImageURL" – change this to point to the aspx page that will render your images
XML elements "title" and "media:title" –a short description of the item.
XML elements "description" and "media:description" – a more detailed description of the item.
XML element "media:thumbnail" – the URL of the thumbnail of the image.
XML element "link" – the URL of the actual page that you want visitors to be taken to.
XML element "pubDate" – the publication date of the article. RSS readers need this item to figure out which items in your feed are new.

Tell the World

By adding Media RSS to your Iron Speed Designer application, you generate targeted and timely content that tells your story and promotes your organization. The content is automatically generated.

Any business would jump at the chance to publish free, self-generating news stories with pictures. By learning how to do this with Iron Speed Designer, you’ll enhance your skill set.

Once you’ve created your own Media RSS feed, experiment with it. Try using it on your blog, on social networking sites, and at some of the websites I mentioned at the start of this article.

If you’d like to see some of the fun things you can do with RSS, have a look at these online toys:

  • Slideshows with the Google Ajax Feed API

  • Eye candy for your website or blog with Vuvox

  • Automatically publish your latest RSS news feed to Twitter with TwitterFeed

  • And the ultimate way to mash up RSS content, Yahoo pipes

About the Author

Neil Ennis has more than 25 years experience as a software developer. He graduated from the University of Queensland in 1981 with a Bachelor of Science degree.

He is the creator of the popular IBS Finance and Tango32 loan management systems. His software has been used by lenders throughout Australia, the South Pacific and the UK since the 1980s.

Neil founded Expert 1 Pty Ltd in 2004. It specializes in the development of loan origination and loan management software with interfaces to most major banking systems and credit agencies.

Neil is an enthusiastic cruiser and built the ShipWatcher.com website as a free service to lovers of cruise ships.

  Support   Company Info  
 

Privacy Statement