The SharePoint Pinterest-style Image Library

A picture is worth a thousand words.

 

In the latest version of spaspa.codeplex.com, I created a separate Knockout Template and bind the Images library (BaseTemplateID 851) to it.  Then I inserted a simple jQuery Plugin Wookmark https://github.com/GBKS/Wookmark-jQuery

The end result is that when we have pictures, they are displayed in an awesome layout.

As an added bonus, I'm calculating the thumbnail image from SharePoint, so instead of rendering:

http://spg-dev-jl/PublishingImages/wallpaper_08.jpg

image

Original: 78K

I'm rendering

http://spg-dev-jl/PublishingImages/_w/wallpaper_08_jpg.jpg

image

Thumbnail image generated by SharePoint.  Which is a far smaller file - 16k.

 

Next update, I'll try to resolve those pesky SharePoint users and get the correct user name and picture.  So we don't have Mr. Bill Gates staring back at us! ;-)

Test your C#: Generic overloaded constructors

I love languages.  Here's one for a language nut.

public class Response<T> {

    private T result;
    private string error;

    public Response(T result) { this.result = result; }
    public Response(string message) { this.error = message; }

}

 

You can use this generic class as a wrapper for returning data.

return new Response<int>(1000);

Or to return an abnormal result

return new Response<int>("Something has gone wrong");

 

Question 1

The fun part then, is what happens when you have this?

var result = new Response<string>("Is this a result or an error?");

What is result

 

Question 2


What about this:

public class Sample
{
    public static Response<T> GetSample<T>(T arg)
    {
        return new Response<T>(arg);
    }
}

and then:

var result = Sample.GetSample("Is this an error?");

What is result

SharePoint Saturday Adelaide update

 

Hope you enjoyed the session and all the wonderful sessions through out the day.

I hope I've also given you plenty of ideas on how you can mix and match a really rich set of the latest technology in your SharePoint environment. 

A summary link of all my related talks on REST, services and JavaScript technologies like jQuery and Knockout are on /rest/

A direct link to the solution that I used for the demo is at: https://static1.squarespace.com/static/5527bff2e4b0b430660b0d10/5527c30de4b030eeeef09715/5527c30ee4b030eeeef09b23/1316868647487/SPGSvcWp.zip

The PowerPoint presentation is at: https://static1.squarespace.com/static/5527bff2e4b0b430660b0d10/5527c30de4b030eeeef09715/5527c30ee4b030eeeef09b24/1335084544036/SharePoint+REST+and+jQuery5.pptx

Drop me a question if you want to ask me anything specific related to these topics and I'm more than willing to geek out!  Hope to see you guys again soon.

You can find me via

T: @johnnliu
E: john.liu at sharepointgurus.net

Or grab a business card from me throughout the day!

SharePoint Saturday Brisbane update

 

Thank you for attending my session on Building Custom REST services and consuming them with jQuery AJAX. 

I hope you enjoyed the session and survived (or even find it interesting) my 1hr rant.

But more importantly, I hope I've given you plenty of ideas on how you can integrate the set of techniques presented in your SharePoint development.

 

A summary link of all my related talks on REST, services and JavaScript technologies like jQuery and Knockout are on /rest/

 

A direct link to the solution that I used for the demo is at: https://static1.squarespace.com/static/5527bff2e4b0b430660b0d10/5527c30de4b030eeeef09715/5527c30fe4b030eeeef0a010/1316868647487/SPGSvcWp.zip

The PowerPoint presentation is at: https://static1.squarespace.com/static/5527bff2e4b0b430660b0d10/5527c30de4b030eeeef09715/5527c30fe4b030eeeef0a011/1335084544036/SharePoint+REST+and+jQuery5.pptx

 

Drop me a question if you want to ask me anything specific related to these topics and I'm more than willing to geek out!  Hope to see you guys again soon.

SharePoint, why is listdata service using strange names?

The wonders and pains of Microsoft.SharePoint.Linq.Util.GetFriendlyName

I'm doing some more work with SharePoint as a Single Page Application (spaspa.codeplex.com) and realized that when you are using the REST interface via _vti_bin/listdata.svc, the names of the list it generates are extremely strange.  That is, it doesn't map nicely to anything from the client object model.

Take for example, the out of the box Shared Documents library in a team site.

The URL is: /Shared%20Documents/

The display name is: Shared Documents

The list GUID is: {DEB93E69-7EDE-4AA0-974D-C05FCCCCE619}

But in ListData.svc,

The REST URL is: /_vti_bin/listdata.svc/SharedDocuments/

If you try to use any of the following, you'd get an error:

  • /_vti_bin/listdata.svc/Shared%20Documents/
  • /_vti_bin/listdata.svc/shareddocuments/
  • /_vti_bin/listdata.svc/{DEB93E69-7EDE-4AA0-974D-C05FCCCCE619}/

 

If you are coding to specific lists, this is probably not a big issue, since you'd target the list you want directly.  But for a project like SPASPA, where I am making no assumptions about what the names of the list actually looks like - this is very strange, and very difficult to work around.

Furthermore, if you are trying to mix and match REST service API with Client Object Model - you can't map them.  They have different names.  The client object model does not return SharedDocuments anywhere.

At a glance, you think - oh it's no big deal, just take the URL and strip out the spaces.

Ah ha, that's where you'd fail terribly.

It's almost like when Microsoft implemented the LINQ interface, they decided to make up their own names - and there's some sort of pattern:

  • If you have a lowercase list URL at: /doc/
  • The listdata.svc URL will be: /_vti_bin/listdata.svc/Doc/

Yep, magically capitalized.

  • And if you go crazy and create a list URL at: /my%20test%20lisT/
  • Then rename the title to: my test lisTT
  • Guess what's the listdata.svc end point?  /_vti_bin/listdata.svc/MyTestLisTT/

So, not just magically capitalized, camel-cased too, and it seem to be generated from the Title, disregarding the URL.  Crazy.

And you say oh that's easy, just split by spaces and turn it into CamelCase.

  • Enter foreign characters: My Test ïist  (that's a lowercase i with tréma: ALT+139)
  • Listdata.svc says: /_vti_bin/listdata.svc/MyTestÏist/  (capitalized: ALT+0207)

 

At some point, you decided that the only way forward is to read the listdata.svc code.

Here's the gem:

Microsoft.SharePoint.Linq.Util.GetFriendlyName

 

// Microsoft.SharePoint.Linq.Util
internal static string GetFriendlyName(string name)
{
    string[] array = Regex.Split(name, "[^\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}\\p{Mn}\\p{Mc}\\p{Nd}\\p{Pc}\\p{Cf}]", RegexOptions.Compiled);
    for (int i = 0; i < array.Length; i++)
    {
        if (!string.IsNullOrEmpty(array[i]) && char.IsLower(array[i], 0))
        {
            array[i] = char.ToUpper(array[i][0], CultureInfo.InvariantCulture) + ((array[i].Length > 0) ? array[i].Substring(1) : string.Empty);
        }
    }
    name = string.Join(string.Empty, array);
    if (string.IsNullOrEmpty(name))
    {
        throw new InvalidOperationException(Resources.GetString("CannotConvertNameToValidIdentifier", new object[]
        {
            name
        }));
    }
    if (Regex.IsMatch(name[0].ToString(), "[^\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}\\p{Nl}]", RegexOptions.Compiled))
    {
        name = "_" + name;
    }
    if (name.Length > 128)
    {
        name = name.Substring(0, 128);
    }
    return name;
}

 

Why you should always go to the source

 

There are some surprising bits in here, for example:

  • If your Title starts with a number, the function prepends an underscore.
    • Title: 1My Test ïist
    • REST: /_vti_bin/listdata.svc/_1MyTestÏist/
  • And if it exceeds 128 characters it is truncated.  I think this one is very unlikely, but may be people do go crazy with their list title.

 

Food for thought

A consequence of this kind of renaming, is that now there's a new problem.

Take two lists:

  • List 1 title: shared documents
  • List 2 title: SharedDocuments

The listdata service gives you:

  • /_vti_bin/listdata.svc/SharedDocuments/
  • /_vti_bin/listdata.svc/SharedDocuments0/

 

Which is what list?  Who knows!