Download FluentSP 1.0 from Codeplex.com
Once you are doing a lot of SharePoint programming you know you often have to write lengthy pieces of code to implement simple tasks like querying SharePoint lists. Nowadays you can read a lot of fluent APIs or fluent interface. For instance, jQuery, a JavaScript library that had successfully introduced a fluent API to handle the hierarchical structure of the HTML documents.
Today, I want to introduce a small library I have developed, FluentSP, a modern fluent interface around the classic SharePoint 2010 API. By using FluentSP instead of the classic SharePoint API, you will be able to chain methods and act on sets of items of the underlying SharePoint objects.
What is a fluent API?
Checkout this CodeProject article A Look at Fluent APIs and the Wikipedia article Fluent interface.
To start into the fluent API you call the Use() method on SPSite, SPWeb, SPWebCollection or SPListCollection. The Use() method is implemented as an extension method that will return the entry facade object (see facade table below). Another entry point to the fluent API is the static class SP with its static methods CurrentSite, CurrentWeb, CurrentLists or RootWebLists.
1 | SPContext.Current.Site.Use()... |
Using the entry facade instance you can start chaining the available facade methods as follows:
1 | SP.CurrentSite().Web( "Home" ).List( "Tasks" ).Items().ForEach(i => |
Each facade object is actually wrapping an underlying data item, for instance the SPSiteFacade class is the fluent wrapper of the SPSite class. Depending on what kind of facade methods you are calling the method is returning either the current facade instance (e.g., ForEach() or Where()) or the method is returning a new child facade object (e.g. Items()). During the process of chaining methods in such a way you will build up a tree or hierarchy of facade instances. In order to step back to the parent or previous facade instance you need to call the End() method:
FluentSP is currently missing a number of possible useful methods, but you can easily extend the FluentSP API with custom facade classes and extension methods, see below and source code for implementation examples.
Samples
1 | SPSite site = SPContext.Current.Site; |
6 | site.Use().RootWeb().Lists().Where(l => l.Title.StartsWith( "T" )).ForEach(l => Console.WriteLine(l.Title)); |
9 | site.Use().RootWeb().Lists( "ts$" ).ForEach(l => Console.WriteLine(l.Title)).Count( out c); |
12 | site.Use().RootWeb().Lists().Where(l => l.Title.StartsWith( "T" )).OrderBy(l => l.Title).ForEach(l => Console.WriteLine(l.Title)); |
18 |
.Where(l => l.Title.StartsWith( "T" )) |
19 |
.OrderByDescending(l => l.Title) |
20 |
.ForEach(l => Console.WriteLine(l.Title)); |
29 |
.Do(w => Console.WriteLine( "Deleting all members..." )) |
33 |
.Do(w => Console.WriteLine( "Adding all members..." )) |
34 |
.AddItems(7, (i, c) => i[ "Title" ] = "Member " + c) |
37 |
.TakeUntil(i => (( string )i[ "Title" ]).EndsWith( "6" )) |
38 |
.ForEach(i => Console.WriteLine(i[ "Title" ])); |
47 |
.ThatAreCreatedBy( "Unknown User" ) |
48 |
.IfAny(f => f.ForEach(l => Console.WriteLine(l.Title))) |
49 |
.IfAny(l => l.Title.StartsWith( "M" ), f => Console.WriteLine( "Lists found that starts with M*" )) |
50 |
.IfEmpty(f => Console.WriteLine( "No lists found for user" )) |
52 |
.Do(w => Console.WriteLine( "---" )) |
54 |
.ThatAreCreatedBy( "System Account" ) |
55 |
.IfAny(f => f.ForEach(l => Console.WriteLine(l.Title))); |
59 | var items = new List<SPListItem>(); |
62 | site.Use().RootWeb().List( "Members" ).Items().Skip(2).TakeUntil(i => i.Title.EndsWith( "5" )).ForEach(i => { items.Add(i); Console.WriteLine(i.Title); }); |
70 |
.TakeWhile(i => i.Title.StartsWith( "Member" )) |
71 |
.ForEach(i => { items.Add(i); Console.WriteLine(i.Title); }) |
74 |
.Where(i => i.Title == "XYZ" ) |
75 |
.ForEach(i => { items.Add(i); Console.WriteLine(i.Title); }); |
85 |
for ( int c = 1; c <= 5; c++) |
86 |
f.AddItem(i => i[ "Title" ] = "Standard Member #" + c); |
88 |
.AddItem(i => i[ "Title" ] = "Premium Member" ) |
90 |
.OrderBy(i => i.Title) |
91 |
.ForEach(i => Console.WriteLine(i[ "Title" ])); |
Extensibility Samples
5 |
.ThatAreCreatedBy( "System Account" , "jbaurle" ) |
6 |
.Count(c => Console.WriteLine( "Lists found: {0}" , c)) |
7 |
.ForEach(l => Console.WriteLine(l.Title)); |
10 | site.WebApplication.Use() |
12 |
.ForEach(i => Console.WriteLine(i.Url)); |
15 | site.WebApplication.Use().WithFirstSite().DoSomething(); |
16 | site.Use<SPSiteFacadeAlternate<BaseFacade>>().DoSomething(); |
The custom method ThatAreCreatedBy which is used in the first query of the extensibility samples is implemented as follows:
1 | static class Extensions |
3 |
public static SPListCollectionFacade<TParentFacade> ThatAreCreatedBy<TParentFacade>( this SPListCollectionFacade<TParentFacade> facade, params string [] names) |
4 |
where TParentFacade : BaseFacade |
12 |
facade.Set(facade.GetCollection().Where(i => names.Contains(i.Author.Name))); |
14 |
return facade.GetCurrentFacade(); |
For more samples and details check out the source code you can download from Codeplex.
Built-In Facades and Methods
See Codeplex