IE 8 Web Slices - part 2

See part 1 for the introduction of this web slice implementation where we set up the order web page. In the order page we showed where we set the RSS feed that we want to point to. In this part we will implement the Httphandler and RSS feed.

There's plenty of information available on how Httphandlers work, I won't go into the details about that. Our Httphandler listens for requests coming in to our SalesOrderWeb web site that takes the form http://localhost/SalesOrderWeb/123/OrderTracking.rss where "123" is the SalesOrderId of an order in the AdventureWorks database we want to look up.

The IHttpHandler interface have one method and one property that must be implemented:

  • IsReusable
  • ProcessRequest
The IsResuable property has confused many developers due to very sparse documentation about it. It can be set to true if multiple requests can process the HttpHandler at the same time, i.e. we don't have any private data or similar that could inadvertily be shared between two requests that run at the same time. Clear as mud? Good. Our HttpHandler does not have any data that is shared between requests so we can set IsResuable to true.

The ProcessRequest method will process the requests for us and output the processed data when we are done. This sequence diagram shows roughly the sequence of events that takes place.



The actual ProcessRequest method in our HttpHandler looks like this:


public void ProcessRequest(HttpContext context)
{

if (ValidateParameters(context) == false) // Not good
{
context.Response.StatusCode = 500;
context.Response.End();

return;
}

string[] requestPath = context.Request.Path.Split((char)'/');
string salesOrderNumber = requestPath[2];

FeedChannel chan = new FeedChannel(salesOrderNumber);
string feed = chan.GetRSSFeed();

context.Response.ContentType = "text/xml";
context.Response.Write(feed);
}


The first thing we need to do is to validate the input which is handled in the ValidateParameters method. In this sample we're just checking that we have what appears to be a SalesOrderId and then we get the salesOrderId out of the request.

Next, we instantiate the FeedChannel which loads the SalesHeader and SalesDetail for this sales order and we build the html that will be displayed in the "Description" field in the RSS item. In this implementation we only will have one single FeedItem but it's possible to have more than one FeedItem for every channel if you have aggregate data that you want to display in your feed.

We call the GetRSSFeed method which will create the XML we want to output and display in the web slice. We use the XmlDocument in .Net and the associated classes to help build the request in this case.


public string GetRSSFeed()
{
XmlElement workNode = null;
XmlElement itemNode = null;

// Get the custom section which contains the default values for the RSS feed.
SalesOrderConfigSection soSection = SalesOrderConfigSection.GetConfig();

XmlDocument doc = new XmlDocument();
XmlProcessingInstruction pi =
doc.CreateProcessingInstruction("xml-stylesheet",
string.Format("type='text/css' href='http://{0}/SalesOrderWeb/css/rss.css'"
, Dns.GetHostName()));
doc.AppendChild(pi);

XmlElement docNode = doc.CreateElement("rss");
XmlAttribute attribute = doc.CreateAttribute("version");
attribute.Value = "2.0";
docNode.Attributes.Append(attribute);
doc.AppendChild(docNode);

// Create the channel element and its subelements:
XmlElement channelElement = doc.CreateElement("channel");
docNode.AppendChild(channelElement);

AddElement(doc, channelElement, "title", string.Format(_title, SalesOrderId));
AddElement(doc, channelElement, "link", string.Format(soSection.URL,
Dns.GetHostName(), SalesOrderId));
AddElement(doc, channelElement, "description", soSection.Description);
AddElement(doc, channelElement, "ttl", soSection.ttl);

// Add the information about each line item.
foreach (FeedItem feedItem in _feedItems)
{
itemNode = doc.CreateElement("item");
channelElement.AppendChild(itemNode);
workNode = doc.CreateElement("title");
workNode.InnerText = string.Format(feedItem.Title, SalesOrderId);
itemNode.AppendChild(workNode);
workNode = doc.CreateElement("description");
workNode.InnerText = feedItem.Description;
itemNode.AppendChild(workNode);
workNode = doc.CreateElement("link");
workNode.InnerText = string.Format(soSection.URL, Dns.GetHostName(), SalesOrderId);
itemNode.AppendChild(workNode);
}

return doc.OuterXml;
}


The returned xml is written into the HttpResponse, formatted as text/xml and returned to the browser.


context.Response.ContentType = "text/xml";
context.Response.Write(feed);


The feed is a fairly normal RSS feed that can be viewed in the browser, in a separate RSS Reader or in the web slice as the intent was in this case.