views:

22

answers:

1

I have a user control that is featured on several pages of a heavily hit site. Some of these pages include our blog sidebar, our forum sidebar, and smack right in the middle of our home page. That means this control is rendered a lot. The control it meant to read in a twitter RSS feed for a specific account and write out the last 2 tweets. Below is the majority of my Page_Load for the control. I have it in a try {} catch because it seems that on production the site is unable to load the XML often, so I need to flip on a friendly error message.

try {
  var feed = XmlReader.Create(ResourceManager.GetString("TwitterRSS"));
  var latestItems = SyndicationFeed
    .Load(feed)
    .GetRss20Formatter()
    .Feed
    .Items
    .Take(2);

  rptTwitter.ItemDataBound += new RepeaterItemEventHandler(rptTwitter_ItemDataBound);
  rptTwitter.DataSource = latestItems;
  rptTwitter.DataBind();

} catch (Exception ex) {
  phError.Visible = true;
}

As you can see, I just fetch the 2 most recent items and repeat over them in a repeater for the front-end. If anything fails, I flip on the error PlaceHolder which says something like "Twitter is unavailable".

I often see this error message on the prod site so I'm wondering if it's making too many requests to the RSS feed. I was thinking about output caching the control for 10 minutes but I thought, "what if it gets cached in the error state"? Then it's guaranteed to display the error message panel for 10 minutes. My question is, is true that if it displays the error from the catch when its creating a newly cached version, will that truly be cached for 10 minutes (assuming I set Duration="600")? Does anyone have any tips as to how I can make this work better or cache when only real Twitter data is rendered, not the error message?

Thanks in advance

+1  A: 

Instead of caching the entire page, I would cache the application data returned by your

var latestItems = .... 

statement as well as if you receive an error. You can make the cache duration of each different so if you successfully get the data, cache it longer than if you got an error. One implementation would look like this:

object Twitter = Cache["MyTwitter"];

if(Twitter==null)
{
    // cache empty
    try
    { 
        var latestItems = (load items)
        Cache.Insert("MyTwitter", latestitems, null, DateTime.Now.AddSeconds(600),
            Cache.NoSlidingExpiration);
        Twitter = latestitems;
    }
    catch(Exception ex)
    {
        Cache.Insert("MyTwitter", ex.ToString(), null, DateTime.Now.AddSeconds(60),
            Cache.NoSlidingExpiration);
        Twitter = ex.ToString();
    }
}

if(Twitter is string)
{
    phError.Visible = true;
}
else
{
    rptTwitter.DataSource = Twitter;
    // rest of data binding code here
}

There are two parts here. The first part is to check the cache and if the object is not in the cache, do your loading. If there's an error just store a string in the cache.

Then with you object, if it's a string you know you've got an error. Otherwise it's the result of retrieving the twitter feed.

Keltex
Thanks! That's a great code snippet. I used it and it works well.
Mark Ursino