接着上一篇Query Options的一些用法(4):UTC时间处理,这一篇也是介绍一下日历中关于重复发生事件(Recurrence)的查询。
首先,建立测试数据,一个每周重复发生的事件,一个普通的事件。
这个测试中,增加了一个特殊的ViewField,fRecurrence,用来判断当前事件是否是重复发生的。
static XmlNode ViewFields
{
get
{
XmlElement viewFields = _camlDoc.CreateElement("ViewFields");
System.Text.StringBuilder viewFieldsSB = new System.Text.StringBuilder();
#region View Fields
viewFieldsSB.Append(" <FieldRef Name=\"Title\" />");
viewFieldsSB.Append(" <FieldRef Name=\"fRecurrence\" />");
#endregion
string sResult = viewFieldsSB.ToString();
viewFields.InnerXml = viewFieldsSB.ToString();
return viewFields;
}
}
先来看看没有Query Options的情况。
static void Main(string[] args)
{
Lists client = new Lists();
client.Url = webUrl + "/_vti_bin/lists.asmx";
client.Credentials = System.Net.CredentialCache.DefaultCredentials;
XmlNode resultNode = client.GetListItems(listName, String.Empty, QueryAll, ViewFields, "0", null, String.Empty);
Console.ReadLine();
}
<rs:data ItemCount="2" xmlns:rs="urn:schemas-microsoft-com:rowset">
<z:row ows_Title="Event01" ows_fRecurrence="0" ows_MetaInfo="1;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-13 13:00:00" ows_ID="1" ows_UniqueId="1;#{AD2FE4CC-9E53-4C90-9D9D-57EFBD4E04B9}" ows_owshiddenversion="1" ows_FSObjType="1;#0" ows_Created="2012-12-13 12:58:13" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 12:58:13" ows_EndDate="2012-12-13 14:00:00" ows_FileRef="1;#teams/smetechcom/Lists/Calendar/1_.000" xmlns:z="#RowsetSchema" />
<z:row ows_Title="WeeklySeries" ows_fRecurrence="1" ows_MetaInfo="3;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-13 09:00:00" ows_ID="3" ows_UniqueId="3;#{1F1AB07D-1161-4355-8B20-7EEEC9AC5C02}" ows_owshiddenversion="1" ows_FSObjType="3;#0" ows_Created="2012-12-13 13:07:46" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 13:07:46" ows_EndDate="2032-02-02 12:00:00" ows_FileRef="3;#teams/smetechcom/Lists/Calendar/3_.000" xmlns:z="#RowsetSchema" />
</rs:data>
结果一目了然。和我们的测试数据完全一致。紧接着,增加Query Options,看看有什么变化。
static XmlNode QueryOptions
{
get
{
XmlElement queryOptions = _camlDoc.CreateElement("QueryOptions");
queryOptions.InnerXml = "<ExpandRecurrence>True</ExpandRecurrence>";
return queryOptions;
}
}
static void Main(string[] args)
{
Lists client = new Lists();
client.Url = webUrl + "/_vti_bin/lists.asmx";
client.Credentials = System.Net.CredentialCache.DefaultCredentials;
XmlNode resultNode = client.GetListItems(listName, String.Empty, QueryAll, ViewFields, "0", QueryOptions, String.Empty);
Console.ReadLine();
}
<rs:data ItemCount="2" xmlns:rs="urn:schemas-microsoft-com:rowset">
<z:row ows_Title="Event01" ows_fRecurrence="0" ows_MetaInfo="1;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-13 13:00:00" ows_ID="1" ows_UniqueId="1;#{AD2FE4CC-9E53-4C90-9D9D-57EFBD4E04B9}" ows_owshiddenversion="1" ows_FSObjType="1;#0" ows_Created="2012-12-13 12:58:13" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 12:58:13" ows_EndDate="2012-12-13 14:00:00" ows_FileRef="1;#teams/smetechcom/Lists/Calendar/1_.000" xmlns:z="#RowsetSchema" />
<z:row ows_Title="WeeklySeries" ows_fRecurrence="1" ows_MetaInfo="3;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-13 09:00:00" ows_ID="3" ows_UniqueId="3;#{1F1AB07D-1161-4355-8B20-7EEEC9AC5C02}" ows_owshiddenversion="1" ows_FSObjType="3;#0" ows_Created="2012-12-13 13:07:46" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 13:07:46" ows_EndDate="2032-02-02 12:00:00" ows_FileRef="3;#teams/smetechcom/Lists/Calendar/3_.000" xmlns:z="#RowsetSchema" />
</rs:data>
有意思的事情出来了,结果没有任何变化。似乎这个参数并没有什么用处。看来必须要对CAML查询动动手脚了。必须要增加对重复发生事件的一段查询(DateRangesOverlap部分,这一部分也是属于缺少相关文档状态,如需了解更多用法,善用搜索)。如下高亮所示。
static XmlNode QueryAll
{
get
{
XmlElement query = _camlDoc.CreateElement("Query");
System.Text.StringBuilder querySB = new System.Text.StringBuilder();
querySB.Append(" <Where>");
querySB.Append(" <And>");
querySB.Append(" <Neq>");
querySB.Append(" <FieldRef Name=\"ID\" />");
querySB.Append(" <Value Type=\"Counter\">0</Value>");
querySB.Append(" </Neq>");
querySB.Append(" <DateRangesOverlap>");
querySB.Append(" <FieldRef Name=\"EventDate\" />");
querySB.Append(" <FieldRef Name=\"EndDate\" />");
querySB.Append(" <FieldRef Name=\"RecurrenceID\" />");
querySB.Append(" <Value Type=\"DateTime\"><Month /></Value>");
querySB.Append(" </DateRangesOverlap>");
querySB.Append(" </And>");
querySB.Append(" </Where>");
query.InnerXml = querySB.ToString();
return query;
}
}
再次运行示例,结果变化了,每周发生的重复事件被成功展开了。
一点需要注意的,在DateRangesOverlap中我指定了只展开一个月的数据(<Value Type=\"DateTime\"><Month /></Value>),这里的一个月根据测试结果显示,是从这个重复事件创建之后的一个月内。例如本示例,该事件创建于2012-12-13,虽然第一个事件开始事件是2012-12-17,这里最后一个事件是到2013-01-07,而不是2013-01-14。
<rs:data ItemCount="5" xmlns:rs="urn:schemas-microsoft-com:rowset">
<z:row ows_Title="Event01" ows_fRecurrence="0" ows_MetaInfo="1;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-13 13:00:00" ows_ID="1" ows_UniqueId="1;#{AD2FE4CC-9E53-4C90-9D9D-57EFBD4E04B9}" ows_owshiddenversion="1" ows_FSObjType="1;#0" ows_Created="2012-12-13 12:58:13" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 12:58:13" ows_EndDate="2012-12-13 14:00:00" ows_FileRef="1;#teams/smetechcom/Lists/Calendar/1_.000" xmlns:z="#RowsetSchema" />
<z:row ows_Title="WeeklySeries" ows_fRecurrence="1" ows_MetaInfo="3;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-17 09:00:00" ows_ID="3.0.2012-12-17T01:00:00Z" ows_UniqueId="3;#{1F1AB07D-1161-4355-8B20-7EEEC9AC5C02}" ows_owshiddenversion="1" ows_FSObjType="3;#0" ows_Created="2012-12-13 13:07:46" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 13:07:46" ows_EndDate="2012-12-17 12:00:00" ows_FileRef="3;#teams/smetechcom/Lists/Calendar/3_.000" xmlns:z="#RowsetSchema" />
<z:row ows_Title="WeeklySeries" ows_fRecurrence="1" ows_MetaInfo="3;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-24 09:00:00" ows_ID="3.0.2012-12-24T01:00:00Z" ows_UniqueId="3;#{1F1AB07D-1161-4355-8B20-7EEEC9AC5C02}" ows_owshiddenversion="1" ows_FSObjType="3;#0" ows_Created="2012-12-13 13:07:46" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 13:07:46" ows_EndDate="2012-12-24 12:00:00" ows_FileRef="3;#teams/smetechcom/Lists/Calendar/3_.000" xmlns:z="#RowsetSchema" />
<z:row ows_Title="WeeklySeries" ows_fRecurrence="1" ows_MetaInfo="3;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2012-12-31 09:00:00" ows_ID="3.0.2012-12-31T01:00:00Z" ows_UniqueId="3;#{1F1AB07D-1161-4355-8B20-7EEEC9AC5C02}" ows_owshiddenversion="1" ows_FSObjType="3;#0" ows_Created="2012-12-13 13:07:46" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 13:07:46" ows_EndDate="2012-12-31 12:00:00" ows_FileRef="3;#teams/smetechcom/Lists/Calendar/3_.000" xmlns:z="#RowsetSchema" />
<z:row ows_Title="WeeklySeries" ows_fRecurrence="1" ows_MetaInfo="3;#" ows__ModerationStatus="0" ows__Level="1" ows_fAllDayEvent="0" ows_EventDate="2013-01-07 09:00:00" ows_ID="3.0.2013-01-07T01:00:00Z" ows_UniqueId="3;#{1F1AB07D-1161-4355-8B20-7EEEC9AC5C02}" ows_owshiddenversion="1" ows_FSObjType="3;#0" ows_Created="2012-12-13 13:07:46" ows_PermMask="0x7fffffffffffffff" ows_Modified="2012-12-13 13:07:46" ows_EndDate="2013-01-07 12:00:00" ows_FileRef="3;#teams/smetechcom/Lists/Calendar/3_.000" xmlns:z="#RowsetSchema" />
</rs:data>
在示例开始之前,我增加了一个特殊的ViewField,fRecurrence。如果没有增加,运行整个例子的话,最后重复事件是没法展开的。
有时候其实我们并不知道什么时候需要添加这种很奇葩的东西,那怎么办?
我推荐在每个查询中,Query Option都最好使用<IncludeMandatoryColumns>True</IncludeMandatoryColumns>,这个参数会自动帮你把需要的这些列都加上去。这个参数在Lists.GetListItems方法文档上已经存在,就不单独介绍了。
IncludeMandatoryColumns |
TRUE to specify that mandatory system columns be returned in addition to the fields specified by the viewFields parameter (for example, owsHiddenVersion, dependent fields, and required fields). This element is optional, and its default value is TRUE. |
祝大家少看看技术文档,度过一个愉快的末日。