Archive for the ‘SharePoint’ Category

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. };

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>

Okay, I’ve not blogged for sometime. So here a quick one just as a memory jogger for myself.

I needed to add a SharePoint URL field to a GridView to display data from a SP link list.  Here’s how i did it.

Code Snippet
  1. <asp:TemplateField>
  2.                         <HeaderTemplate>
  3.                           Title
  4.                         </HeaderTemplate>
  5.                         <ItemTemplate>
  6.                             <asp:Hyperlink NavigateUrl='<%#DataBinder.Eval(Container.DataItem, "URL").ToString().Split(new string[] {", "}, StringSplitOptions.RemoveEmptyEntries)[0]%>' Text='<%#DataBinder.Eval(Container.DataItem, "URL").ToString().Split(new string[] {", "}, StringSplitOptions.RemoveEmptyEntries)[1]%>' runat="server"></asp:Hyperlink>
  7.                         </ItemTemplate>
  8.                     </asp:TemplateField>

I know its not rocket science and there’s probably a better way to do it, but a least I won’t have to trawl through Google again to find the answer.

More to come soon. Need to get back into blogging…

Okay, I’ve not done any blogging for a while, been mega busy… But I just came across this problem in a MOSS environment, which after a bit of digging was easily resolved. Just thought I’d share…

While trying to filter a list with a Telerik component. I came across the above error ( also shown in the screen shot below)

image

After looking in the log files I discovered that is was throwing an exception of type ThrowIfMaxHttpCollectionKeysExceeded

Entry in the log file 

Error=Operation is not valid due to the current state of the object.   at System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded()     at System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding)     at System.Web.HttpRequest.FillInFormCollection()

After a bit of digging it turns out that this is a direct result of an MS update to thwart DOS attacks. As can be seen by the entry on Scott Guthrie’s Blog.  However, in this case, i was trying to fix an internal application so DOS attacks were not an issue.

To fix this issue add the following to the web.config file

<appSettings>
  <add key="aspnet:MaxHttpCollectionKeys" value="Number greater than 1000 until the error goes away" />
</appSettings>

I needed to set this value to 3000 to resolve the issue.   Surprised smile

I just like to start by saying that this post is not ground breaking. However, when I tried to do this it did take me a while to find the answer, so I thought I’d just blog to add it to the grey matter.

As I’m sure you are all aware you can provision multiple files with preconfigured web parts by using a SharePoint module’s element file and a web part page as a template, by targeting the web part zones on the web part page.

However, trying to connect these caused me a bit of problems. In the end though it was quite straight forward. And can be done by specifying the following attributes in the code snippets and the descriptions given in the table below.

WebPartConnection
  1. <WebPartConnection ConsumerConnectionPointID="MediaSearchConsumer" ConsumerID="MediaResultsWebPart"
  2.                          ProviderConnectionPointID="MediaSearchProvider" ProviderID="MediaSearchWebPart" ID="MediaSearchConnector"/>

Web Part Consumer
  1.       <AllUsersWebPart WebPartZoneID="MiddleZone2" WebPartOrder="0" ID="MediaResultsWebPart">
  2.         <![CDATA[<?xml version="1.0" encoding="utf-8"?>
  3. <webParts>
  4.   <webPart xmlns="http://schemas.microsoft.com/WebPart/v3"&gt;
  5.     <metaData>
  6.       <type name="Instalec.SharePoint.WebParts.MediaResultsWebPart.MediaResultsWebPart, Instalec.SharePoint.WebParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e5b38b443f03fff" />
  7.       <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
  8.     </metaData>
  9.     <data>
  10.       <properties>
  11.         <property name="Title" type="string">Media Search Results</property>
  12.         <property name="Description" type="string">Web part to display the results from the media search</property>
  13.          <property name="Hidden" type="bool">True</property>
  14.           <property name="AllowHide" type="bool">True</property>
  15.       </properties>
  16.     </data>
  17.   </webPart>
  18. </webParts>
  19. ]]>
  20.       </AllUsersWebPart>

Web Part Provider
  1.     <AllUsersWebPart WebPartOrder="1" WebPartZoneID="MiddleZone" ID="MediaSearchWebPart">
  2.             <![CDATA[<webParts>
  3.   <webPart xmlns="http://schemas.microsoft.com/WebPart/v3"&gt;
  4.     <metaData>
  5.       <type name="Instalec.SharePoint.WebParts.MediaSearchWebPart.MediaSearchWebPart, Instalec.SharePoint.WebParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e5b38b443f03fff" />
  6.       <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
  7.     </metaData>
  8.     <data>
  9.       <properties>
  10.         <property name="Title" type="string">Media Search</property>
  11.         <property name="Description" type="string">My Visual WebPart</property>
  12.       </properties>
  13.     </data>
  14.   </webPart>
  15. </webParts>
  16. ]]>
  17.         </AllUsersWebPart>

Connection Consumer Attribute
  1. [ConnectionConsumer("The Search Criteria", "MediaSearchConsumer")]
  2.         public void IMediaSearchConsumer(IMediaSearch mediaSearch)

Connection Provider
  1. [ConnectionProvider("The Search Criteria", "MediaSearchProvider")]
  2.      public IMediaSearch IMediaSearchProvider()
  3.      {
  4.          return this;
  5.      }

 

ConsumerID ID specified in the AllUserWebPart element as seen in the Web Part Consumer above
ConsumerConnectionPointID The ID of the ConnectionConsumerAttribute seen above
ProviderID ID specified in the AllUserWebPart element as seen in the Web Part Provider above
ProviderConnectionPointID The ID of the ConnectionProviderAttribute seen
above
ID This can be any value but will not work without it

Job done… Smile

Scenario: Using a Data View Web Part to create a form to submit anonymous user’s enquiries.  These enquiries were submitted to a list called “Contact Us” on the root sites.  This was all very well, but as it was a internet exposed publishing site,  the anonymous user had to have RW access to the list to allow it to write the enquires.   Unfortunately, it is not possible to give the anonymous user write only access to a list. 

Solution: To block browser access you need to add a location path to the web.config on all of the front end servers. In this instance it was the Contact Us list which was done as follows.

     <location path="Lists/Contact Us">
      <system.web>
         <authorization>
            <deny users="?"/>
         </authorization>
      </system.web>
   </location>

Note: A space is used in the path, not %20

This is only applicable to the top level site and if you want to restrict access to lists on sub sites, they will need to be prefixed with the site name.

To see some other security factors use the Plan for and design security and Plan security for an external anonymous access environment pages on MSDN