in

ASP.NET Weblogs

This Blog

Syndication

Jason Salas' WebLog

On-air and online: making people laugh, making people think, pissing people off

Code download: RSS custom server control

I wrote this custom server control class to demonstrate how easy it is to develop a portable control generating RSS feeds for a content-oriented site.  It formats data coming out of a SQL Server database to conform with the RSS 2.0 Specification

The only requirement is that since this control generates XML data, a page using the control can have no other HTML headers or markup other than the control, and page-level directives, so output caching will still apply to the XML-based data.  For example, this would be the code in a client page, like an .ASPX or .ASCX file:

<%@ Page debug="false" trace="false" language="c#" AutoEventWireup="false" %><%@ Page debug="false" trace="false" language="c#" AutoEventWireup="false" %>
<%@ Register TagPrefix="kuam" Namespace="RSSFeed" Assembly="RSSFeed"%>
<%@ OutputCache Duration="30" VaryByParam="none" Location="server" %>

<kuam:rssgenerator id="rssgen1" runat="server" SQLString="SELECT ID,Date,Title,Author,Description FROM ContentDBTable" Server="server=localhost;database=CompanyContent;uid=sa;pwd=;enlist=false;" DataFormatString="
http://www.mysite.com/news/{0}.aspx"/>

Here's the skinny on the object model (3 public properties):

  • DataFormatString - an echo of the .NET Framework's property of the same name, for structuring the destination URL
  • Server - the database connection string for the data store to hit
  • SQLString - the query to execute against the specified DB

There's some room for improvement, which is very easily done, notably in the following areas:

  • support for databases other than SQL Server (Access, Oracle, ODBC, etc.)
  • support for XML-based data stores
  • a few more public properties for more customization

Let me know if you find it helpful, and write me if you extend it to fit your own uses.  I did this in between TV shows, and I'm always a sucker for improvement.  :)


using System;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.ComponentModel;

using System.Text;

using System.Data;

using System.Data.SqlClient;

 

namespace RSSFeed

{

        /// <summary>

        /// This custom server control grabs data from KUAM.COM to be used as an RSS feed for headlines.

        /// This control requires removing all of the HTML headers from a page (no content).  Therefore, the only

        /// things that can be on the page are the control itself and any page-level directives.

        /// </summary>

        [DefaultProperty("Text"),ToolboxData("<{0}:rssgenerator runat=server></{0}:rssgenerator>")]

        public class rssgenerator : System.Web.UI.WebControls.WebControl

        {

               // data members

               private string _sql;

               private string _serverName;

               private string _url;

                      

               // public properties

               [Bindable(true),Category("Data"),DefaultValue("")]

               public string SQLString

               {

                       get {return this._sql;}

                       set {this._sql = value;}

               }

 

               [Bindable(true),Category("Data"),DefaultValue("")]

               public string Server

               {

                       get {return this._serverName;}

                       set {this._serverName = value;}

               }

 

               [Bindable(true),Category("Data"),DefaultValue("{0}")]

               public string DataFormatString

               {

                       get {return this._url;}

                       set {this._url = value;}

               }

 

               // get the daily news

               private string GetRSSNewsFeed(string server,string sql)

               {

                       SqlConnection conn = new SqlConnection(server);

                       SqlCommand comm = new SqlCommand(sql,conn);

                       SqlDataReader dr;

              

                       string newsFeedData = string.Empty;

 

                       try

                       {

                              conn.Open();

                              dr = comm.ExecuteReader(CommandBehavior.CloseConnection);

 

                             newsFeedData += "<!-- RSS Newsfeed custom server control -->\n";

                              newsFeedData += "<!-- Written by Jason Salas \n Web Development Manager / News Anchor, KUAM News \n jason@kuam.com \n http://weblogs.asp.net/jasonsalas/ \n December 19, 2003 -->\n";

                              newsFeedData += "<rss version=\"2.0\">\n\t<channel>";

                             

                              while(dr.Read())

                              {

                             // TODO: make the array of DB values come from a string[] array, use boolean operator for data provider

                                      newsFeedData += "\n\t\t<item>\n\t\t\t<title>" + MakeDataXMLSafe(dr.GetString(2)) + "</title>\n\t\t\t<description>";

                                      newsFeedData += CreateAbstract(dr.GetString(4)) + "</description>\n\t\t\t<link>";

                                      newsFeedData += MakeDataXMLSafe(string.Format(DataFormatString,dr.GetInt32(0))) + "</link>\n\t\t\t<author>";

                                      newsFeedData += MakeDataXMLSafe(dr.GetString(3)) + "</author>\n\t\t\t<pubDate>";

                                      newsFeedData += MakeDataXMLSafe(string.Format("{0:D}",dr.GetDateTime(1).ToString())) + "</pubDate>\n\t\t</item>";

                              }

                              dr.Close();

 

                              newsFeedData += "</channel>\n\t</rss>";

                       }

                       catch(SqlException ex)

                       {

                              newsFeedData += ex.ToString();

                       }

                       catch(Exception ex)

                       {

                              newsFeedData += ex.ToString();

                       }

                       finally

                       {

                              if(conn.State == ConnectionState.Open) conn.Close();

 

                              comm.Dispose();

                              conn.Dispose();

                       }

                       return newsFeedData;

               }

 

               private string MakeDataXMLSafe(object data)

               {

                       string dataString = data.ToString();

                       dataString = dataString.Replace("'","&apos;");

                       dataString = dataString.Replace("\"","&quot;");

                       dataString = dataString.Replace(">","&gt;");

                       dataString = dataString.Replace("<","&lt;");

                       dataString = dataString.Replace("&","&amp;");

 

                       return dataString;

               }

 

               private string CreateAbstract(string bodyContent)

               {

                       // create an story summary by truncating the BODY field of the DB table

                       int periodIndex = bodyContent.IndexOf(".");

                       string finalText = string.Empty;

 

                       if(periodIndex < 150)

                       {

                              int newPeriodIndex = bodyContent.IndexOf(".",periodIndex+1);

                              finalText = bodyContent.Substring(0,newPeriodIndex);

                       }

                       else

                       {

                              finalText = bodyContent.Substring(0,periodIndex);

                       }

                       return finalText + " ... ";

               }

 

               protected override void OnInit(EventArgs e)

               {

                       // set the MIME type for the page in which the control sits to XML

                       this.Context.Response.ClearContent();

                       this.Context.Response.ClearHeaders();

                       this.Context.Response.ContentType = "text/xml";

               }

              

               protected override void Render(HtmlTextWriter output)

               {      

                       output.Write(GetRSSNewsFeed(_serverName,_sql));

               }

        }

}

Comments

 

asdf said:

asdf
February 1, 2004 3:13 AM
 

TrackBack said:

December 13, 2004 10:28 AM
 

TrackBack said:

December 13, 2004 12:08 PM
 

TrackBack said:

December 13, 2004 8:30 PM

Leave a Comment

(required)  
(optional)
(required)  
Add