Introduction
The Collaborative Application Markup Language (better known as CAML) is an XML-based query language that helps you querying, building and customizing Web sites based on Windows SharePoint Services. The XML elements define various aspects of a WSS site.
In this first series of articles I will explain in detail how to build and execute CAML queries to retrieve list items from a SharePoint list. List items can be retrieved in several different ways: using the SharePoint object model, using the SharePoint Lists web service or even by using Powershell. Use the SharePoint object model when your code runs on the server (like f.e. when you’re developing a web part or an application page). Use the SharePoint Web Services when your code doesn’t run on the server where SharePointis installed, for example when you develop office clients or windows applications. Powershell, at the other side, can be used by administrators when they quickly need to retrieve some information. In any way the CAML query is the same.
Building the CAML
CAML is an XML-based query language. Its root element is Query. Within the Query element two other elements are possible but not required: the OrderBy element and the Where element.
The OrderBy element is the simplest one. It is used to sort the returning list items. You have to specify the field(s) on which you want to sort the items and the sort direction. The syntax looks as follows:
The Where clause is used to specify one or more filter criteria. This clause can be very simple but can end up being rather complex. In its most simple form you specify an operator, a field name for which you want to specify a criterion, and a value.
Eq Equals
Neq Not equal
Gt Greater than
Geq Greater than or equal
Lt Lower than
Leq Lower than
IsNull Is null
BeginsWith Begins with
Contains Contains
FieldsThe FieldRef element can be any field of the list on which you want to execute the CAML query. If you use the Name attribute you need to specify the internal name of the field. But you can also use the IDattribute to specify the Guid of the field.
ValueThe Valueelement specifies the value part of the criterion. The attribute Typeis optional and specifies the data type of the field you want to specify the criterion for. If omitted the data type is considered as being Text. In all other cases you have to specify the Type attribute. DateTime fields are a special case and will be described in more detail later in this article.
If the field type is a Lookup you need to specify the text value.For example you have an Employees list and the Country field is a lookup field referring to the Countries list. In that case an employee living in Belgium will have f.e. following value: #15;Belgium. If you have to query for the employees living in Belgium you will have to write your query as follows:
If you need to retrieve items from a list when developing web parts, application pages or custom field types you can best use the SPQueryobject from the SharePoint object model. This object is located in the Microsoft.SharePoint namespace of the Microsoft.SharePoint.dll located in the Global Assembly Cache.
Instantiate the object as follows:
SPQuery qry = new SPQuery();The most important property is the Query property, which needs to be set to your CAML query:
string camlquery = "
SPListItemCollection listItemsCollection = list.GetItems(qry);A small remark with the GetItems method of the SPList instance: this method returns a collection of type SPListItemCollection. It is possible that it is easier working with a DataTable. In that case you can execute the query as follows:
DataTable listItemsTable = list.GetItems(qry).GetDataTable();The query will not only return all list items that have their last name set to Smith, but also all columns of each list item. In cases you work with large lists it can be important to retrieve a subset of list items containing only the columns you need. In that case you will have to set the ViewFields property of the SPQuery object. You can do this by specifying all columns you want to see returned:
qry.ViewFields = "
The major disadvantage of the SPQuery object is that you can query only one list. If you want to query more than one list you will have to use the SPSiteDataQuery. More on this object in a later article because it earns special attention.
It is common knowledge by now but let me remind you that it’s always a good idea to use SPQuery to retrieve a subset of list items. You can loop through the list item collection to find the list items that match your needs but this will have a serious negative impact on the performance of your work.
Retrieving List Items with CAML using the SharePoint Web Services
If you are developing office clients or any other application that will not run on the server where SharePoint is installed you will need to use the SharePoint Web Services to retrieve (or update) information from SharePoint. If you want to query a list you will need to execute the GetListItems method from the Lists.asmxSharePoint web service.
Working with the SharePoint web services is different in Visual Studio 2005 then in Visual Studio 2008.
Retrieving List Items from the Lists.asmx using Visual Studio 2005First you have to reference the web service in your Visual Studio project. If you work with Visual Studio 2005 you have to add a Web Reference to theLists.asmx.
Then you have to instantiate the web service and pass the url of the SharePoint site, plus the location and name of the SharePoint web service. The SharePoint web services are all located in the ISAPI directory of the SharePoint 12 hive but are accessible from outside via the _vti_bin directory.
Initialize the Lists.asmx web service:
ListService listsWs = new ListService.Lists();listsWs.Url = siteUrl + @"/_vti_bin/lists.asmx";Then you have to set the credentials. In case you don’t need to specify a username or password you can proceed as follows:
listsWs.Credentials = System.Net.CredentialCache.DefaultCredentials;If you have to specify a user name and password:
listsWs.Credentials = new System.Net.NetworkCredential(userName, password);If you also have to specify a domain, use the other overload:
listsWs.Credentials = new System.Net.NetworkCredential(userName, password, domain);Then you are ready to call the GetListItems method, which requires the following syntax:
resultNode = _sharepointSite.ListsWSS.GetListItems(listName, viewName, queryNode, viewFieldsNode, rowLimit, queryOptionsNode, webID);Not all arguments are required. Arguments like view name, row limit and web ID are optional.
The query node argument will contain the CAML query as explained in previous sections but need to be enclosed within a
XmlDocument camlDocument = new XmlDocument();XmlNode queryNode = camlDocument.CreateElement("Query");queryNode.InnerXml = "
XmlNode viewFieldsNode = camlDocument.CreateElement("ViewFields");viewFieldsNode.InnerXml = "
XmlNode queryOptionsNode = camlDocument.CreateElement("QueryOptions");Retrieving List Items from the Lists.asmx using Visual Studio 2008But in case you are working with Visual Studio 2008 you will have to add a Service Reference to theLists.asmxweb service. If you don’t want to work asynchronously you have to uncheck the Generate Asynchronous Operations option in the Advanced dialog. When closing the dialog box Visual Studio automatically adds an app.config or web.config file. Open this file and locate the security section. The following XML is generated automatically:
ListsWS.ListsSoapClient ws = new ListsWS.ListsSoapClient();You also have to set the necessary credentials. If you can work with the default credentials you can write the following:
ws.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials; ws.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;If necessary you can also pass user name, password and domain:
ws.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("Administrator", "secret", "U2UCOURSE"); ws.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;If necessary you can set the URL to the web service dynamically:
ws.Endpoint.Address = new System.ServiceModel.EndpointAddress( "http://wss.u2ucourse.com/_vti_bin/lists.asmx");Now you are ready to call the GetListItems method of the web service. There is no difference in calling this method from within Visual Studio 2005:
XmlDocument camlDocument = new XmlDocument(); XmlNode queryNode = camlDocument.CreateElement("Query");queryNode.InnerXml = "
Query Options
Executing a query is not only about CAML. When working with the SPQuery object you can set different properties to influence the returned list items. When working with the SharePoint web services, these options are translated into CAML and are part of the QueryOptions element.
RowLimitSetting this property limits the number of rows returned in the result set.
When working with the SPQuery object:
qry.RowLimit = 10;When working with the GetListItems method of the Lists.asmx web service:
XmlNode queryOptionsNode = camlDocument.CreateElement("QueryOptions");queryOptionsNode.InnerXml = "
When working with the SPQuery object:
qry.IncludeMandatoryColumns = true;When working with the GetListItems method of the Lists.asmx web service:
XmlNode queryOptionsNode = camlDocument.CreateElement("QueryOptions");queryOptionsNode.InnerXml = "
ExpandUserFieldWhen you omit this property or set it to false, user fields will return the login name of the user.
Setting this Boolean property to true (or include it in the QueryOptions node), user fields are returned as follows:
Karine Bosch,#U2UCOURSE\karine,#karine@U2UCOURSE.COM,#,#Karine BoschThe returned value includes the login name, e-mail address, Session Initiation Protocol (SIP) address, and title, when present, which causes a user field to behave as a multilookup field. The syntax is similar to that of the previously described property.
There are some other query options to set but they will be explained in detail in the next section.
Special Types of Queries
Some special types of lists require more specialized CAML queries. In some cases it only affects the CAML but in other cases you have to set extra SPQuery properties. If you execute this query against the Lists web service it will affect another argument of the GetListItems method, i.e. the QueryOptions argument.
Building queries for working with FoldersA first variant I will explain is how you can work with folders and sub folders. A folder is a special list item on a list or document library. If you execute a standard CAML query you will end up with list items from the root folder.
If you want to query all folders and sub folders of a list or document library, you have to define extra query options. If you are working with the object model you have to set the ViewAttributes property of the SPQuery object as follows:
qry.ViewAttributes = "Scope='Recursive'";If you work with GetListItems method of the Lists.asmx SharePoint web service, you have to define an extra node with the QueryOptions element:
XmlNode queryOptionsNode = camlDocument.CreateElement("QueryOptions");queryOptionsNode.InnerXml = "
qry.Folder = list.ParentWeb.GetFolder("Folders DocLib/2008");When working with the web services you have to do the following:
XmlNode queryOptionsNode = camlDocument.CreateElement("QueryOptions");queryOptionsNode.InnerXml = "
As already said, this way the date is hard coded. If you want your query a bit more dynamic, you can always use the element Today.
You can also add or subtract a number of days from today’s date. In that case you have to add the Offset attribute to the Today element. The Offset attribute accepts a positive value for adding days and a negative value for subtracting days.
Building Queries for Calendar ListsCalendar lists also require a little more attention. A calendar list is based on the Event content type. Normal events can be retrieved with the usual CAML queries. It’s only when you start working with recurring events (events that occur once a day or twice a week or month) that you run into problems.
The Event content type defines a field named fRecurrence, which is set to 1 when a recurring event is created.
Defining a recurring event
When the Calendar view is rendered a recurring event is split into a number of event instances, one for each recurrence.
Calendar view showing event instances for recurring event
The definition of the recurrence is XML stored in another field defined by the Event content type, i.e. RecurrenceData. An example of such a definition looks as follows:
When working with the SPQuery object you need to set the ExpandRecurrences property to true. You also have to specify a date in the CalendarDate property. This date will be used to compare the recurring event instances.
Next you have to add a DateRangesOverlap element to the Where clause of the CAML query. This element is used in queries to compare the dates in a recurring event with the date specified in the CalendarDateproperty to see whether they overlap. The CAML looks as follows:
In case you need to work with the GetListItems method of the Lists.asmx web service, you translate the query options into XML:
XmlNode queryOptionsNode = camlDocument.CreateElement("QueryOptions");queryOptionsNode.InnerXml = "
This is it about retrieving List Items using CAML. Don’t hesitate to post your comments and questions below.
No comments:
Post a Comment