Getting Started with LiquidSilver
What is LiquidSilver? If you don’t know about it yet, I suggest you read the short introduction post first.
1. Getting the source code
Before anything, you need to download the LiquidSilver source code from CodePlex. Currently there’s only one change set available. I still have some more updates on my private repository that needs some clean ups and more commenting before uploading to CodePlex. But this change set is already usable.
2. Building the project
After downloading, you can open the solution in Visual Studio 2008 (SP1 is recommended). Ensure that the project maintains the references to Microsoft.SharePoint.dll and Microsoft.SharePoint.Security.dll properly. You may need to assign a strong name key to the project. After everything is in order, you can start to build the project. If the build is successful, it will produce LiquidSilver.dll in the project output folder.
3. Setting up your SharePoint site
Now, we need to set up a SharePoint site for our playground. You can create a new site or use an existing one. You can use either WSS 3.0 or MOSS 2007. In that site, create a new list called Actors. It doesn’t matter whether you want to create a list definition or just create a new custom list from SharePoint UI. In the list, define the following columns:
| Column Name | Column Type |
|---|---|
| Title | Single line of text |
| Dob | Date and Time; Date and Time Format: Date Only |
| Spouse | Lookup; Get information from: Actors; In this column: Title |
This is enough for now. While you can use the SharePoint built-in UI to add items to the list, we will do it programmatically.
4. Adding an item programmatically with SharePoint API
I totally believe you all know how to do this. I write this section only as a comparison. For this purpose, let’s fire up Visual Studio 2008, create a new console project. To be practical, ensure you have Visual Studio 2008 in the same box with the SharePoint installation.
Open the Program.cs file and write the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | using System; using Microsoft.SharePoint; namespace TestConsole { class Program { const string SiteUrl = "http://your-server-url"; const string ListName = "Actors"; static void Main(string[] args) { using (var site = new SPSite(SiteUrl)) { using (var web = site.OpenWeb()) { var list = web.Lists[ListName]; var tom = list.Items.Add(); tom["Title"] = "Tom Cruise"; tom["Dob"] = new DateTime(1962, 7, 3); tom.Update(); var katie = list.Items.Add(); katie = list.Items.Add(); katie["Title"] = "Katie Holmes"; katie["Dob"] = new DateTime(1978, 12, 18); katie["Spouse"] = new SPFieldLookupValue(tom.ID, tom.Title); katie.Update(); tom["Spouse"] = new SPFieldLookupValue(katie.ID, katie.Title); tom.Update(); } } } } } |
The code adds two items to the Actors list. It is very straight-forward and easy. Really? Well for simple column types like text, boolean, numbers, and date & time, you can simply assign the C# standard type variables to the item’s fields. But for more complex types like user & group, lookup, or URL, there can be some problems. Certain types require different methods of setting and getting the values to or from a field. Like in the code above, it requires instantiating an SPFieldLookupValue object to assign a value to a lookup field. For other complex types, it requires different objects and different techniques. Even the way to set and get the value is sometimes different. This is not intuitive and, for some people, it’s quite hard to guess how to do it without the help of Google.
Let’s see how LiquidSilver can help you with this.
5. Adding an item programmatically with LiquidSilver
You can open the same project or create a new one, it doesn’t matter. Either way, you need to add a reference to LiquidSilver.dll which you have built in step 2 earlier. Then, modify the code inside Program.cs as follow:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | using System; using LiquidSilver; using Microsoft.SharePoint; namespace TestConsole { class Program { const string SiteUrl = "http://your-server-url"; const string ListName = "Actors"; static void Main(string[] args) { using (var site = new SPSite(SiteUrl)) { using (var web = site.OpenWeb()) { var list = web.Lists[ListName]; var tom = new HgListItem(list.Items.Add()); tom.Title = "Tom Cruise"; tom.SetDate("Dob", new DateTime(1962, 7, 3)); tom.Update(); var katie = new HgListItem(list.Items.Add()); katie.Title = "Katie Holmes"; katie.SetDate("Dob", new DateTime(1978, 12, 18)); katie.SetLookup("Spouse", tom.ID, tom.Title); katie.Update(); tom.SetLookup("Spouse", katie.ID, katie.Title); tom.Update(); } } } } } |
Basically, you only need to wrap the SPListItem object instead an HgListItem object. The HgListItem object is equipped with various useful methods and properties to help you work with an SPListItem object.
As demonstrated, HgListItem provides you some setter methods that allow you to assign values into the fields of the SPListItem object it contains. With LiquidSilver, you just need to know what is the type of the field you want to use, not how to use it. And for each setter method, it will come with the getter method counterpart. For example, there are GetString(), GetDate(), and GetLookup() methods.
Currently, the getter/setter methods support the following field types, more will be added:
| Field Type | Getter Methods | Setter Methods |
|---|---|---|
| Bool | bool GetBool(Guid fieldId | HgListItem SetBool(Guid fieldId, bool value) |
| Calculated | string GetCalculated(Guid fieldId) | HgListItem SetCalculated() |
| Date and Time | DateTime GetDate(Guid fieldId) | HgListItem SetDate(Guid fieldId, DateTime value) |
| Integer | int GetInt(Guid fieldId) | HgListItem SetInt(Guid fieldId, value) |
| Lookup | SPFieldLookupValue GetLookup(Guid fieldId) | HgListItem SetLookup(Guid fieldId, SPFieldLookupValue value)
HgListItem SetLookup(Guid fieldId, int lookupId, string lookupValue) |
| User and Group | SPPrincipal GetPrincipal(Guid fieldId)
List<SPPrincipal> GetPrincipals(Guid fieldId) string GetPrincipalsAsCsv(Guid fieldId) |
HgListItem SetPrincipal(Guid fieldId, SPPrincipal principal)
HgListItem SetPrincipals(Guid fieldId, SPFieldUserValueCollection principals) HgListItem SetPrincipalsFromCsv(Guid fieldId, string principalsAsCsv) |
| Text | string GetString(Guid fieldId) | HgListItem SetString(Guid fieldId, string value) |
| Integer | SPFieldUrlValue GetUrl(Guid fieldId) | HgListITem SetUrl(Guid fieldId, string url, string description)
HgListITem SetUrl(Guid fieldId, Uri url, string description) |
All field setter/getter methods can identify the field by the field ID (GUID) or the field internal name or display name — in that order.
If you have noticed in the example also, you will see that HgListItem also exposes a property called Title, which corresponds with the Title property of the SPListItem object. In SPListItem, this property is read-only, but in HgListItem, you can also update it. There are also some other similar properties as follow:
| Property | Type | Access | Corresponding SPListItem Field |
|---|---|---|---|
| ID | int | read-only | ID |
| UniqueId | Guid | read-only | UniqueId |
| Title | string | read-write | Title |
| Author | SPUser | read-write | Author |
| Editor | SPUser | read-write | Editor |
| CreatedOn | DateTime | read-only | Created |
| ModifiedOn | DateTime | read-only | Modified |
I hope this will help you get started with LiquidSilver. Please keep an eye for future posts exploring the goodies of LiquidSilver.
Introducing LiquidSilver SharePoint Framework
This is an introductory post to LiquidSilver SharePoint Framework that I’ve been developing with my friend, Riwut Libinuko.
LiquidSilver is a SharePoint Framework that provides various classes and functions to deal with common tasks in any SharePoint development to help you work much easier, faster, more object-oriented, and more productive. LiquidSilver is compatible with WSS 3.0 and MOSS 2007.
The project is hosted in CodePlex where you can download the source code as well as report issues.
We have put a lot of our experience — in Riwut’s case, years of experience that got him an MVP award — in SharePoint development into this framework and been using it in our projects. We love it and benefit greatly from it. So, we hope you will too.
Enough with the introduction, let’s get started with LiquidSilver or visit the LiquidSilver page to look for more resources.
SharePoint Custom List Definition Recipes
If you want a tutorial on how to create a custom ist definition in SharePoint, check MSDN or Andrew Connell’s post. Here, I’ll just provide several short recipes for some scenarios.
1. How to rename the Title column in the list definition?
Often, you want to rename the Title column in your list definition. Don’t do it, because many internal SharePoint functions requires it. Instead, just change the display name of the column.
You need to do this in the list definition’s schema.xml, not in the content type definition file. In fact, don’t mention the Title column in the content type. If you do, the Title column will appear twice in your list.
Here is what you should modify in your schema.xml:
<Fields>
<Field ID="{82642EC8-EF9B-478F-ACF9-31F7D45FBC31}"
Type="Computed"
Name="LinkTitle"
DisplayName="My Own Title" />
<Field ID="{BC91A437-52E7-49E1-8C4E-4698904B2B6D}"
Type="Computed"
Name="LinkTitleNoMenu"
DisplayName="My Own Title" />
<Field ID="{FA564E0F-0C70-4AB9-B863-0177E6DDD247}"
Type="Text"
Name="Title"
DisplayName="My Own Title"
Required="TRUE" />
<!-- Other fields declaration -->
</Fields>
Keep in mind that you will need those three columns declaration, one for the plain Title data, the others for the Title with link and menu which are displayed in the standard form. You can put your own text inside the DisplayName attribute.
2. What are the required attributes in the List and ListTemplate elements?
The List element in schema.xml is similar to the ListTemplate element in the feature manifest in the sense that they both have a similar set of attributes. A lot of attributes are duplicated and it often cause confusion. Usually, I would put every attributes I needed in both elements. But this is not a good practice, since if you need to change some attributes, you have to do it for both elements. So it’s better to put only the required attributes in each element. What are they?
MSDN actually has listed the required attributes for the List and ListTemplate elements. But, at least in my case, it’s not so accurate. So here is what I found:
Required on the List element:
- BaseType
- Direction
- Name
- Url
The MSDN article suggested that this attribute is optional. But if you don’t include this, you might get the following error when creating an instance of the list:
Exception occurred. (Exception from HRESULT: 0×80020009 (DISP_E_EXCEPTION)) at Microsoft.SharePoint.Library.SPRequestInternalClass.CreateListFromFormPost(String bstrUrl, String& pbstrGuid, String& pbstrNextUrl)
at Microsoft.SharePoint.Library.SPRequest.CreateListFromFormPost(String bstrUrl, String& pbstrGuid, String& pbstrNextUrl)
Required on the ListTemplate element:
- BaseType
- DisplayName
- Name
- Type
C# 4.0 and Dynamic Programming
In Microsoft PDC2008, Anders Hejlsberg — C# lead designer and Microsoft Technical Fellow — introduces the future of C#, dubbed C# 4.0. You can watch his recorded presentation at Channel 9. The following is a brief summary on dynamic programming, one of C# 4.0 new features.
C# Evolution
- C# 1.0: Managed Code
- C# 2.0: Generics
- C# 3.0: Language Integrated Query
- C# 4.0: Dynamic Programming
Nowadays, codes can reside in any kind of form, i.e., .NET objects, JavaScript, Python, Ruby, COM. In order to use the codes written in different form, currently we have some different approaches.
For example, to call a .NET object, we will write the following:
Calculator calc = GetCalculator(); int sum = calc.Add(10, 20);
Now we try to call a .NET object too, but we don’t know which class exactly having the code:
object calc = GetCalculator(); Type calcType = calc.GetType(); object res = calcType.InvokeMember("Add", BindingFlags.InvokeMethod, null, new object[] { 10, 20 }); int sum = Convert.ToInt32(res);
While this is for calling a JavaScript object:
ScriptObject calc = GetCalculator(); object res = calc.Invoke("Add", 10, 20); int sum = Convert.ToInt32(res);
Observe that there are different procedures to call different objects. With C# 4.0 dynamic keyword, we can use this instead of all those above:
dynamic calc = GetCalculator(); int sum = calc.Add(10, 20);
The compiler will not check whether there is an “Add” method in the “calc” object. Instead, the DLR will bind the method call to the responsible object on runtime as shown in the following picture:

Anders stated that he did not have any intention to ask all developers to rewrite all their codes to be dynamic. In fact, he is a strong believer of static language strong features: statement completion, refactoring, compilation type check, and performance. But he also embraces the flexibility and productivity of dynamic languages such as Python and Ruby. And there are an increasing numbers of things that your application needs to talk to, that is not statically typed. You may need to talk to a JavaScript code, or maybe a Python or Ruby codes. The question is, should we make it painful to talk to them or make it easier?
For Anders, he wants the later. As LINQ intends to provide a unified way to access all kind of data source, dynamic in C# intends to provide a unified way to talk to all kind of codes, be it statically or dynamically typed.
SharePoint Bending: Remove “Send To” Context Menu Without Modifying Core.JS
This is becoming a pretty common requirement. Some people just don’t want the “Send To” menu appearing in the context menu of the document library. You can do it — customize the SharePoint context menu by — by simply making some modification in core.js as suggested by many.
But modifying SharePoint core files should not be done, because your modifications can be overwritten by future SharePoint updates. So here’s a little trick to remove the “Send To” context menu without modifying core.js:
- Go to the document’s view url, for example:
http://example.com/Documents/Forms/AllItems.aspx. - If it is a web part page, edit the page and add a Content Editor web part. Otherwise you need to edit that page in SharePoint Designer.
- Open the source editor (not the rich editor) for the Content Editor web part, or open the code view (not the design view) of that particular page in SharePoint Designer.
- Either inside the web part or the code view, insert the following script:
<script type="text/javascript">
AddSendSubMenu = function (m,ctx) {}
</script>
That script will redefine the AddSendSubMenu() function with a new implementation. Since the function body is empty, it simply won’t display anything, thus the “Send To” context menu is removed from the context menu.
You can do this on some pages manually, or if you want to apply this to all pages, just insert the code to your master page.