CAML query for custom content type - sharepoint-2010

Am looking for the same target mentioned in Daivd Hill post, but still can not get the custom content type my query is like;
string dateString = (DateTime.Now.Add(new TimeSpan(-5, 0, 0, 0, 0))).ToString("yyyy-MM-ddThh:mm:ssZ");
string q= String.Format("Where And"+"Eq FieldRef Name='ContentTypeId'/" + "Value Type='Text'0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D08/Value /Eq"+
"Eq FieldRef Name='Created'/" +
"Value Type='DateTime'{0} /Value /Eq ", dateString+ " /And /Where");
SPSiteDataQuery query = new SPSiteDataQuery();
query.Query= q;
After that what should I do -> where should I execute the query against , as am trying to get against the content type , most of the examples I found was about built-in lists like task announcement..etc
in the query am trying to get the specific custom content type based on its ID that is created for ex 5 days ago
Thanks if u have any idea for help, or can u give the example of what ur solution look like thanks Azo

Something like this worked well for me, but I was querying the list.
string dateInCorrectFormat = SPUtility.CreateISO8601DateTimeFromSystemDateTimeDateTime.Now.AddDays(-5));
SPQuery query = new SPQuery();
//Query below
query.Query = String.Format( .... , dateInCorrectFormat);
SPListItemCollection items = list.GetItems(query);
<Where>
<And>
<BeginsWith>
<FieldRef Name='ContentTypeId' />
<Value Type='ContentTypeId'>0x0100XCustomContentypeIdHereX</Value>
</BeginsWith>
<Lt>
<FieldRef Name='Created'/>
<Value Type='DateTime' IncludeTimeValue='TRUE'>{0}</Value>
</Lt>
</And>
</Where>
Hope this helps.

Related

Sharepoint CAML Fliter

I have a SharePoint page which shows new employees from an employee list. I uses the start date of the employee and displays them for 30 days. We have outsourced 2 departments and managers do not want to see them as new employees since they are from a third party firm. Below is the code I tried but can not get to work. I have moved the 'And' up to include all three filter and I get an error '(soap:ServerException of t.SharePoint.SoapServer.SoapServerException' was thrown. Cannot complete this action. Please try again.0x80004005)'.
I move the 'And' near the 'Neq' and they get ignored. I am trying to keep the 30 days for start date and exclude the two departments.
`<Query>
<OrderBy>
<FieldRef Name="Full_x0020_Name"/>
</OrderBy>
<Where>
<And>
<Geq>
<FieldRef Name="StartDate"/>
<Value Type="DateTime">
<Today OffsetDays="-30"/>
</Value>
</Geq>
<Neq>
<FieldRef Name="Department"/>
<Value Type="Text">G4S Security</Value>
</Neq>
<Neq>
<FieldRef Name="Department"/>
<Value Type="Text">Budd Group</Value>
</Neq>
</And>
</Where>
</Query>`
I found a solution, there can be only two within an And. This is the code I changed below.
'<Where>
<And>
<And>
<Geq>
<FieldRef Name="StartDate"/>
<Value Type="DateTime">
<Today OffsetDays="-30"/>
</Value>
</Geq>
<Neq>
<FieldRef Name="Department"/>
<Value Type="Text">G4S Security</Value>
</Neq>
</And>
<Neq>
<FieldRef Name="Department"/>
<Value Type="Text">Budd Group</Value>
</Neq>
</And>
</Where>'
https://msdn.microsoft.com/en-us/library/office/ms196939(v=office.14).aspx
This element can be nested inside other And and Or elements. The server supports unlimited complicated queries. However, any given And element can have only two conjuncts; that is, only two child elements. If you need to conjoin three or more conditions, you must nest the And elements [...]
<Where>
<And>
<And>
<Geq>
<FieldRef Name="StartDate"/>
<Value Type="DateTime">
<Today OffsetDays="-30"/>
</Value>
</Geq>
<Neq>
<FieldRef Name="Department"/>
<Value Type="Text">G4S Security</Value>
</Neq>
</And>
<Neq>
<FieldRef Name="Department"/>
<Value Type="Text">Budd Group</Value>
</Neq>
</And>
</Where>
There is also the issue of the query method itself.
If you are using the method "query" in the "list" class, then you cannot use the <Query></Query> tags in your CAML. The reason is the method already wraps your query with this tag automatically and adding it breaks the query.
See my code for example:
Private Function GenerateCamlForCurrentUserMessages(list As SPList, isActiveOnly As Boolean) As SPQuery
Dim qResult As SPQuery
Dim sCaml As String = ""
Dim web As SPWeb = SPContext.Current.Web
If isActiveOnly Then
sCaml = "<Where><And><Eq><FieldRef Name='Author' /><Value Type='User'>" & web.CurrentUser.Name.ToString() & "</Value></Eq><Eq><FieldRef Name='IsActive' /><Value Type='Boolean'>1</Value></Eq></And></Where>"
Else
sCaml = "<Where><Eq><FieldRef Name='Author' /><Value Type='User'>" & web.CurrentUser.Name.ToString() & "</Value></Eq></Where>"
End If
qResult = New SPQuery()
'sCaml = sCaml & list.DefaultView.Query
qResult.Query = sCaml
Return qResult
End Function

How to get XML elements between specific nodes with LINQ

I'm trying to process some XML with LINQ (vb.net) to return all rows between two specific rows:
XML:
<ss:Table>
<ss:Row ss:FirstRow="true">...</ss:Row>
<ss:Row>1</ss:Row>
<ss:Row>2</ss:Row>
<ss:Row>3</ss:Row>
<ss:Row ss:LastRow="true">...</ss:Row>
</ss:Table>
I can grab the starting row using the following:
Dim Rows = From item In dg...<Table>...<Row> Select item Where item.#ss:FirstRow = "true"
But I bet there is a LINQ elegant way of getting rows with (1,2,3). Obviously I can't find it or I wouldn't be asking here. Thanks!
I think you are after the two functions ElementsAfterSelf and TakeWhile to do the trick. Apologies that my answer is in C#.
var xml = #"
<Table>
<Row FirstRow='true'>bob</Row>
<Row>1</Row>
<Row>2</Row>
<Row>3</Row>
<Row LastRow='true'>bob</Row>
<Row FirstRow='true'>mary</Row>
<Row>4</Row>
<Row>5</Row>
<Row>6</Row>
<Row LastRow='true'>mary</Row>
<Row FirstRow='true'>jane</Row>
<Row>7</Row>
<Row>8</Row>
<Row>9</Row>
<Row LastRow='true'>jane</Row>
</Table>";
var doc = XDocument.Parse(xml);
var rows = (from row in doc.Root.Elements("Row")
where row.Attribute("FirstRow") != null
select new
{
Name = row.Value,
Values = row.ElementsAfterSelf().TakeWhile(n => n.Attribute("LastRow") == null).ToList()
}).ToList();
rows.Dump();
I used LinqPad to put together the answer hence the Dump method call at the end to see the output of the operation.

CAML Query using "Membership Type='CurrentUserGroups'" returns no results

I have the following CAML query to programmatically filter a list:
<Query>
<Where>
<And>
<Geq><FieldRef Name='notificationExpires' /><Value IncludeTimeValue='TRUE' Type='DateTime'>2011-03-30T00:00:00Z</Value></Geq>
<Or>
<Membership Type='CurrentUserGroups'><FieldRef Name='notificationTargetRoles'/></Membership>
<Contains><FieldRef Name='notificationTargetRoles'/><Value Type='User'>MyDomain\administrator</Value></Contains>
</Or>
</And>
</Where>
</Query>
When I execute this exact same query (running under the same account) in the U2U CAML Query Builder I get filtered users, groups and dates.
When apply exact the same filter in code, the Groups do not appear in the results.
What can be the reason that the group filter (CurrentGroups) does not return any results?
The code for applying the filter is:
SPListItemCollection items = null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite elevatedSite = new SPSite(theSiteName))
{
using (SPWeb elevatedWeb = elevatedSite.OpenWeb())
{
SPList alertList = elevatedWeb.Lists[theListName];
SPQuery query = new SPQuery();
query.Query = "<Where><And><Geq><FieldRef Name='notificationExpires' /><Value IncludeTimeValue='TRUE' Type='DateTime'>2011-03-30T00:00:00Z</Value></Geq> <Or><Membership Type='CurrentUserGroups'><FieldRef Name='notificationTargetRoles'/></Membership><Contains><FieldRef Name='notificationTargetRoles'/><Value Type='User'>BSFLMK\administrator</Value></Contains></Or></And></Where>";
items = alertList.GetItems(query);
}
}
});
It turns out that removing the "SPSecurity.RunWithElevatedPrivileges(delegate()" part corrected the problem

Linq To Xml - Unexpected search results

Just when I was thinking that I had Linq To Xml sussed I'm faced with yet another error! I think if I was to understand the linq search process in general better I might have more success, so any good links regarding that are also welcome. To my problem however; using the code below:
Dim xd As XDocument = _
<?xml version="1.0" encoding="utf-8"?>
<root>
<element>
<subelement id="1"/>
<subelement id="2"/>
<subelement id="3"/>
</element>
<element>
<subelement id="4"/>
<subelement id="1"/>
<subelement id="5"/>
</element>
</root>
Dim results = _
From q In xd.Descendants.<element> _
Where q.<subelement>.#id = 1
For Each xe As XElement In results
Console.WriteLine(xe.ToString)
Next
I would have expected the above code to return both 'element' nodes, but it only returns the first because it only searches the first 'subelement' node within 'element', how can I make the where clause apply to all 'subelement' nodes?
You could do
Dim results = _
From q In xd.Descendants.<element> _
From p In q.<subelement> _
Where p.#id = 1
(That is, if my VB.NET is up to the task here... I could do it in C#. Please feel free to edit.)

SQL IN equivalent in CAML

Is there a "nice" way to create a CAML query for SharePoint that does something like this?
SELECT *
FROM table
WHERE Id IN (3, 12, ...)
Or am I stuck with a nightmare of nested <Or> nodes?
EDIT: This was my solution to generate the <Or> nodes.
/// Simulates a SQL 'Where In' clause in CAML
/// </summary>
/// <param name="columnType">Specifies the data type for the value contained by the field.</param>
/// <returns>Nested 'Or' elements portion of CAML query</returns>
public static string CamlIn<T>(string internalFieldName, string columnType, T[] values)
{
XDocument doc = new XDocument();
XElement prev = null;
int index = 0;
while (index < values.Length)
{
XElement element =
new XElement("Or",
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName)),
new XElement("Value",
new XAttribute("Type", columnType),
values[index++].ToString())));
if (index == values.Length - 1)
{
element.AddFirst(
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName)),
new XElement("Value",
new XAttribute("Type", columnType),
values[index++].ToString())));
}
if (prev != null)
prev.AddFirst(element);
else
doc.Add(element);
prev = element;
}
return doc.ToString(SaveOptions.DisableFormatting);
}
Usage:
int[] ids = new int[] { 1, 2, 4, 5 };
string query = string.Format("<Where>{0}</Where>", CamlIn("SomeColumn", "Number", ids));
Output:
<Where>
<Or>
<Or>
<Or>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">5</Value>
</Eq>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">4</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">2</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name=\"SomeColumn\" />
<Value Type=\"Number\">1</Value>
</Eq>
</Or>
</Where>
Also made this overload for working with Lookup Fields a bit easier
/// <summary>
/// Simulates a SQL 'Where In' clause in CAML
/// </summary>
/// <param name="lookupId">Specify whether to use the Lookup column's Id or Value.</param>
/// <returns>Nested 'Or' elements portion of CAML query</returns>
public static string CamlIn<T>(string internalFieldName, bool lookupId, T[] values)
{
XDocument doc = new XDocument();
XElement prev = null;
int index = 0;
while (index < values.Length)
{
XElement element =
new XElement("Or",
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName),
lookupId ? new XAttribute("LookupId", "TRUE") : null),
new XElement("Value",
new XAttribute("Type", "Lookup"),
values[index++].ToString())));
if (index == values.Length - 1)
{
element.AddFirst(
new XElement("Eq",
new XElement("FieldRef",
new XAttribute("Name", internalFieldName),
lookupId ? new XAttribute("LookupId", "TRUE") : null),
new XElement("Value",
new XAttribute("Type", "Lookup"),
values[index++].ToString())));
}
if (prev != null)
prev.AddFirst(element);
else
doc.Add(element);
prev = element;
}
if (values.Length == 1)
{
XElement newRoot = doc.Descendants("Eq").Single();
doc.RemoveNodes();
doc.Add(newRoot);
}
return doc.ToString(SaveOptions.DisableFormatting);
}
For those using Sharepoint 2010, there is an IN element available:
http://msdn.microsoft.com/en-us/library/ff625761.aspx
Here's a working example:
SPQuery locationsQuery = new SPQuery();
locationsQuery.Query = string.Concat("<Where>",
"<In>",
"<FieldRef Name='ID' />",
"<Values>",
"<Value Type='Number'>6</Value>",
"<Value Type='Number'>7</Value>",
"<Value Type='Number'>8</Value>",
"</Values>",
"</In>",
"</Where>");
NO, you'll need to deal with nested OR tags; these are supported query instructions on CAML
Maybe CAML.NET can help you in your quest.
FullTextSqlQuery
It is possible to search MOSS using SQL statements, using the FullTextSqlQuery class. I have no experience of using this class personally. These articles may be of use:
http://blogit.create.pt/blogs/ricardocosta/archive/2007/06/15/How-to-use-FullTextSqlQuery-to-search-in-WSS.aspx
http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2008/03/06/how-to-use-the-moss-enterprise-search-fulltextsqlquery-class.aspx
YACAMLQT
Alternatively, there is also YACAMLQT (Yet Another CAML Query Tool) which allows you to create SharePoint CAML queries using a T-SQL syntax.
LINQ to SharePoint
If you are up to speed with LINQ, then the LINQ to SharePoint project provides a tool to query SharePoint lists using the LINQ syntax. Please note, this tool is still in the alpha testing phase, so it may not be production ready.
U2U CAML Query Builder
If you are working with CAML queries, I would recommend using the U2U CAML Query Builder for SharePoint (2003 and 2007) tool to build up your CAML queries. The tool allows you to build up your query string, and to execute it against the target list, using a point-and-click interface, as shown below.
(source: u2u.net)
Of the above four methods, I can recommend the U2U CAML Query Builder, having used it almost daily over the last 6 months. It also appears to be the most widely used CAML tool in the SharePoint community .
Note, if you are building the CAML queries in code, then I recommend that you take a look at the CAML.NET project on CodePlex, which provides "a set of .NET language-based tools for creating dynamic, reusable CAML query components".
I faced a similar thing and ultimately had to create a recursive algorithm to generate the nested OR structure. Here is my algorithm
var DynamicQuery = '<Query><Where>{{DYNAMICSTRING}}</Where></Query>';
var OneOR = '<Or><Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq>{{DYNAMICSTRING}}</Or>';
var TwoOr = '<Or><Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq><Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq></Or>';
var OnlyEq = '<Eq><FieldRef Name="IMEI" /><Value Type="Text">{{SearchValue}}</Value></Eq>';
function generateAdvancedInQuery(x){
if(x.length == 1)
return OnlyEq.replace('{{SearchValue}}',x[0]);
else if(x.length == 2)
return TwoOr.replace('{{SearchValue}}',x[0]).replace('{{SearchValue}}',x[1]);
else
return OneOR.replace('{{SearchValue}}',x[x.length-1]).replace('{{DYNAMICSTRING}}',generateAdvancedInQuery(x.splice(0,x.length-1) ) );
}
x = ['438753234098792','438753234098793','438753234098794','438753234098795','438753234098796','438753234098797','438753234098798'];
var Caml = DynamicQuery.replace('{{DYNAMICSTRING}}',generateAdvancedInQuery(x) )
This generates the XML caml query as
<Query>
<Where>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098798</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098797</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098796</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098795</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098794</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098792</Value>
</Eq>
<Eq>
<FieldRef Name="IMEI" />
<Value Type="Text">438753234098793</Value>
</Eq>
</Or>
</Or>
</Or>
</Or>
</Or>
</Or>
</Where>
</Query>