Sign in
  • Blog
  • Archive
  • About
  • Contact

Welcome to rickardnilsson.net

rickardnilsson.net is a weblog and the online home of web developer and father of three, Rickard Nilsson... More

Rickard blogs about creating software solutions using ASP.NET and agile practices.

Sites I've visited recently

  • Scott Guthrie
  • Rtur.net
  • ASP.NET Forums
  • Karstad .NET User Group
  • JetBrains ReSharper
  • Scott Hanselman
  • dnrTV!
  • MIX 2009
  • BlogEngine.Net
  • YUI Theater

Categories

  • .NET
  • ASP.NET 2.0
  • BlogEngine.NET
  • C# 2.0
  • C# 3.0
  • CSS
  • Design by Contract
  • Design Patterns
  • JavaScript
  • TDD
  • User tip

Five most recent posts

  • ReSharper User tip #2: Refactor rename namespace
  • Building a Photo Album widget for BlogEngine.NET
  • Applying stylesheets dynamically with jQuery
  • ReSharper User tip: Refactor magical strings to variable
  • Blogging with MS Word 2007

Tag cloud

  • ajax
  • blog
  • blogengine.net
  • c#
  • css
  • dbc
  • design by contract
  • dom
  • douglas crockford
  • foto
  • getweekofyear
  • gregoriancalendar
  • highlight
  • html
  • humble dialog box
  • iso 8601
  • javascript
  • jquery
  • jscript
  • julian bucknall
  • metaweblog api
  • model-view-presenter
  • mvp
  • photo album
  • picasa
  • recent posts
  • refactor
  • refactoring
  • release
  • resharper
  • rhino mocks
  • syntax
  • syntax highlighter
  • tdd
  • test coverage
  • types
  • web service
  • week
  • widget
  • word 2007
  • yahoo
  • yui

Recent comments

  • Week and strong contracts in Design by Contact (3)
    Sulumits retsambew wrote: thanks nice tips RIckard [More]
  • Syntax highlighting in BlogEngine.NET (15)
    Sulumits retsambew wrote: great coding.. thanks for sharing it.. keep it up … [More]
  • Syntax Highlighter Release 0.2 Beta (17)
    SEO wrote: Nice post.I currently in a testing phase with this… [More]
  • Syntax highlighting in BlogEngine.NET (15)
    Max Glipmax wrote: Thanks for taking the time to discuss this, I feel… [More]
  • Building a Photo Album widget for BlogEngine.NET (11)
    tukang nggame wrote: nice widget, thanks for sharing download link [More]
<< Applying stylesheets dynamically with jQuery | ReSharper User tip #2: Refactor rename namespace >>

Building a Photo Album widget for BlogEngine.NET

Thursday, 14 August 2008 01:07 by Rickard

BlogEngine.NET has a widget framework from version 1.4 which are web part like components that can be added and removed, configured and dragged around directly in the page. Simple widgets are very easy to create and plug in to your blog and there are several blog posts explaining how to do that. In this post I'm gonna go through a more advanced example featuring Web services and Ajax.

The Photo Album Widget
The Photo Album Widget

Download: PhotoAlbumWidget-0.1.zip (7,96 kb)
Unzip to ~/widget/ folder. Requires jQuery library.


First we start with some requirements for the widget we're creating.

  1. BlogEngine.NET 1.4+ Widget
  2. Show thumbnail pictures
  3. Get pictures from Picasa web album
  4. Ajax style asynchronous loading
  5. Configurable number of pictures
  6. Clickable pictures to show full size picture 
  7. Picture repository provider model
  8. Flickr repository provider
  9. Folder repository provider
  10. Configurable picture count
  11. Provider specific configuration
  12. Configurable choice of provider
  13. Full size picture pops up in Lightbox
  14. Web 2.0 style controls for scrolling
  15. Larger preview on mouse over picture

The list above is a prioritized backlog and the first version should include items 1 - 4.

Widget 

We start off with number one, a BlogEngine Widget. To create a widget we add a new folder to the /widget/ folder and we call it PhotoAlbum. Then we create two user controls, one for widget presentation and one for configuration UI. They must be named, by convention, widget.ascx and edit.ascx respectively and should derive from WidgetBase and WidgetEditBase respectively. See more on basic widgetry here by Rtur and here by Mads as well as this, that and whatnot.

That was the easy part.

Picasa web album

With the next requirement we first need to get the pictures from somewhere so we skip to the next requirement. Picasa is Google's web album and it has its own REST API as well as a .NET client library. Conveniently there is also a public feed which contains all public photos uploaded to Picasa. (You can of course use your own Picasa album, see the Data API docs for more information). All we need to do is provide a query tag/tags to limit the search or we'll get an error message. The following code retrieves a couple of photos picturing cats:

PicasaService service =
    new PicasaService("exampleCo-exampleApp-1");

PhotoQuery query = 
    new PhotoQuery("http://picasaweb.google.com/data/feed/api/all");
query.Query = "cat";
query.NumberToRetrieve = 5;
PicasaFeed feed = service.Query(query);

foreach (PicasaEntry entry in feed.Entries) {
    string firstThumbUrl = entry.Media.Thumbnails[0].Attributes["url"] as string;
    writer.Write("<img src=\"{0}\" alt=\"{1}\" />",
                 firstThumbUrl, entry.Title.Text);
}

If we drop the code above into the widget.ascx.cs we affectivally fullfills both requirements 2 and 3 so lets get on with number 4.

Ajax

Requirement number four implies the Incremental Page Display pattern where the main part of the page is shown quickly and portions of the page that takes longer to load are fetched and displayed asynchronously. To give the user feedback of the loading we place an animated gif image in the widget which is later swapped out when the real pictures arrive. To accomplish this we're using the jQuery JavaScript library which let us get away with very little code for pretty advanced stuff.

First we need to do a little refactoring since the widget needs to do an asynchronous call somewhere to get its content, i.e. the pictures to display. We're gonna go with the simplest possible solution here, just enough to satisfy the requirement. The simplest thing from the widget's point of view is to have the html containing a number of <img> elements returned from the call. Then it's very simple to insert the html into the widget using jQuery. Given that the widget contains a div with the id "photoalbum" this is all it takes:

$("#photoalbum").html(the_html_to_insert);

As it is now, the widget codebehind is rendering the requested html and this is not god. We need to move the code to some place which we can make a http request to and get the html in response. This can be done with a regular aspx page. All we need to do is to put a simple Repeater control on a page and bind it to a list of image URLs which we get from Picasa web album. So, we add a new aspx page to the /widgets/Photo Album/ folder and call it PhotoService.aspx. All we want in response is the <img> tags which should be inserted into the widget so we clear the page from html and put a single Repeater on it like this:

<asp:Repeater ID="pictureRepeater" runat="server">
    <ItemTemplate>
        <asp:Image ID="image" runat="server"
            ImageUrl="<%# Container.DataItem.ToString() %>" />
    </ItemTemplate>
</asp:Repeater>

In the codebehind we insert something like before and makes sure we bind to the Repeater control.

// Error checking is omitted for clarity
List<string> pictures = new List<string>();
PicasaService service = new PicasaService("exampleCo-testApp-1");

string picasaUri = "http://picasaweb.google.com/data/feed/api/all";
PhotoQuery query = new PhotoQuery(picasaUri);
query.Query = "cat";
query.NumberToRetrieve = 6;
PicasaFeed feed = service.Query(query);

foreach (PicasaEntry entry in feed.Entries) {
    string firstThumbUrl = entry.Media.Thumbnails[0]
                               .Attributes["url"] as string;
    pictures.Add(firstThumbUrl);
}

pictureRepeater.DataSource = pictures;
pictureRepeater.DataBind();

To test the service we point a web browser to /widgets/Photo Album/PhotoService.aspx which should show a bunch of cats! Everything looks good and all we need to do to get the pictures into the widget are two things. First we need to register the jQuery JavaScript file, either localy or a referer to the jQuery official site. Last we need to add some custom JavaScript that makes the Ajax call and puts the html at the right place.

JavaScript blocks should allways, if possible, be placed as close to the </body> tag as possible. The reason is that the browser won't continue to load the remainder of the page when it hits a JavaScript block but rather wait until it is fully loaded. This is not a problem if we're dealing with short scripts but the jQuery library is relatively large in this context so we need to put it as far down the page as possible. Our own script that does the actual work depends on jQuery, thus it must be loaded last. The problem is that we need to do this in a User control in the middle of the page. To our help to solve this we have the ClientScriptManager that every aspx page has. With the method RegisterStartupScript we get to insert arbitrary scripts just before the </form> tag (which is close enough) of the surrounding page. We make the registrations when the widget is loaded, i.e. in the LoadWidget() method.

With this final step done we have our first version of the Photo Album Widget which is ready for demo.

Problems with the solution

Before the second iteration I'd like to summarize a couple of things with version one that are not of production quality.

  1. PhotoService mimics the behavior of a Web service (kind of) but is really a simple aspx page
    - We could have done a Generic handler (ashx) instead but then we couldn't have used a Repeater
    - We could have done a custom HttpHandler but that need to go into App_Code and edit web.config which is harder to install
  2. The requirements maybe fullfilled but no one cares for a widget that only display cats!
    - We need to be able to configure the feed as well as the query.
a3988f31-ed80-4694-b4ca-85641d66c15d|1|2.0
Tags:   widget, photo album, web service, ajax, jquery, picasa
Categories:   BlogEngine.NET | JavaScript
Actions:   E-mail | Permalink | Kick it! | DZone it! | del.icio.us | Comments (11) | Comment RSSRSS comment feed

Related posts

Syntax highlighting in BlogEngine.NET BlogEngine.NET ships with an extension that automatically highlights source code in blog posts. Al...Problem with Related Posts in BlogEngine.NET 1.4 With the new release of BlogEngine.NET a new feature was added that shows the description or part ...Ny blog med BlogEngine.NET Hej! Kul att du tittar in. Jag har äntligen haft möjlighet att flytta min gamla blog fr&...

Comments

August 26. 2008 23:24

Rickard

Feel free to leave a comment if you have any feedback regarding the Photo Album widget or anything else.

Rickard

September 4. 2008 19:20

nemesis

  
excellent... but, how can I use it outside the widget area as a standard control?

nemesis

September 4. 2008 23:32

Rickard

Well, you can't at this point. My main goal with the tutorial was to show how to make a slightly more advanced widget. However, it is still a User control and you should be able to placed it where ever you want. It will still render as widget though, since it derives from WidgetBase.

Thanks for the feedback and I will add your suggestion to the feature backlog.

Rickard

September 18. 2008 10:30

David

Very usefull Rickard.

I tried to use your example but changing just one line in PhotoService.aspx.cs

string firstThumbUrl = entry.Media.Content.Attributes["url"] as string;

instead

string firstThumbUrl = entry.Media.Thumbnails[0].Attributes["url"] as string;

because I want to show a full size picture instead a thumbnail


well, I have a some problem with this because the image looks like lost but when I copy the url and paste in another internet explorer it´s work

this is my example
http://dpobla.blogdns.com

Do you know something about that?

David

September 19. 2008 09:55

Bryan Avery

Great code, but you need to include the google library

Google.GData.Photos

As Google Picasa provied an RSS feed for the photo libraries can't we just tap in to those and display the images?

Bryan Avery

January 30. 2009 23:45

Bryan Avery

This is looking really good.

Bryan Avery

February 8. 2009 20:21

Bryan Avery

Just finished of a Picture Extension for BlogEngine

www.bryanavery.co.uk/.../...r-BlogEngine-site.aspx

Bryan Avery

February 12. 2009 12:34

 Kampanye Damai Pemilu Indonesia 2009

Wow..

Thanks for you informations, that's very helpfully

Kampanye Damai Pemilu Indonesia 2009

April 2. 2009 11:02

Franchise Blog

Great article - the Internet is such a great medium and resource and I thank you for taking the time out to write, it is always a pleasure to read.

Franchise Blog

June 6. 2009 10:20

affordable SEO companies

After now i was thinking on my new website. I am undecided to my topic so i was continuing searching what topic and free design for my new website. I hope the information i got to this website are in function. Thanks for the information. Good luck.

affordable SEO companies

June 23. 2009 15:11

tukang nggame

nice widget, thanks for sharing download link

tukang nggame

Saving the comment

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



 
Copyright © 2008-2009 rickardnilsson.net