Programmatically adding RSSAggregatorWebPart to a Page

I have been struggling to find information on how to add RSSAggregatorWebPart to a page. First I started with doing something like

RSSAggregatorWebPart rssViewer = new RSSAggregatorWebPart();
rssViewer.FeedUrl = "https://ketulpatel.wordpress.com/feed/";
rssViewer.ID = "rssFeed";
rssViewer.DataSourcesString = dataSourceString.ToString();
rssViewer.Title = "My Blog";
//AddWebPart is an helper method to add a webpart to a page
AddWebPart(web,rssViewer,"default.aspx","CenterColTop",0);

That added the web-part to the page but when rendering the Page, web part gave an error asking to check error logs for errors and error log under 12 hive contained following error

RssWebPart: Exception handed to HandleRuntimeException.HandleException System.ArgumentNullException: Value cannot be null. Parameter name: key at Microsoft.SharePoint.WebControls.CacheObject.LoadDataFromCache(String key) at Microsoft.SharePoint.WebControls.BaseXmlDataSource.GetXmlDocument() at Microsoft.SharePoint.WebPartPages.DataFormWebPart.GetHierarchicalDocument(IHierarchicalDataSource ds) at Microsoft.SharePoint.WebPartPages.DataFormWebPart.GetHierarchicalXPathNavigator(IHierarchicalDataSource ds) at Microsoft.SharePoint.WebControls.SingleDataSource.GetXPathNavigatorInternal() at Microsoft.SharePoint.WebControls.SingleDataSource.GetXPathNavigator() at Microsoft.SharePoint.WebControls.SingleDataSource.GetXPathNavigator(IDataSource datasource, Boolean origin…

Blha Blha….. Really could not tell what’s going on, but If I add the same web-part from the UI (Using the Web Part Gallery) than it worked fine and my feed showed up in the web-part. After examining the properties of the working web-part in the debug mode, I noticed the web part has DataSourceString and ParameterBindings property set, MSDN has no documentation about it (or at least I could not find it) and setting those properties when adding RSS WebPart programmatically worked

Here is the full code snippet

RSSAggregatorWebPart rssViewer = new RSSAggregatorWebPart();
rssViewer.FeedUrl = "https://ketulpatel.wordpress.com/feed/";
rssViewer.ID = "rssFeed";
StringBuilder dataSourceString = new StringBuilder("<%@ Register TagPrefix=\"WebControls\" Namespace=\"Microsoft.SharePoint.WebControls\" Assembly=\"Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c\" %>");
            dataSourceString.Append("<%@ Register TagPrefix=\"WebPartPages\" Namespace=\"Microsoft.SharePoint.WebPartPages\" Assembly=\"Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c\" %>");
            dataSourceString.Append("<WebControls:XmlUrlDataSource runat=\"server\" AuthType=\"None\" HttpMethod=\"GET\">");
            dataSourceString.Append("<DataFileParameters>");
            dataSourceString.Append("<WebPartPages:DataFormParameter Name=\"RequestUrl\" ParameterKey=\"RequestUrl\" PropertyName=\"ParameterValues\"/>");
            dataSourceString.Append("</DataFileParameters>");
            dataSourceString.Append("</WebControls:XmlUrlDataSource>");

rssViewer.DataSourcesString = dataSourceString.ToString();
rssViewer.ParameterBindings = "<ParameterBinding Name=\"RequestUrl\" Location=\"WPProperty&#91;FeedUrl&#93;\"/>";
rssViewer.Title = "My Blog";
AddWebPart(web,rssViewer,"default.aspx","CenterColTop",0);

Value of DataSourceString is:

<%@ Register TagPrefix="WebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<WebControls:XmlUrlDataSource runat="server" AuthType="None" HttpMethod="GET">
<DataFileParameters>
<WebPartPages:DataFormParameter Name="RequestUrl" ParameterKey="RequestUrl" PropertyName="ParameterValues"/>
</DataFileParameters>
</WebControls:XmlUrlDataSource>

Value of ParameterBindings is:

<ParameterBinding Name="RequestUrl" Location="WPProperty&#91;FeedUrl&#93;"/>

Programmatically setting up Approval workflow in MOSS

Out-of-box Approval works pretty well for simple content approval and that’s what exactly I wanted. If you attach an Approval workflow to a list from the UI you get number of options to set such as Approvers, People who needs to be notified and an important one if you want to update the approval status of a list item to Approved or Rejected is “Update the approval status (use this workflow to control content approval)” in “Post completion Workflow Activities”

As in most the real world situation I want to set this up during deployment process and not from the UI.

Following code snippet will set up your list with Moderation enabled:

SPList list = web.Lists["MyList"];
list.EnableModeration = true;
list.Update();

Following code snippet sets up the Approval work flow on the list

SPWorkflowTemplate baseTemplate = web.WorkflowTemplates.GetTemplateByName("Approval", CultureInfo.InvariantCulture);
SPWorkflowAssociation assoc = SPWorkflowAssociation.CreateListAssociation(baseTemplate, "Property Approval", web.Lists["Workflow Tasks"], web.Lists["Workflow History"]);
assoc.AllowManual = true;
assoc.AutoStartCreate = true;
string data = GetApprovalWorkFlowData();
assoc.AssociationData = data;
list.AddWorkflowAssociation(assoc);

In Above code snippet AssociationData property of SPWorkflowAssociation can be used to set things like Approvers, People who needs to be notified and “Post completion Workflow Activities” for content approval

AssociationData is in XML format and looks like:

<my:myFields xml:lang="en-us" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD">
  <my:Reviewers>
    <my:Person>
      <my:DisplayName>Ketul Patel</my:DisplayName>
      <my:AccountId>domain\kpatel</my:AccountId>
      <my:AccountType>User</my:AccountType>
    </my:Person>
  </my:Reviewers>
  <my:CC>
    <my:Person>
      <my:DisplayName>Joe Doe</my:DisplayName>
      <my:AccountId>domain\jdoe</my:AccountId>
      <my:AccountType>User</my:AccountType>
    </my:Person>
  </my:CC>
  <my:DueDate xsi:nil="true"></my:DueDate>
  <my:Description>A new Property has been added to the system and requires approval.</my:Description>
  <my:Title></my:Title>
  <my:DefaultTaskType>1</my:DefaultTaskType>
  <my:CreateTasksInSerial>true</my:CreateTasksInSerial>
  <my:AllowDelegation>true</my:AllowDelegation>
  <my:AllowChangeRequests>true</my:AllowChangeRequests>
  <my:StopOnAnyReject xsi:nil="true"></my:StopOnAnyReject>
  <my:WantedTasks xsi:nil="true"></my:WantedTasks>
  <my:SetMetadataOnSuccess>false</my:SetMetadataOnSuccess>
  <my:MetadataSuccessField></my:MetadataSuccessField>
  <my:MetadataSuccessValue></my:MetadataSuccessValue>
  <my:ApproveWhenComplete>true</my:ApproveWhenComplete>
  <my:TimePerTaskVal xsi:nil="true"></my:TimePerTaskVal>
  <my:TimePerTaskType xsi:nil="true"></my:TimePerTaskType>
  <my:Voting>false</my:Voting>
  <my:MetadataTriggerField></my:MetadataTriggerField>
  <my:MetadataTriggerValue></my:MetadataTriggerValue>
  <my:InitLock>false</my:InitLock>
  <my:MetadataStop>false</my:MetadataStop>
  <my:ItemChangeStop>false</my:ItemChangeStop>
  <my:GroupTasks>false</my:GroupTasks>
</my:myFields>

Various elements in the above XML are pretty self explaining and roughly maps to relevant tick box or textbox on the “Customize Workflow” Page (CstWrkflIP.aspx)

<my:ApproveWhenComplete>true</my:ApproveWhenComplete>

Is the element to use to set the “Update the approval status (use this workflow to control content approval)” checkbox

Programmatically Working with ListViewWebPart using Non-Default View (GetUncustomizedViewByBaseViewId)

If you add an Announcement web part to page from the web part gallery you get a nice view of the list which shows 5 items, shows (More Announcements…) link and “Add a new Announcement” link

ListViewWebPart - Announcements

This is exactly what I needed for one of my web part but my requirement was to add the web part to page from a feature programmatically and not using the UI.

After looking around for a while in MSDN and searching most of the examples showed how to set the properties of the ListViewWebPart programmatically but all of the examples used the Default View of the list as shown below (The default view is the view which you get by default on AllItems.aspx).

<br /> SPList list = web.Lists["Announcement"];<br /> ListViewWebPart webPart = new ListViewWebPart();<br /> webPart.Title = "Announcements";<br /> webPart.ViewGuid = list.DefaultView.ID.ToString("B").ToUpper();<br /> 

If you look at the Schema file for the list, the View with BaseViewID of 0 is the one which has the HTML to render the view in the ListViewWebPart

<View BaseViewID=”0″ FreeForm=”TRUE” Type=”HTML”>

So First thing that came to my mind was to iterate though the Views collection of SPList object and look for a view with BaseViewID of zero, but to my surprise it was not there in the collection OOPSSS! But If I add the Announcement web part using the UI and than search the Views collection of SPList object for BaseViewID of Zero than the View is found in the collection. So the moral of the story is SharePoint is doing some thing to customize the view and add it to the Views collection.

Now how do you do the same programmatically? Luckily I did not try very hard and found a method called GetUncustomizedViewByBaseViewId on the SPList object and that was it, here is the code snippet:

<br /> SPList list = web.Lists["Announcement"];<br /> ListViewWebPart webPart = new ListViewWebPart();<br /> webPart.Title = "Announcements";<br /> webPart.ListName = list.ID.ToString("B").ToUpper();<br /> SPView view = list.GetUncustomizedViewByBaseViewId(0);<br /> webPart.ListViewXml = view.HtmlSchemaXml;<br /> 

Few things though:

  • You cannot use ViewGuid property of ListViewWebPart as ID of the View returned by GetUncustomizedViewByBaseViewId will be empty instead use ListViewXml property of ListViewWebPart and assign View’s HtmlSchemaXml property to it
  • If your List is in a different SPWeb than the page on which you are adding ListViewWebPart than use WebId property of ListViewWebPart to point it to the ID of SPWeb which contains the List

Happy SharePointing!

Removing Attachment button from MOSS Form Toolbar

I have a requirement where I need to remove the Attachment button from the Sharepoint Form Toolbar that comes with OOTB NewForm.aspx and EditForm.aspxSharePoint tool bar Attachment

you can remove the attachment support from your list by setting DisableAttachments=”TRUE” in the <List in the Schema file. But My requirement was to keep the attachment support so the attachment can only be added from different place and not from the edit or new form pages.

To do this, you will need to override the .ascx based toolbar templates by using a custom template that overrides the OOTB toolbar.

If you look at DefaultTemplates.ascx under C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES it has a RenderTemplate with an ID of “ListForm” and the RenderingTemplate contains <SharePoint:FormToolBar runat=”server”/> . FormToolBar has a TemplateName property which can be used to override the default rendering template for the toolbar.

Copy the “ListForm” rendering template to your own ascx (myCustomTemplates.ascx) file and also add following custom template to the ascx file

<br /> <SharePoint:RenderingTemplate ID="NoAttachMentFormToolBar" runat="server"><br /> <Template></p> <table class="ms-toolbar" id="toolBarTbl" cellSpacing="0" cellPadding="2" width="100%" border="0"> <tr> <td class="ms-toolbar" noWrap width="99%"><br />                     <img height="18" alt="" src="/_layouts/images/blank.gif" width="1" /></td> <td class="ms-toolbar" noWrap><br />                     <span class="ms-descriptiontext" id="reqdFldTxt" style="PADDING-RIGHT: 3px; WHITE-SPACE: nowrap"><br />                     <span class="ms-formvalidation">*</span> indicates a required field</span></td> </tr> </table> <p></Template><br /> </SharePoint:RenderingTemplate><br /> 

Now change the ID of ListForm rendering template that you copied into your ascx to MyCustomFormTemplate and add TemplateName=”NoAttachMentFormToolBar” to the <SharePoint:FormToolBar… control.

<br /> <SharePoint:RenderingTemplate ID="MyCustomFormTemplate" runat="server"><br /> 	<Template><br /> 		<SPAN id='part1'><br /> 			<SharePoint:InformationBar runat="server"/><br /> 			<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator="&nbsp;" runat="server"><br /> 					<Template_RightButtons><br /> 						<SharePoint:NextPageButton runat="server"/><br /> 						<SharePoint:SaveButton runat="server"/><br /> 						<SharePoint:GoBackButton runat="server"/><br /> 					</Template_RightButtons><br /> 			</wssuc:ToolBar><br /> 			<SharePoint:FormToolBar runat="server" TemplateName="NoAttachMentFormToolBar"/><br /> 			<TABLE class="ms-formtable" style="margin-top: 8px;" border=0 cellpadding=0 cellspacing=0 width=100%><br /> 			<SharePoint:ChangeContentType runat="server"/><br /> 			<SharePoint:FolderFormFields runat="server"/><br /> 			<SharePoint:ListFieldIterator runat="server"/><br /> 			<SharePoint:ApprovalStatus runat="server"/><br /> 			<SharePoint:FormComponent TemplateName="AttachmentRows" runat="server"/><br /> 			</TABLE></p> <table cellpadding=0 cellspacing=0 width=100%> <tr> <td class="ms-formline"><IMG SRC="/_layouts/images/blank.gif" width="1" height="1" alt=""></td> </tr> </table> <p><TABLE cellpadding=0 cellspacing=0 width=100% style="padding-top: 7px"></p> <tr> <td width=100%><br /> 			<SharePoint:ItemHiddenVersion runat="server"/><br /> 			<SharePoint:ParentInformationField runat="server"/><br /> 			<SharePoint:InitContentType runat="server"/><br /> 			<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbl" RightButtonSeparator="&nbsp;" runat="server"><br /> 					<Template_Buttons><br /> 						<SharePoint:CreatedModifiedInfo runat="server"/><br /> 					</Template_Buttons><br /> 					<Template_RightButtons><br /> 						<SharePoint:SaveButton runat="server"/><br /> 						<SharePoint:GoBackButton runat="server"/><br /> 					</Template_RightButtons><br /> 			</wssuc:ToolBar></td> </tr> <p></TABLE><br /> 		</SPAN><br /> 		<SharePoint:AttachmentUpload runat="server"/><br /> 	</Template><br /> </SharePoint:RenderingTemplate></p> <p>

That’s it. Copy your myCustomTemplates.ascx into C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES. Now Sharepoint will use the NoAttachMentFormToolBar template when rendering the custom template.

one last thing, you will need to point the editform and newform pages to your new custom template. In your list schema.xml file modify the <Form element to point to the new template

Don’t forget IISRESET after copying the new schema and custom ascx control tempalte to 12 hive

<br />  <Forms><br />       <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" /><br />       <Form Type="EditForm" Url="EditForm.aspx" WebPartZoneID="Main" Template="MyCustomFormTemplate" /><br />       <Form Type="NewForm" Url="NewForm.aspx" WebPartZoneID="Main" Template="MyCustomFormTemplate"/><br />     </Forms></p> <p>

Remove Attachment button from Sharepoint form toolbar

Update:

Satesh attempt to post a code block into comments for some reason is not working, so here is the code bloc, Thanks for the comment:

<br />  <SharePoint:RenderingTemplate ID="NoAttachMentFormToolBar" runat="server"><br />  <Template><br />   <wssuc:ToolBar CssClass="ms-toolbar" id="toolBarTbl" RightButtonSeparator="&nbsp;" runat="server"><br />   </wssuc:ToolBar><br />  </Template><br /> </SharePoint:RenderingTemplate></p> <p>

Custom Paging in SPGridView — Extending SPGridViewPager

Setting up Paging in SPGridView is pretty well explained in SPGridView: Adding paging blog.

Basically you have to set the PagerTemplate property of the SPGridView to null after adding the Grid to the Controls collection and you will get default style (1 2 3……. ) pagination.

But what if you want SharePoint OOTB style pagination like:

Custom Paging in SPGridView

For that SPGridViewPager control (which is not much talked about) comes in handy, drop the control on to the page and set the GridViewId to your SPGridView control’s ID

<SharePoint:SPGridViewPager runat=”server” GridViewId=”myGridView” />

If you are adding the SPGridView programmatically than create an instance of SPGridViewPager and set the GirdViewId programmatically

</p> <p>SPGridViewPager pager = new SPGridViewPager();<br /> pager.ID = "mypager";<br /> pager.GridViewId = "myGridView";<br /> base.Controls.Add(pager);</p> <p>

Well now what if you want something like Page 1 of 10 style pagination with Next and Previous Button 🙂

You can extend SPGridViewPager control and overrider it’s Render method to render out what ever style you want. Reflector came in really handy in mimicing what SPGridViewPager was doing.

Here is Sample Code for Extending SPGridViewPager control:

</p> <p>public class CustomPager : SPGridViewPager<br /> {</p> <p>protected override void Render(System.Web.UI.HtmlTextWriter output)<br />     {<br />         if ((this.GridViewControl != null)<br />                 && (this.PreviousPageLinkIsEnabled || this.NextPageLinkIsEnabled))<br />         {<br />             this.RenderImage(output, this.PreviousPageLinkIsEnabled, "previouspage", "/_layouts/images/prev.gif", "/_layouts/images/blank.gif", "Previous Page");<br />             output.Write(string.Format("Page {0} of {1}",this.GridViewControl.PageIndex.ToString(), this.GridViewControl.PageCount.ToString()));<br />             this.RenderImage(output, this.NextPageLinkIsEnabled, "nextpage", "/_layouts/images/next.gif", "/_layouts/images/blank.gif", "nextpage");</p> <p>}<br />     }</p> <p>private bool PreviousPageLinkIsEnabled<br />     {<br />         get<br />         {<br />             if (this.GridViewControl != null)<br />             {<br />                 if (this.GridViewControl.PageIndex > 0)<br />                 {<br />                     return true;<br />                 }<br />             }<br />             return false;<br />         }<br />     }</p> <p>private bool NextPageLinkIsEnabled<br />     {<br />         get<br />         {<br />             if (this.GridViewControl != null)<br />             {<br />                 if (this.GridViewControl.PageIndex < (this.GridViewControl.PageCount - 1))<br />                 {<br />                     return true;<br />                 }<br />             }<br />             return false;<br />         }<br />     }</p> <p>private void RenderImage(HtmlTextWriter output, bool isEnabled, string postbackEventArgument, string enabledImageUrl, string disabledImageUrl, string toolTip)<br />     {<br />         string str = disabledImageUrl;<br />         if (isEnabled)<br />         {<br />             output.Write("<a href="\&quot;#\&quot;" onclick="\"");><br" />             output.Write(this.Page.ClientScript.GetPostBackEventReference(this, postbackEventArgument));<br />             output.Write("; return false;\">");<br />             str = enabledImageUrl;<br />         }<br />         output.Write("<img src="\&quot;&quot;);&lt;br" />         output.Write(str);<br />         output.Write("\" border=\"0\" alt=\"");<br />         output.Write(toolTip);<br />         output.Write("\"/>");<br />         if (isEnabled)<br />         {<br />             output.Write("</a>");<br />         }<br />     }<br /> }</p> <p>

SPGridViewPager contains a protected property GridViewControl using that you can easily find out current PageIndex and total PageCount as shown in above code snippet.

Programmatically Sorting Top Navigation Menu in MOSS 2007

You can easily sort the Top navigation bar in MOSS 2007 by going to Settings -> Navigation in your root level Web

Sorting Navigation in MOSS 2007

Programmatic access to proprieties for Navigation sorting is buried within Microsoft.SharePoint.Publishing.PublishingWeb namespace in Microsoft.SharePoint.Publishing assembly!

There are three properties for Navigation sorting

1. NavigationOrderingMethod

2. NavigationSortAscending

3. NavigationAutomaticSortingMethod

here is sample code that sorts the navigation menu by Created Date of Sub-Webs

</p> <p>using (SPSite site = new SPSite("http://localhost"))<br /> {<br />                using (SPWeb web = site.RootWeb)<br />                {<br />                     PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);<br />                     pubWeb.NavigationOrderingMethod = OrderingMethod.Automatic;<br />                     pubWeb.NavigationSortAscending = true;<br />                     pubWeb.NavigationAutomaticSortingMethod = AutomaticSortingMethod.CreatedDate;<br />                     web.AllowUnsafeUpdates = true;<br />                     pubWeb.Update();<br />                     web.AllowUnsafeUpdates = false;<br />                }<br />  }</p> <p>