SharePoint Blogs / SharePoint University
SharePoint Blogs and SharePoint University - all in one place!
Need SharePoint Training? Attend a SharePoint Bootcamp!

Please delete cookies related to sharepointblogs.com and sharepointu.com to resolve login issues!

Building A Dynamic CAML Query

 

I started with creating a string builder object


StringBuilder sb = new StringBuilder();


Next I created a string array to hold the clauses I would eventually turn into my CAML values to test for.


StringCollection andClauses = new StringCollection();


Then, I checked the values of the controls by casting to the type which matched those on the page.  I used a switch statement to check the ID of the control.  For simplicity I have included only the <And> clauses and a couple of controls.  You can extend these to include more using a similar method.


switch (ctl.ID)

{

case "field1":

         if(((TextBox)ctl).Text != null && ((TextBox)ctl).Text != "")

         {

             andClauses.Add("<Eq><FieldRef Name=’field1’/><Value Type='Text'>" + ((TextBox)ctl).Text + "</Value></Eq>");

         }

         break;

case "field2":

         if(((DropDownList)ctl).SelectedValue != null && ((DropDownList)ctl).SelectedValue != "")

         {

             andClauses.Add("<Eq><FieldRef Name=’field2’/><Value Type='Choice'>" + ((DropDownList)ctl).SelectedValue + "</Value></Eq>");

         }

         break;

case "field3":

         if(((Microsoft.SharePoint.WebControls.DateTimeControl)ctl).IsDateEmpty == false)

         {

             andClauses.Add("<Geq><FieldRef Name=’field3’/><Value Type='DateTime'>" + Convert.ToDateTime 
             (((Microsoft.SharePoint.WebControls.DateTimeControl)ctl).SelectedDate).ToShortDateString() + "</Value></Geq>");

         }

         break;


Notice the casting for the SharePoint controls.  In order to get to the value that I need, and to trim the value and remove the time from the  DateTimeControl, I have converted the value using the Convert.ToDateTime() method.
 

After looping through the controls and checking for a value posted, it’s time to now loop through the values and build the CAML string.  It is important to note here that a check should be made validating any strings and check for the count of the items.  If there is a count of -1 then the loop will produce a wrong output.


Begin by appending the ‘Where’ clause to the string builder.  If the item is 1, we do not need to add any ‘And’ clauses.


sb = sb.Append("<Where>");

                                                //only 1 item

                                                if(andClauses.Count == 1)

                                                {

                                                                sb = sb.Append(andClauses[0].ToString());

                                                }


When the count is 2, we need to add one ‘And’ clause and add both item to be searched for.


                                                //two items

                                                else if(andClauses.Count == 2)

                                                {

                                                                sb = sb.Append("<And>" + andClauses[0].ToString() + andClauses[1].ToString() + "</And>");

                                                }


When the item count is greater than 2, we will add the ‘And’ clauses based on the count – 1.


                                                else if(andClauses.Count > 2)

                                                {

                                                                for(int i = andClauses.Count - 1; i > 0; i--)

                                                                {

                                                                                sb = sb.Append("<And>");

                                                                }


After adding the proper number of clauses we will add the first two items and close the first ‘And’ clause off.  Then, as we loop through the remaining items, we add another ‘And’ clause after each iteration and close then set.  If you were to add ‘Or’ clauses, you could do the same.


                                                               

                                                                sb = sb.Append(andClauses[0].ToString() + andClauses[1].ToString() + "</And>");

                                                                for(int j = 2; j < andClauses.Count; j++)

                                                                {

                                                                                sb = sb.Append(andClauses[j].ToString() + "</And>");

                                                                }

                                                }


Finally we close the entire set off by adding the closing ‘Where’ clause.


                                                sb = sb.Append("</Where>");


What you should have is a structure that is properly built to issue the query against the list.  As mentioned before, this will work for any number of items and is not limited to the ‘And’ element.  When building the array you can add additional checks, such as a comparison of ‘Or’, whereby you can test for additional parameters passed into the above loops and build an even more complex structure.


 


Posted 09-05-2007 9:59 AM by Robert J Wheeler

Comments

Robert J Wheeler wrote Dynamic CAML Query
on 09-04-2007 6:14 PM

Occasionally the need arises to build dynamic CAML queries in order to get items from a SharePoint list

Mike wrote re: Building A Dynamic CAML Query
on 02-08-2008 6:54 PM

Check these classes out:

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.SharePoint;

using System.Data;

using System.Xml;

using System.IO;

using Microsoft.SharePoint.Utilities;

using System.Collections.Specialized;

namespace Staff

{

   public enum CamlConjunction

   {

       And, Or

   }

   public enum CamlOperator

   {

       Neq, Gt, Lt, Eq, DateRangesOverlap, Geq, Leq, Contains, BeginsWith, IsNotNull, IsNull

   }

   public interface ICaml

   {

       string Render();

   }

   public class ValueComparison : ICaml

   {

       ICaml FirstValue;

       ICaml SecondValue;

       CamlConjunction opera;

       public ValueComparison(ICaml firstValue, ICaml secondValue, CamlConjunction conjunction)

       {

           FirstValue = firstValue;

           SecondValue = secondValue;

           this.opera = conjunction;

       }

       #region ICaml Members

       public string Render()

       {

           StringBuilder sb = new StringBuilder("<");

           sb.Append(opera.ToString());

           sb.Append(">");

           sb.Append(FirstValue.Render());

           sb.Append(SecondValue.Render());

           sb.Append("</");

           sb.Append(opera.ToString());

           sb.Append(">");

           return sb.ToString();

       }

       #endregion

   }

   public class FieldRefValue : ICaml

   {

       CamlOperator opera;

       string fieldName; FieldType fieldType; string value;

       public FieldRefValue(string fieldName, FieldType fieldType, string value, CamlOperator opera)

       {

           this.fieldName = fieldName;

           this.fieldType = fieldType;

           this.value = value;

           this.opera = opera;

       }

       #region ICaml Members

       public string Render()

       {

           StringBuilder sb = new StringBuilder("<");

           sb.Append(opera.ToString());

           sb.Append("><FieldRef Name='");

           sb.Append(fieldName);

           sb.Append("' /><Value Type='");

           sb.Append(fieldType.ToString());

           sb.Append("' >");

           sb.Append(value);

           sb.Append("</Value>");

           sb.Append("</");

           sb.Append(opera.ToString());

           sb.Append(">");

           return sb.ToString();

       }

       #endregion

   }

   public enum FieldType

   {

       Text, Lookup, Number, DateTime, User

   }

 internal static class Util

   {

     internal static string DispFormUrl(SPList list)

     {

         SPWeb web = list.ParentWeb;

         string url = list.DefaultViewUrl;

         string siteUrl = web.Site.Url;

         url = url.Remove(url.LastIndexOf("/") + 1);

         url += "DispForm.aspx?ID=";

         if (web.Site.ServerRelativeUrl != "/")

             url = url.Remove(url.IndexOf(web.Site.ServerRelativeUrl), web.Site.ServerRelativeUrl.Length);

         if (siteUrl.EndsWith("/"))

             siteUrl = siteUrl.Remove(siteUrl.LastIndexOf("/"));

         return  web.Site.Url + url;

     }

     internal static string CombineUrls(string webUrl, string url)

     {

         string ret = webUrl.Trim();

         if (!ret.EndsWith("/"))

             ret += "/";

         return ret + url;

     }

     internal static SPQuery CreateQuery(ICaml caml)

     {

       SPQuery ret = new SPQuery();

         ret.Query = "<Where>" + caml.Render() + "</Where>";

         return ret;

     }

     internal static SPQuery CreateQuery(ICaml caml, string[] ViewFieldNames)

     {

         SPQuery ret = new SPQuery();

         ret.Query = "<Where>" + caml.Render() + "</Where>";

         ret.ViewFields = ViewFields(ViewFieldNames);

         return ret;

     }

     internal static SPQuery CreateQuery(string[] internalFieldNames)

     {

         SPQuery ret = new SPQuery();

         ret.ViewFields = ViewFields(internalFieldNames);

         return ret;

     }

     internal static void Log(Guid siteGuid, Guid webGuid, Exception ex, string title)

     {

         Log(siteGuid, webGuid, title, ex.Message, ex.Source, ex.StackTrace, "Exception");

     }

     internal static void Log(Guid siteGuid, Guid webGuid, string title, string message, string source, string stackTrace, string logType)

     {

         try

         {

             using (SPSite site = new SPSite(siteGuid))

             using (SPWeb web = site.OpenWeb(webGuid))

             {

                 SPList logList = web.Lists["NewsletterLog"];

                 SPListItem logItem = logList.Items.Add();

                 logItem["Title"] = title;

                 logItem["Message"] = message;

                 logItem["Source"] = source;

                 logItem["StackTrace"] = stackTrace;

                 logItem["LogType"] = logType;

                 logItem.Update();

             }

         }

         catch { }

     }

       internal static string FormatValue(string rawValue)

       {

           string val = rawValue;

           if (val.Contains(";#"))

           {

               try

               {

                   val = val.Substring(val.IndexOf(";#") + 2);

               }

               catch { }

           }

           return val;

       }

       internal static string CreateQuery(string fieldName, FieldType fieldType, string value)

       {

           return "<Where><Eq><FieldRef Name='" + fieldName + "' /><Value Type='" + fieldType.ToString() + "' >" + value + "</Value></Eq></Where>";

       }

       internal static string CreateQuery(string fieldName, string value)

       {

           // SPQuery q = new SPQuery();

           return "<Where><Eq><FieldRef Name='" + fieldName + "' /><Value Type='Text' >" + value + "</Value></Eq></Where>";

       }

       internal static string ViewFields(string[] internalFieldNames)

       {

           if (internalFieldNames.Length > 0)

           {

               StringBuilder ret = new StringBuilder();

               foreach (string field in internalFieldNames)

                   ret.Append("<FieldRef Name='" + field + "' />");

               return ret.ToString();

           }

           else

               return string.Empty;

       }

     internal static string ViewFields(StringCollection internalFieldNames)

     {

         if (internalFieldNames.Count > 0)

         {

             StringBuilder ret = new StringBuilder();

             foreach (string field in internalFieldNames)

                 ret.Append("<FieldRef Name='" + field + "' />");

             return ret.ToString();

         }

         else

             return string.Empty;

     }

     internal static bool GetFieldValueBool(SPListItem item, string fieldName)

     {

         bool res = false;

         try

         {

        res =     bool.Parse(item[fieldName].ToString());

         }

         catch { }

         return res;

     }

     internal static string GetFieldValue(SPListItem item, string fieldName)

     {

         string res = string.Empty;

         try

         {

          res =   FormatValue(item[fieldName].ToString());

         }

         catch { }

         return res;

     }

   }

}

SharePoint tips and tricks - 20 Feb 08 « Patrick’s Bytes wrote SharePoint tips and tricks - 20 Feb 08 &laquo; Patrick&#8217;s Bytes
on 02-19-2008 11:17 AM

Pingback from  SharePoint tips and tricks - 20 Feb 08 &laquo; Patrick&#8217;s Bytes

Dustin Frenton wrote re: Building A Dynamic CAML Query
on 03-05-2008 2:44 PM

I like the Staff Classes!

I've been looking them over quite a bit.

Were these custom or provided from somewhere?

Mike wrote re: Building A Dynamic CAML Query
on 04-11-2008 10:18 AM

I wrote them a while back.

yhyuiyui wrote re: Building A Dynamic CAML Query
on 05-09-2008 5:21 AM

yiyuiyiyui

sondergaard wrote re: Building A Dynamic CAML Query
on 06-30-2008 3:59 AM

Great stuff!

Heads-up: Getting more conditions in a query is a bit tedious. Here's a good explanation:

sharepointsharpener.wordpress.com/.../several-ands-in-a-caml-query

vikpri wrote re: Building A Dynamic CAML Query
on 06-29-2009 4:09 PM

great post!..thanks

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Need SharePoint Training? Attend a SharePoint Bootcamp!
Posts (c) their respective authors. Everything else (c) 2009 SharePoint Experts, Inc.