ASP.NET Server Control: FeedList - List most recent items from an RSS feed as links

April 21, 2008 22:30 by MartinHN

RSS feeds is everywhere, and rightly so. Just about any modern browser, e-mail client, search engine or mobile phone is compliant with the RSS technology, and it gives web developers an easy and very convenient way to share and consume content across the web. From time to time I need to show a list of recent items form an RSS feed. This is a very easy thing to do, and I always end up copying the same usercontrol around, which becomes nothing but a mess! Eventually I need to change a few things, which means I get different versions of the same control spread throughout my projects.

This mess has got to stop, and from now on I'll put all my common controls in a class library project, which I can reference from all the other projects.

Back to my RSS feed reader - this is the first control I've made into a server control, from one of my many usercontrols around the projects folder. The control downloads the XML at the Url of the RSS feed, and renders a list of links. The controls contains a few properties:

  • FeedUrl: The Url of the RSS feed to download
  • NumberOfItems: The number of items which should be rendered. Defaults to 5 if none is specified.
  • CssClass (Part of the WebControl class, from which FeedList derives): Use this so you have style the control from CSS.

The code

It really is straight forward. Below is the method that renders the links.

private void RenderFeedItems(HtmlTextWriter writer)
{
  if (!String.IsNullOrEmpty(FeedUrl))
  {
    XmlDocument doc = new XmlDocument();
    doc.Load(FeedUrl);

    XmlNodeList items = doc.DocumentElement.SelectNodes("channel/item");

    if (items != null)
    {
      int bounce = NumberOfItems;
      if (items.Count < NumberOfItems)
        bounce = items.Count;

      for (int i = 0; i < bounce; i++)
      {
        XmlNode titleNode = items[i].SelectSingleNode("title");
        XmlNode urlNode = items[i].SelectSingleNode("link");
        XmlNode pubDateNode = items[i].SelectSingleNode("pubDate");

        string title = String.Empty;
        string url = String.Empty;
        DateTime pubDate = new DateTime();

        if (titleNode != null)
          title = titleNode.InnerText;

        if (urlNode != null)
          url = urlNode.InnerText;

        if (pubDateNode != null)
          DateTime.TryParse(pubDateNode.InnerText, out pubDate);

        writer.RenderBeginTag(HtmlTextWriterTag.Li);

        writer.AddAttribute(HtmlTextWriterAttribute.Href, url);
        writer.AddAttribute(HtmlTextWriterAttribute.Title, title);
        writer.RenderBeginTag(HtmlTextWriterTag.A);
        writer.Write(title);
        writer.RenderEndTag();

        writer.RenderEndTag();
      }
    }
    else
    {
      RenderErrorMessage(writer, String.Format("No RSS-feed items found at: {0}", FeedUrl));
    }
  }
  else
  {
    throw new Exception("FeedUrl cannot be empty!");
  }
}

To use the control, put it in your website's App_Code folder, and add the following to the <controls> collection of your <pages> section in web.config:

<add tagPrefix="dnknormark" namespace="dnknormark" />

This should make your <pages> section look like this one:

<pages>
  <controls>
    <add tagPrefix="dnknormark" namespace="dnknormark" />
  </controls>
</pages>
 
And to put it on an aspx page, and show the latest 5 items from this blog, add this line to the page:
 
<dnknormark:FeedList ID="lstFeeds" runat="server" CssClass="feedList" 
NumberOfItems="5" FeedUrl="http://www.dnknormark.net/syndication.axd" />

Use it as you'd like. Feel free to change it, the way you need.


kick it on DotNetKicks.com


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Add to: Facebook Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Technorati

Event performance optimization with the EventHandlerList

December 25, 2007 23:35 by MartinHN

When using custom events (event delegates) in your ASP.NET pages, user controls and server controls, many developers might define their Events as public fields, like this:

public event EventHandler<EventArgs> MyCustomEvent;


And use this code to fire the event:

protected void OnMyCustomEvent(EventArgs e)
{
  if(MyCustomEvent != null)
  {
    MyCustomEvent(this, e);
  }
}

 

Nothing is wrong with the approach of the latter, but defining the MyCustomEvent as a public field introduces two problems:

    1. Even though no clients have registered any delegates to the invocation list of your event, the compiler generates
      one private delegate field for each event delegate in your class. This is a waste of server memory, especially if
      you have several events inside your class.

    2. One Add and one Remove method is generated for each event field of your class. When clients use += and -= to add
      and remove delegates from the invocation lists of your class' events, these methods are called behind the scenes.
      These two compiler-generated methods are thread-safe, which means they include extra code to synchronize threads
      that are accessing these methods. This means, that everytime a client adds or removes a delegate to or from the
      invocation list of an event, they have to get a lock before they can do the actual work. This introduces an
      unnecessary overhead because most page developers don’t use multiple threads and therefore there is no need for
      thread synchronization.

     

    The EventHandlerList is the answer to our issues. This class comes with the .NET Framework. The EventHandlerList is a linked list of delegates,which is optimized for adding and removing delegates. To use the EventHandlerList in your classes, you need to add a private static key for each event your class exposes. The code bellow defines a key for MyCustomEvent:

    private static readonly object MyCustomEventKey = new object();

    The memory is allocated only once, because the key is static.

    After this, you need to define your events as properties - not fields. These event properties has a different syntax that normal get-set properties. Event properties uses add-remove instead of get-set. The following property, is an event property for MyCustomEvent:

    public event EventHandler<EventArgs> MyCustomEvent
    {
      add { Events.AddHandler(MyCustomEventKey, value); }
      remove { Events.RemoveHandler(MyCustomEventKey, value); }
    }
     

    Every Page, UserControl and WebControl - among others - has a protected property of type EventHandlerList named Events. With this approach, when clients use += to add a delegate to the invocation list of the MyCustomEvent, the add method of the event property calls the AddHandler method of the EventHanderList class, as the code above will tell you. As for -= the RemoveHandler method is called.

    The EventHandlerList class maintains a linked list which can have none or one entry for each event. The AddHandler method checks whether this internal linked list contains an entry for an event with the given event key. If it does, the method calls the Combine method of the Delegate class to add the client delegate to the invocation list of the event. If this internal list doesn’t contain an entry for an event with the given event key, the AddHandler method just adds a new entry.

    With this new approach, we need to update our OnMyCustomEvent Method, which is responsible for firing the event:

    protected void OnMyCustomEvent(EventArgs e)
    {
      EventHandler<EventArgs> handler = Events[MyCustomEventKey] as EventHandler<EventArgs>;
    
      if (handler != null)
        handler(this, e);
    }
     

    This method uses the MyCustomEventKey as an index in the Events list to access the MyCustomEvent-event. The Events list will return null if it does not contain an entry at the specified index. This will happen when no clients has subscribed to the MyCustomEvent.

    Using the EventHandlerList class automatically resolves the two previously mentioned performance problems with the event fields.

    Technorati Tags: ,

     

    kick it on DotNetKicks.com

    Currently rated 5.0 by 1 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Add to: Facebook Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Technorati

    Windows Vista / Mac debugging a Silverlight app using Visual Studio 2008

    December 24, 2007 01:38 by MartinHN

    As I wrote recently in another blog post about a .NET Rocks interview with Brad Abrams, I was very impressed with his keynote at ReMix Boston, where he did the Linux / Vista / Mac debugging. I referred to Richard Campbell's opinion that he didn't believe it would work. At the end of the post, I wrote that I want to try it for myself, to see if it really works. Brad Abrams posted a comment to my blog post, saying that it should work just fine. Well. This post tells the story.

    Prerequisites

    • A Windows machine with Visual Studio 2008 and Silverlight Tools Alpha for Visual Studio 2008 installed.
    • A Macintosh with the Silverlight 1.1 Alpha installed.
    • A network connection on both machines and a way to transfer files between the Vista box and the Mac. (A USB flash drive/stick is fine)
    • A Silverlight 1.1 Alpha project linked to a website, ready to run.
    • The website has to be remotely accessible. (Otherwise you can copy the website to the Mac as static HTML files, and run it locally from there.)

    Debugging environment

    This is the environment I will use for the debugging. For starters, I want to concentrate on the Vista / Mac debugging, so I won't set up a Linux box with Apache and serve the Silverlight app on a PHP page. But there really should be no problem to it. You can even copy a static HTML page with the XAML page, and the assemblies to the Mac, and run the Silverlight app locally, and attach the Visual Studio debugger to the Safari process on the Mac. Let's save the Linux box for another time.

    The mac: Basically just a Macbook with default configurations, and no special software.

    The Vista box: This is my development box. Windows Vista with Visual Studio 2008, IIS 7 and an ASP.NET website set up at localhost.

    Before we get started, locate your Visual Studio 2008 folder on the Vista box (usually: C:\Program Files\Microsoft Visual Studio 9.0), and find the Silverlight folder. This folder contains the necessary files to do the initial set-up. You'll also find a guide to set-up and start debugging, but I've found a few mistakes in there, and you can find yourself confused.

    Setting up the Mac for Silverlight debugging

    Remote debugging is not as easy as pointing Visual Studio to a remote computer, and selecting a process to debug. You have to authenticate against the remote machine. This is done via an SSL encrypted TCP channel between the debugger (The Vista box) and the target machine (The Mac). You will need to set-up the TCP port along with a private/public key pair. This is done in 6 easy steps:

    1. Copy the contents of the C:\Program Files\Microsoft Visual Studio 9.0\Silverlight\MacIntel folder to a destination on the Mac of your choosing.
    2. Start up a Terminal on the Mac, and execute the 'configcoreclrdebug' using an absolute filepath. e.g.: /MacIntel/configcoreclrdebug.
    3. First, your private/public key pair will be generated, and then you have to specify a TCP port in the range of 49152 - 65535. Just pick a number.
    4. Then you need to enter a password, and confirm it. Choose a password of at least 8 characters.
    5. A hidden directory is created in your Users folder, located here: /Users/username/.coreclrdbg - copy the "ConfigureWindowsCoreCLRDebugging.exe" file to the Vista box, in a destination of your choosing.
    6. Execute the 'core_clr_proxy' file on the Mac from the Terminal, using an absolute filepath like this: /MacIntel/coreclr_dbg_proxy

    image  image

    That was all the set-up needed on the Mac for now. Next up is setting up the Vista box.

    Setting up the Vista machine for Silverlight debugging

    This is the easy part.

    1. From a command prompt, run the "ConfigureWindowsCoreCLRDebugging.exe" which you just copied from the Mac.
    2. Enter the password you created on the Mac in step 4, and hit Enter.

    Starting the debugger

    Now to the exciting part. Will it work, or not?

    1. Launch Safari on the Mac, and point the address to the URL of your Silverlight application you wish to debug.
    2. Launch Visual Studio 2008 on the Vista box, and open the Silverlight project that you wish to debug.
    3. Open up a source file, and set a breakpoint.
    4. From the Debug menu, click Attach to Process. (Or hit Ctrl + Alt + P)
    5. From the Transport drop down menu, select 'CoreCLR Remote Cross-platform Debugging'.
    6. Enter the IP address or hostname of the Mac in the Qualifier box bellow and hit Enter.
    7. Now you should see a list of processes running on the Mac. Anyone that has CoreCLR Remote in the Type column can be attached.
    8. Select the Safari process and hit Attach.
    9. There you go. You've just attached the Safari process on the Mac to the Visual Studio debugger.

    image  image  image

    Now. Perform whatever action on the Mac that makes you hit the breakpoint you set before, and take a moment to enjoy real-time cross-platform remote debugging.

    Screenshots of the Mac showing the webpage with the Silverlight app:

    image image

    The second picture above, has the SetDefaultView() Button highlighted as if I was holding down the mouse bottom. This is because the screenshot is taken when I hit the breakpoint you can see on the third picture of Visual Studio further above.

    One thing I noticed while using the Silverlight charts from the Mac, was the speed. When I paste the serialized string in to the textbox and click LoadData() - the Silverlight loads the string and deserializes it to some custom classes I made. On Vista it takes less than a second. On the Mac it takes about two seconds or maybe a bit more. And it is not because of network latency. Silverlight runs in the browser, which means the app is downloaded to the Mac, and when I click the buttons, all the logic handling events and doing stuff runs locally. So Silverlight is lot slower on the Mac than on Windows. Maybe this will get better when Silverlight 1.1 is officially released.

     


    kick it on DotNetKicks.com

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Add to: Facebook Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Technorati

    Recommended listening: .NET Rocks with Brad Abrams

    October 25, 2007 23:54 by MartinHN

    If you haven't heard .NET Rocks before, now is a good time to do it. In their last show, they interviewed Brad Abrams during Remix Boston where he did a keynote. So who is Brad Abrams.

    Quote from his own blog:

    Brad Abrams was a founding member of both the Common Language Runtime, and .NET Framework teams at Microsoft Corporation where he is currently the Group Program Manager for the UI Framework and Services team which is responsible for delivering the developer platform that spans both clients and web based applications as well as the common services that are available to all applications. Specific technologies owned by this team include ASP.NET and ASP.NET AJAX, parts of Silverlight, and Windows Forms.

    In the interview, they talk a lot about Silverlight, what they are trying to do and how open the technology actually is. And they talk a lot about that openness Microsoft has recently approached, and how the Silverlight technology could be adapted by a developer of any of the three major platforms. (Windows, Mac & Linux). I really like that approach, and the result is clear. Already - even though Silverlight just hit the 1.0 RTM recently, there's a huge amount of applications running live from notable companies.

    They also talk a lot about Brad Abrams' keynote at Remix Boston, where he did a demo on debugging a Silverlight 1.1 app.

    And he didn't do it the easy way! He had a Linux box with a small PHP page, hosting the Silverlight 1.1 app. That worked great. The he fired up a Mac, and hit that page from Safari. And to achieve the debugging experience of Visual Studio, he attached the VS debugger to the Safari process on the Mac, set a breakpoint in the code, and refreshed the page on the Mac, to hit the breakpoint. And there you go. A Mac hitting a breakpoint on a Vista box, and the website being hosted on a Linux box - how cool is that?

    During the show Richard Campbell said that he didn't believe it would work. I don't know - but I want to try the same thing, and se if it really works.

    Technorati Tags: , ,

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Add to: Facebook Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Technorati

    Content Aware Image Resizing

    August 30, 2007 19:22 by MartinHN

    We've all been there. You have an image which is too big to fit on the website, and it needs to be resized or cropped. Resizing can make your image look bad in quality, because of the pixels getting merged. This can make things impossible to see, and your image is damaged. Cropping on the other hand, removes the pixels completely, and sometimes you just don't want to remove things from an image - sometimes you need the entire content of the image.

    Your solution is here. I found it at Channel 8 and there is a Youtube video referenced, where you can watch the algorith in action. It even enables you to enlarge an image beyond it's original size without dropping in quality. That is so cool.

    Technorati Tags: ,

    Currently rated 4.0 by 1 people

    • Currently 4/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Add to: Facebook Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: Furl Add to: Yahoo Add to: Spurl Add to: Google Add to: Technorati

    Powered by BlogEngine.NET 1.4.0.0
    Theme by Mads Kristensen

    About the author

    Martin Høst Normark

    Senior Frontend Developer at TraceWorks.

    View Martin Høst Normark's profile on LinkedIn

    Recent comments

    Comment RSS

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

    © Copyright 2008