It would appear that, when it comes to querying calendar events in SharePoint 2013, the CAML required does not seem to recognise <Now/> as its predecessors did.

To retrieve all future events in 2007 the CAML was as follows:

2007 Events CAML
  1. var query = new SPQuery
  2.                 {
  3.                     Query = @"<Where>
  4.                                  <DateRangesOverlap>
  5.                                     <FieldRef Name='EventDate'/>
  6.                                     <FieldRef Name='EndDate'/>
  7.                                     <FieldRef Name='RecurrenceID'/>
  8.                                     <Value IncludeTimeValue='TRUE' Type='DateTime'>
  9.                                         <Now/>
  10.                                     </Value>
  11.                                  </DateRangesOverlap>
  12.                               </Where>
  13.                               <OrderBy>          
  14.                                 <FieldRef Name='EventDate' Ascending='TRUE'/>      
  15.                               </OrderBy>",
  16.                     ExpandRecurrence = true,
  17.                     RowLimit = Convert.ToUInt32(this.ItemsToDisplay)
  18.                 };

However, when trying this in 2013, only the recurring events are returned.

To fix this,  amend the query as follows:

2013 Events CAML
  1. var query = new SPQuery
  2.                         {
  3.                             Query =
  4.                               string.Format(
  5.                                  @"<Where>
  6.                                   <Or>
  7.                                      <Geq>
  8.                                         <FieldRef Name='EventDate' />
  9.                                             <Value Type='DateTime'  IncludeTimeValue='TRUE'>{0}</Value>
  10.                                     </Geq>
  11.                                       <DateRangesOverlap>
  12.                                         <FieldRef Name='EventDate'/>
  13.                                         <FieldRef Name='EndDate'/>
  14.                                         <FieldRef Name='RecurrenceID'/>
  15.                                         <Value IncludeTimeValue='TRUE' Type='DateTime'><Now/></Value>
  16.                                      </DateRangesOverlap>
  17.                                 </Or>
  18.                               </Where>
  19.                               <OrderBy>          
  20.                                 <FieldRef Name='EventDate' Ascending='TRUE'/>      
  21.                               </OrderBy>",
  22.                                          DateTime.Now.ToCamlDateFormat()),
  23.                             ExpandRecurrence = Convert.ToBoolean(context[ContextKeys.IsRecurringIncluded]),
  24.                             RowLimit = Convert.ToUInt32(context[ContextKeys.ItemsToDisplay])
  25.                         };

 

Firstly, I tried to use the above query using <Now/> instead of the {0} parameter of string.Format, but the non-recurring events were not returned. It turns out that you need to use a Z format date for it to work. For this, I created an extension method of DateTime as follows:

ToCamDateFormat
  1. /// <summary>
  2.       /// To the CAML date format.
  3.       /// </summary>
  4.       /// <param name="dateToConvert">The date to convert.</param>
  5.       /// <returns>The date in the 2012-03-21T12:18:55Z format</returns>
  6.      public static string ToCamlDateFormat(this DateTime dateToConvert)
  7.      {
  8.          return dateToConvert.ToString("u").Replace(" ", "T");
  9.      }

Hope this saves you a few hours Smile

Okay, I’ve not blogged for a while and this was mainly due to being subjected to SharePoint 2007 development once again.  However, I’m now into the land of SharePoint 2013 and I’ve no doubt I will be actively posting once more as I discover various nuances of the new environment.

So, here’s my first, which was a bit of a head scratcher!! After creating a custom list, I tried to add a new list item and received the following unhelpful error.

clip_image002

After a bit of Google-ing as few fixes were suggested, but none of which seemed like a viable solution. For reference, so you don’t go down same route, these were :

  • Enable Anonymous access
  • Restart the SharePoint Search Host Controller  service
  • Lack of RAM

None of these work, so don’t even try.

Next step, was to go to the logs where I found a call was being made to the /_vti_bin/client.svc/ProcessQuery

However, on opening the WCF service in the browser I received the following 500 error  “Operation is not valid due to the current state of the object” which lead me the eventual problem.

My web.config didn’t have a serviceHostingEnvironment element.  Adding the following to the <system.serviceModel> section resolved the issue

Service Hosting Element
  1. <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

However, you may have the following already in your config

Wrong Service Hosting Environ
  1.  
  2. <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true"/>

If you remove  multipleSiteBindingsEnabled="true"  it should work

Hope this helps you save a few hours

Open-mouthed smile

After spending a bit of time trying to figure out the correct CAML to show all future items with the inclusion of recurring items. I thought I’d just blog it to save me the hassle if I need to use it again 

All Calendar Items CAML
  1.  
  2. var query = new SPQuery {
  3.     Query = @"<Where>
  4.                  <DateRangesOverlap>
  5.                     <FieldRef Name='EventDate'/>
  6.                     <FieldRef Name='EndDate'/>
  7.                     <FieldRef Name='RecurrenceID'/>
  8.                     <Value IncludeTimeValue='TRUE' Type='DateTime'>
  9.                         <Now/>
  10.                     </Value>
  11.                  </DateRangesOverlap>
  12.               </Where>
  13.               <OrderBy>          
  14.                 <FieldRef Name='EventDate' Ascending='TRUE'/>      
  15.               </OrderBy>",
  16.     ExpandRecurrence = true,
  17.     RowLimit = Convert.ToUInt32(this.ItemsToDisplay)
  18. };

Loading a Dropdown in Gridview Edit Mode

Posted: 16th April 2013 in ASP.NET
Tags:

I’ve just came across and strange phenomenon when using a grid view control. The scenario I encountered occurred when the edit event was fired

Scenario:

To allow items to be added to the grid view I added a text box and a dropdown to the footer which works fine.

However, if, at a future date, I needed to edit the added item I need to load the dropdown into the row being edited and set the previously selected item.  In principal this seemed fairly straight forward by just checking the RowState on the RowDataBound event to see if it was in edit mode (DataControlRowState.Edit).  In practice this only worked on every second/alternate row. 

It turns out you have to use a bitwise comparison to get it to work as seen in the Row Data Bound code below

Row Data Bound
  1. protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
  2.         {
  3.             GridView gridView = (GridView)sender;
  4.             if (e.Row.RowType == DataControlRowType.EmptyDataRow || e.Row.RowType == DataControlRowType.Footer || (e.Row.RowState & DataControlRowState.Edit) > 0)
  5.             {
  6.                 DropDownList categoryDropDownList = e.Row.FindControl("CategoryDropDownList") as DropDownList;
  7.                 this.BindCategoryDropDown(categoryDropDownList);
  8.                 if (e.Row.RowState == DataControlRowState.Edit)
  9.                 {
  10.                     var teamUpdate = e.Row.DataItem as TeamUpdate;
  11.                     if (categoryDropDownList != null && teamUpdate != null)
  12.                     {
  13.                             categoryDropDownList.Items.FindByText(teamUpdate.Category).Selected = true;
  14.                     }
  15.                 }
  16.             }

Bind Dropdown
  1. /// <summary>
  2.       /// Binds the category drop down.
  3.       /// </summary>
  4.       /// <param name="dropDownList">The drop down list.</param>
  5.       private void BindCategoryDropDown(DropDownList dropDownList)
  6.       {
  7.           if (dropDownList == null)
  8.           {
  9.               return;
  10.           }
  11.  
  12.           dropDownList.DataSource = this.ReportCategories;
  13.           dropDownList.DataValueField = "Key";
  14.           dropDownList.DataTextField = "Value";
  15.           dropDownList.DataBind();
  16.       }

 

So,in short, use:

(e.Row.RowState & DataControlRowState.Edit) > 0)

not

e.Row.RowState == DataControlRowState.Edit

Cheers Smile

 

Table Cell Padding and Spacing using CSS

Posted: 11th October 2012 in css
Tags:

Okay folks I’m not going to lie. This is a blatant copy of a post on Stack Overflow, but its something I keep forgetting and one for the memory banks.

Here’s the original post by 2astalavista

DEFAULT:

enter image description here

CELLSPACING:

controls the space between table cells

enter image description here

CELLPADDING:

sets the amount of space between the contents of the cell and the cell wall

enter image description here

BOTH:

enter image description here

BOTH SPECIAL:

enter image description here

http://jsfiddle.net/H4emK/

When trying to set the value a data source element to a Boolean value my first attempt was using ToString() on the Boolean value. To me this seemed like a valid way to set the value as can be seen below.

Setting XPath using ToString
  1. this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isTaskHighlight", this.NamespaceManager).SetValue(this.IsTaskHighlight.ToString());

However, when I tried to use this I received the following error. 

image

On further investigation I found that the ToString() method on a Boolean returns “True” or “False”, not the lower case “true” or “false” InfoPath is looking for.  

To resolve this I created  local method BooleanToString to return the correct value

Infopath boolean to string
  1. private string BooleanToString(bool isTrue)
  2.         {
  3.             return isTrue ? "true" : "false";
  4.         }

And called it to set the value

Setting XPathNavigator to Bool
  1. this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isTaskHighlight", this.NamespaceManager).SetValue(this.BooleanToString(this.IsTaskHighlight));

job done ! Smile

It’s been a while since I’ve used AJAX, but I came across the error “Script control may not be registered before PreRender” when trying to add a timer control to an User Control embedded in a WebPart. I’m pretty certain I have encountered this error before, but as it took me a little while to resolve I thought I’d better blog about it.

What was I trying to do? Well, I was trying to create a Web Part which created a sort of slideshow of web parts! The idea was to use various web parts, which displayed different charts, by loading them dynamically using an Update Panel, a Timer and an AsyncPostBackTrigger. 

At first, things didn’t go to well and I received the error screen shown below

Script control may not be registered before PreRender 

It turns out that the solution is slightly easier that I expected.  Initially, I added a script manager to the user control but, because the timer control automatically posts back the script manager is not loaded when its is looking for it.

So, to resolve the issue, I added the ScriptManager to the SharePoint master page added a ScriptManagerProxy to the user control and it worked a treat.

User Control HTML
  1.   <asp:ScriptManagerProxy ID="ScriptManagerProxy1"runat="server">
  2. </asp:ScriptManagerProxy>
  3. <asp:Timer ID="Timer1" runat="server" OnTick="Timer1_Tick" Interval="20000">
  4. </asp:Timer>
  5. <asp:UpdatePanel ID="DynamicUpdatePanel" runat="server">
  6.    <Triggers>
  7.         <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
  8.     </Triggers>
  9.     <ContentTemplate>
  10.         <asp:PlaceHolder ID="DynamicPlaceHolder" runat="server"></asp:PlaceHolder>
  11.     </ContentTemplate>
  12. </asp:UpdatePanel>