SharePoint 2010 Picture Library and the Client Object Model

by Luke 4. August 2010 17:18

The goal of a recent project was to provide a way for a non-technical person to be able to add images and metadata to an ASP.NET page without the intervention of a developer.  I’m using SharePoint Foundation 2010 as the “user-friendly” interface where anyone with the right permissions can upload an image and add some metadata. And accessing the Picture Library using the new SharePoint 2010 Client Object Model (ClientOM).

I first started by writing a simple .aspx page to retrieve the images from SharePoint. In order for this to work I had to enable anonymous access to the document library. I used the MSDN examples as a starting point. In order for the below to work, you will need to add a reference to Microsoft.SharePoint.Client.dll and the Microsoft.SharePoint.Client.Runtime.dll. Below is what I used to retrieve the necessary list item collection. Ignore the parameters  in the CAML query, I’ll explain those last:

using (ClientContext clientContext = new ClientContext(url + "/sites/siteName/"))
{
      // gets the credentials of the web application
      clientContext.Credentials = System.Net.CredentialCache.DefaultCredentials;

      List oList = clientContext.Web.Lists.GetByTitle("listTitle");
      StringBuilder query = new StringBuilder();
      query.Append("<View>")
           .Append("<Query>")
           .Append("  <Where>")
           .Append("  </Where>")
           .Append("  <OrderBy>")
           .Append("    <FieldRef Name='" + OrderColumn
                   + "' Ascending='" + Ascending.ToString() + "' />")
           .Append("  </OrderBy>")
           .Append("</Query>")
           .Append("<RowLimit>" + RowLimit)
           .Append("</RowLimit>")
           .Append("</View>");
      CamlQuery camlQuery = new CamlQuery();
      camlQuery.ViewXml = query.ToString();

      Microsoft.SharePoint.Client.ListItemCollection items =
        oList.GetItems(camlQuery);

      // load server data and required columns
      clientContext.Load(
        items,
        listItems => listItems.Include(
          item => item.File,
          item => item.Id,
          item => item["Title"],
          item => item["Description"],
          item => item["ImageCreateDate"],
          item => item["votes"]));

      clientContext.ExecuteQuery();
}

 

The trick to making this code efficient is to only request the columns you need data from. I have used the .Include() statement to only retrieve the necessary columns.

Once I had my ListItemCollection, it was easy to iterate the items in the collection and write some HTML out onto the page.  The foreach takes advantage of SharePoint’s auto-generated thumbnails and displays them on the page. The full sized image is accessed via JavaScript using a LightBox type presentation.

In my first attempt I was “guessing” as to how big the thumbnails should be. But a co-worker pointed out to me SharePoint auto-generated its own thumbnails! So, after doing some simple research I determined that every time an image was uploaded to a picture library it used a consistent algorithm to generate the thumbnail. By adding a ‘/_t/’ to the URL then replacing the last . (period) with an _ (underscore) and appending “.jpg” to the end of the image URL, I could grab the auto-generated thumbnails, wicked cool!

// iterate each list item and generate HTML
foreach (Microsoft.SharePoint.Client.ListItem listItem in items)
{
  // images accessed via SP Library, library must allow anonymous read on items
  string imageUrl = url + listItem.File.ServerRelativeUrl;
  string thumbUrl = imageUrl.Substring(0, imageUrl.LastIndexOf('/'));
  thumbUrl = thumbUrl + "/_t/" + listItem.File.Name.Replace('.', '_') + ".jpg";
  DateTime taken = (listItem["ImageCreateDate"]) != null ?
     DateTime.Parse(listItem["ImageCreateDate"].ToString()) : DateTime.Now;

  // sanatize data from SharePoint
  string title = (listItem["Title"] != null) ? listItem["Title"].ToString() : "No Title";
  string description = (listItem["Description"] != null) ? listItem["Description"].ToString() : "";
  int itemId = listItem.Id;

  StringBuilder sb = new StringBuilder();
  sb.Append("<div class='picItem'>");
  sb.Append("  <div class='picItemImage'>");
  sb.Append("    <a title='" + description + "' href='" + imageUrl + "' rel='lightbox[" + ThumbnailGroup + "]' />");
  sb.Append("      <img src='" + thumbUrl + "' alt='" + title + "' />");
  sb.Append("    </a>");
  sb.Append("  </div>");
  sb.Append("  <p>" + taken.ToShortDateString() + " - " + title + " </p>");
  sb.Append("</div>");

  imagePane.Controls.Add(new LiteralControl(sb.ToString()));
}

The last piece of functionality I added to the project was wrapping everything up into a user control and adding Properties to the user control. I used the properties in two places: 1. Parameters to be passed into the CAML query to change the sort order, and sort column values of the returned ListItemCollection and 2. as configurable thumbnail group names so if the control is re-used on the page the images can be grouped together or separated.

public int RowLimit { get; set; }
public string OrderColumn { get; set; }
public bool Ascending { get; set; }
public string ThumbnailGroup { get; set; }

To keep things simple, all my code executes in the Page_Load() method. And, because I have the ListItem’s ID, I can manipulate the SharePoint list item. But that is for another post.

Let me know what you think? Any improvements or suggestions? For instance, how can I eliminate the need for anonymous access on the Picture Library and just display the images from memory?

Tags: , ,

ClientOM | SharePoint 2010

Comments

9/1/2010 3:50:00 AM #

Hi that's interesing - what's the business process that the non-technical person is following?  Ie.  why do they want to add pictures and text to a page?  I ask because I wonder what the reason for not using the Content Editor Web Part is?

Thanks for the great post!
Bruce

Bruce Canada |

11/19/2011 6:54:45 PM #

Nice blog, thanks for your effort in writing your posts Smile

John Davis United States |

11/19/2011 7:16:06 PM #

Great blog, thanks for your time in writing your posts Smile

Alrick United States |

11/21/2011 8:44:56 AM #

What's your twitter account name for following Smile

red japanese maple bonsai for sale United States |

Comments are closed

About Luke

C# .NET developer who really likes kettle style potato chips. Current favorite is Cape Code potato chips with a Henry Weinhards root beer on the side, mmmm delicious

 
 
The views and opinions on this blog site are my own and are not that of my employer.