NullReferenceException at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_ApplicationProperties()

You get the exception below when browsing to your SharePoint site. In my case this happened on a brand new site that I just created.

Server Error in ‘/’ Application.

Object reference not set to an instance of an object.

Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.]
Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_ApplicationProperties() +134
Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_PartitionIDs() +44
Microsoft.Office.Server.Administration.UserProfileApplicationProxy.IsAvailable(SPServiceContext serviceContext) +329
Microsoft.Office.Server.WebControls.MyLinksRibbon.get_PortalAvailable() +44
Microsoft.Office.Server.WebControls.MyLinksRibbon.EnsureMySiteUrls() +60
Microsoft.Office.Server.WebControls.MyLinksRibbon.get_PortalMySiteUrlAvailable() +15
Microsoft.Office.Server.WebControls.MyLinksRibbon.OnLoad(EventArgs e) +91
….

Searching for this on Google will turn up quite a number of hits. Some people reported that deleting and recreating the User Profile Service Application (UPSA) fixed the issue. However, this isn’t always an option – it certainly wasn’t in my case.

In my case the problem was because the app pool account of the web application did not have permission to the UPSA. I fixed this by:

  • Go to Central Admin, then Manage service applications
  • Click on the row (not the link) of the UPSA to highlight it
  • From the ribbon, click Permissions then grant the app pool account of the web application Full Control (the only option)
  • Do not use the Administrators button on the ribbon. Adding the app pool account to the Administrators list did not fix the issue in my case.

 

 

Posted in SharePoint 2010 | Leave a comment

Visual Studio 2010 freezes periodically for a few seconds

Lately I started experiencing the above problem. Visual Studio 2010 would frequently freeze up for a few seconds and then unfreeze itself. When it does this, I cannot type or do anything in Visual Studio.

This was driving me mad and I came close to doing the same thing to the computer as the guy in this video: http://youtu.be/HtTUsOKjWyQ

Luckily I found a solution that works for me. Launch Internet Explorer. Go to Internet Options, then Advanced tab. Under the Security group, untick “Check for server certificate revocation“. You may need to restart Visual Studio.

Posted in Visual Studio 2010 | Leave a comment

Adding Enter and ESC default keys to SharePoint list forms

When creating or editing list items in SharePoint, have you ever wished that you could save the item by pressing Enter?

I have developed a small solution that enables users to save the list item by pressing Enter when the cursor is in a single-line text box. Pressing the ESC key closes the form without saving. The Enter and ESC keys work on the Create and Edit forms. The ESC key in addition also works on the Display form.

This solution is elegant in that it does not require you to modify any element in your SharePoint instance.

1. Download the solution

You can download the complete Visual Studio solution here.

Activate the site collection feature BNH.SharePoint.ListFormDefaultButtons after deploying the solution.

2. How does it work?

The approach is actually really simple. On loading of a page, a jQuery script is executed and check if the page is one of the list forms. The script then attaches JavaScript event handlers to the text boxes on the form to handle the keypress and keyup events. Within the handlers, if the key stroke was an Enter or ESC, then jQuery is used to retrieve the Save or Cancel button on the form and invoke their click event. The code is well commented so review the comment if you are interested.

What makes this solution elegant is how the script is delivered to the page. This is done by a CustomAction with the Location attribute set to ScriptLink as below:

<CustomAction Id="ListFormDefaultButtonsCustomActions.JQueryScript"
				  Location="ScriptLink"
				  ScriptSrc="BNH.SharePoint.ListFormDefaultButtons/jquery-1.7.2.min.js"
				  Sequence="100"/>

	<CustomAction Id="ListFormDefaultButtonsCustomActions.MainScript"
				  Location="ScriptLink"
				  ScriptSrc="BNH.SharePoint.ListFormDefaultButtons/listFormDefaultButtons.js"
				  Sequence="101"/>

The two CustomActions above cause the two script files to be included in the <head> section of all pages where the feature is activated. This means you can add JavaScript execution on load to any page without modifying any masterpage or page layout. It also means they can be removed simply by deactivating the feature.

3. Things to note

  • List form file names: the code determines whether the current page is a list form by looking for the OOTB form file names, i.e. DispForm.aspx, NewForm.aspx, and EditForm.aspx. The solution as provided will not work if your list forms use other file names.
  • OOTB ESC key behaviour in IE: OOTB and in IE, pressing the ESC key while the cursor is in a single-line text box will undo/reset changes to the text in the text box. Chrome does not have this behaviour. This solution will override this behaviour in IE.
  • OOTB keyboard short cuts: OOTB you can use Alt + O to trigger the Save button on the Create and Edit forms. I still like the Enter key better :). OOTB you can use Alt + C to trigger the Cancel button. However for some reason this does not work for me in Chrome. And again, I prefer the ESC key.

4. Check out my other solutions

Check out my other custom solutions that fill certain gaps in SharePoint here.

Posted in List Form, SharePoint 2010 | Leave a comment

Cache Monitor: Now you can force that cache item to refresh!

Caching is a two-edged sword. It is essential to the performance of your site, but it becomes a problem when you, or the business, needs to affect a high priority change in production. If you are using the HTTP runtime’s cache, the only way you can force the cache to update is to recycle the app pool. If you manage to convince the server admin to do this for you in production, this means that your users, and users of other site collections on the app pool will be negatively impacted.

Introducing the Cache Monitor. This is a simple tool that allows site collection administrators to search for cache items (by item key) and remove them from the cache, hence forcing the items to be refreshed.

Users access the tool from Site Settings \ Site Collection Administration.

Users search for items by key and choose the items to delete from the cache.

After deploying the solution, you need to active the site collection feature BNH.SharePoint.CacheMonitor.

This solution works with the HTTP runtime’s cache only.

1. Download the solution

You can download the complete Visual Studio solution here.

2. Interesting points

The code pretty much is just straightforward ASP.NET. One thing worth mentioning is how to handle the SPMenuField click event on server-side as a postBack. I have written about that here.

3. Check out my other solutions

Check out my other custom solutions that fill certain gaps in SharePoint here.

Posted in SharePoint 2010 | Leave a comment

SummaryLinkWebPart: Access Denied saving Web Part properties: either the Web Part is embedded directly in the page, or you do not have sufficient permissions to save properties (Web Part ‘Summary Links’).

Normal users (read-only) of our SharePoint site start receiving this error when visiting a content page:

Access Denied saving Web Part properties: either the Web Part is embedded directly in the page, or you do not have sufficient permissions to save properties (Web Part ‘[web part name]’).

The full stack is:

[WebPartPageUserException: Access Denied saving Web Part properties: either the Web Part is embedded directly in the page, or you do not have sufficient permissions to save properties (Web Part ‘Summary Links’).]
Microsoft.SharePoint.WebPartPages.WebPart.ThrowIfSaveWouldFail() +24319257
Microsoft.SharePoint.WebPartPages.WebPart.SetSavePropertiesInternal(Boolean dirty) +66
Microsoft.SharePoint.WebPartPages.WebPart.set_SaveProperties(Boolean value) +24296479
Microsoft.SharePoint.Publishing.WebControls.SummaryLinkWebPart.OnInit(EventArgs e) +122
System.Web.UI.Control.InitRecursive(Control namingContainer) +143
System.Web.UI.Control.AddedControl(Control control, Int32 index) +271
System.Web.UI.WebControls.WebParts.WebPartManagerControlCollection.AddWebPartHelper(WebPart webPart) +305
System.Web.UI.WebControls.WebParts.WebPartManagerControlCollection.AddWebPart(WebPart webPart) +1933374
System.Web.UI.WebControls.WebParts.WebPartManagerInternals.AddWebPart(WebPart webPart) +63
Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartWithRetry(WebPart webPart) +746
Microsoft.SharePoint.WebPartPages.SPWebPartManager.CreateWebPartsFromRowSetData(Boolean onlyInitializeClosedWebParts) +7123
Microsoft.SharePoint.WebPartPages.SPWebPartManager.LoadWebParts() +146
Microsoft.SharePoint.WebPartPages.SPWebPartManager.OnPageInitComplete(Object sender, EventArgs e) +288
System.EventHandler.Invoke(Object sender, EventArgs e) +0
System.Web.UI.Page.OnInitComplete(EventArgs e) +11058238
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1674

The error appeared random and occurred for different pages. Sometime for the same page, the error would go away then come back later.

As it turns out, other people are experiencing the same issue: http://social.technet.microsoft.com/Forums/en-US/sharepoint2010setup/thread/d86e22b3-d929-48b1-9e4a-166a275365d1/. The error appeared random because it would go away when an admin user visits the page, and sometime came back at a later stage.

These errors are caused by the OOTB SummaryLinkWebPart. Using dotPeek to look at the code I was able to figure out what’s going on.

Internally the SummaryLinkWebPart stores the URL of the links that have been added to it. When the web part loads, it compares the stored URLs with the actual current URL of the links. If there are differences, it will update itself. It does this even for normal users that have read-only access, and hence the error occurs. When an admin user visits the page, the web part is able to successfully update its data. The stored URLs and the actual current URL of the links are in sync, and hence the page starts working again for read-only users… until someone updates the URL of one of the links that have been added to the SummaryLinkWebPart.

I have tested this with the July 2012 CU and the issue still exists.

Please let me know if you have found a fix for this somewhere.

Posted in SharePoint 2010, SummaryLinkWebPart | 3 Comments

How to handle SPMenuField click on server side as postBack

Using SPMenuField in an SPGridView you can create drop down menu options for each item in the list – just like the ECB in SharePoint.

Sometime you may want to handle each menu item click as a server-side event, i.e. a postBack. I have seen a few different approaches for achieving this, but I think the cleanest and most intuitive is to raise server-side events against the parent SPGridView. I’ll describe this approach below.

The key is to use the ClientOnClickUsingPostBackEvent property of each MenuItemTemplate. The value of this property has the format [ID of control to receive event],[argument for the event]. So if the ID of your parent grid is grdItems, you should set the value of this property to “grdItems,[argument for the event]“.

[argument for the event] should have the format [command name]$[command argument].

Using this approach fires the OnRowCommand server-side event on the parent grid when the menu item is clicked. The [command name] and [command argument] is passed in to our event handler as the CommandName and CommandArgument properties of the event parameter respectively.

So in the code example below, the grid ID is grdItems, which has an event handler for the OnRowCommand, namely grdItems_RowCommand. The menu item “Refresh from Source” would fire the OnRowCommand event on the grid, passing the command name as “Refresh” and the command argument as “ItemKey” (for now the value ItemKey is hardcoded and will be the same for all items – we will fix this later).

<SharePoint:SPGridView ID="grdItems" AutoGenerateColumns="false" runat="server" OnRowCommand="grdItems_RowCommand">
		<Columns>
			<SharePoint:SPMenuField HeaderText="Item Key" TextFields="Key" MenuTemplateId="grdItemsMenu" />
		</Columns>
	</SharePoint:SPGridView>
	<SharePoint:MenuTemplate ID="grdItemsMenu" runat="server">
		<SharePoint:MenuItemTemplate Text="Refresh from Source" ImageUrl="/_layouts/images/recurrence.gif"
			runat="server" ClientOnClickUsingPostBackEvent="grdItems,Refresh$ItemKey" />
	</SharePoint:MenuTemplate>

The code behind would look like this:

protected void grdItems_RowCommand(object sender, GridViewCommandEventArgs e)
		{
			switch (e.CommandName.ToLower())
			{
				case "refresh":
					HandleRefreshCommand((string)e.CommandArgument);
					break;
			}
		}

		private void HandleRefreshCommand(string itemKeyToRefresh)
		{
			//Do your stuff
		}

The code above pass in the hardcoded value “ItemKey” for all items. We need to change it so that the actual Key of the selected item is passed in. To do this, add the attribute TokenNameAndValueFields=”ItemKey=Key” to the SPMenuField’s markup. This tells the SPMenuField that the token %ItemKey% can be used in the MenuItemTemplate, and its value will be replaced with the data field Key. We also need to change the ClientOnClickUsingPostBackEvent attribute in the MenuItemTemplate’s markup to be “grdItems,Refresh$%ItemKey%“.

The markup for the grid should now be as follow:

<SharePoint:SPGridView ID="grdItems" AutoGenerateColumns="false" runat="server" OnRowCommand="grdItems_RowCommand">
		<Columns>
			<SharePoint:SPMenuField HeaderText="Item Key" TextFields="Key" MenuTemplateId="grdItemsMenu"
				TokenNameAndValueFields="ItemKey=Key" />
		</Columns>
	</SharePoint:SPGridView>
	<SharePoint:MenuTemplate ID="grdItemsMenu" runat="server">
		<SharePoint:MenuItemTemplate Text="Refresh from Source" ImageUrl="/_layouts/images/recurrence.gif"
			runat="server" ClientOnClickUsingPostBackEvent="grdItems,Refresh$%ItemKey%" />
	</SharePoint:MenuTemplate>

The other nice thing with this approach is you can actually make your menu item fires the grid’s OOTB events, e.g. OnRowDeleting, OnSorting, OnSelectedIndexChanging, etc. You do this by specifying a command name that is known to the GridView class (parent of SPGridView). For example, to trigger the OnRowDeleting event, use the command name Delete. Use ILSpy or dotPeek to check out the GridView.HandleEvent() method to see the known command names. Beware however, that some of the OOTB command names (e.g. Delete) expects the command argument to be the index of the item. If you use these, make sure you pass in the appropriate command argument.

Posted in SharePoint 2010, SPGridView | 3 Comments

“SPSolutionExporter: System.InvalidOperationException: The Writer is closed or in error state” when saving site as template

I ran into the above error when saving a collaboration site as template using the OOTB SharePoint 2010 UI. The full stack is as below. This post describes how I solved this issue.

SPSolutionExporter: System.InvalidOperationException: The Writer is closed or in error state.    
 at System.Xml.XmlWellFormedWriter.AdvanceState(Token token)   
 at System.Xml.XmlWellFormedWriter.WriteEndElement()   
 at Microsoft.SharePoint.ScopedXmlWriterElement.Closer(XmlWriter writer, ScopedObjectUsage`1 wrapper)   
 at Microsoft.SharePoint.ScopedObjectUsage`1.Dispose(Boolean isDisposing)   
 at Microsoft.SharePoint.ScopedObjectUsage`1.Dispose()   
 at Microsoft.SharePoint.SPSolutionExporter.ExportFields(SPFieldCollection fields, String partitionName)   
 at Microsoft.SharePoint.SPSolutionExporter.ExportLists()   
 at Microsoft.SharePoint.SPSolutionExporter.GenerateSolutionFiles()   
 at Microsoft.SharePoint.SPSolutionExporter.ExportWebAsSolution()

Note that one of the calls in the stack is SPSolutionExporter.ExportFields(SPFieldCollection, ..). Using ILSpy you can see that this is being called for SPWeb.AvailableFields where SPWeb is the site you are saving. This means all fields “available” to the site are being exported.

First, change the logging level in Central Admin so we can get more info about what’s going on. When saving a site as template, activities are logged under the category SharePoint Foundation \ General. Change this to Verbose.

Run ULS Viewer and perform the save again. Using the correlation ID of the error, you will now see these two additional lines in the ULS just before the error:

SPSolutionExporter: Creating output stream for XML file at ‘C:\Users\TEMP.[yourDomain].002\AppData\Local\Temp\SPSolutionExporter-f472347a-8001-4756-8949-604f4ccad08c\TEST2ListInstances\ElementsFields.xml’

SPSolutionExporter: Closing XmlWriter ‘TEST2ListInstances\ElementsFields.xml’.

The first line indicates the physical location where the WSP (i.e. your site template) is being saved. The second line indicates the file that is causing the error. Note ‘TEST2ListInstances‘ – ‘TEST2’ is the name I specified for my site template.

Go to the physical location and open the ElementsFields.xml file. In my case, this file was incomplete and therefore the XML is malformed. The last field (i.e. the incomplete field) in the file appeared as below:

<Field Type="MultiChoice" ID="{faeb36f0-dca0-4636-a0a1-936353e1076a}" Name="MyField" DisplayName="My Field" Group="My List Columns" Required="TRUE" FillInChoice="FALSE" ShowInDisplayForm="FALSE" ShowInViewForms="FALSE" xmlns="http://schemas.microsoft.com/sharepoint/" SourceID="{1349b558-1773-4441-b7ab-1df02509bc8e}" StaticName="MyField" EnforceUniqueValues="FALSE" Indexed="FALSE" Overwrite="TRUE">
		<CHOICES>
			<CHOICE

I checked the SchemaXml property of the offending field in SharePoint Manager, and it appeared as below:

<Field Type="MultiChoice" ID="{faeb36f0-dca0-4636-a0a1-936353e1076a}" Name="MyField" DisplayName="My Field" Group="My List Columns" Required="TRUE" FillInChoice="FALSE" ShowInDisplayForm="FALSE" ShowInViewForms="FALSE" xmlns="http://schemas.microsoft.com/sharepoint/" SourceID="{1349b558-1773-4441-b7ab-1df02509bc8e}" StaticName="MyField" EnforceUniqueValues="FALSE" Indexed="FALSE" Version="4">
  <CHOICES>
    <CHOICE xmlns="">Some text</CHOICE>
  </CHOICES>
</Field>

The problem is the xmlns=”” part of the CHOICE element. I edited the SchemaXml property of the field straight in SharePoint Manager (do this in Dev environment only!!) and removed the xmlns=”” part. I was then able to successfully save the site as template.

There is more work to be done at this point, because if you now edit the field using the OOTB SharePoint UI, it will add the xmlns=”” part back in (even if you just click OK and didn’t make any update using the SharePoint UI).

To stop SharePoint from doing this, remove the xmlns=”http://schemas.microsoft.com/sharepoint/&#8221; part from the parent Field element.

The offending field was deployed through XML. I went back and look at the source code and both the Field and the CHOICE elements do not have the xmlns attribute specified. Not sure how that attribute made it into the SharePoint DB – another mystery.

Posted in Field, SharePoint 2010, Site Column, Site Template | Leave a comment

HTTP 403 Forbidden when calling Excel Services REST API (ExcelRest.aspx)

Today I was looking into Excel Services REST API (ExcelRest.aspx) in SharePoint 2010 for the first time. I followed some good articles on the web but kept on getting HTTP 403 Forbidden errors when invoking ExcelRest.aspx through the browser. Surprisingly didn’t find much help on this error on Google.

Looked into the ULS and found the following error message:

Result=Microsoft.Office.Excel.Server.CalculationServer.ExcelServiceBase+EcsFaultException: This workbook cannot be opened because it is not stored in an Excel Services Application trusted location. (Fault Detail is equal to Microsoft.Office.Excel.Server.ExcelServerMessage).

This must be one of those rare occassions that SP gives you error messages that help troubleshooting!

To fix this launch Central Admin, then go to Manage service applications, and click on Excel Services Application. Click Trusted File Locations and then add your location as a Trusted File Location.

Posted in Excel Services, SharePoint 2010 | Leave a comment

Custom Ribbon buttons to bulk publish, approve/reject, cancel approval and unpublish multiple items

————

UPDATE (2015-07-10): If you just want the WSPs, then they can be downloaded here for 2013.

UPDATE (2013-06-06): A SharePoint 2013 version of this solution is now available! Download it here. The 2010 version is still available for download.

UPDATE: There is a bug in the original code where the modal wait screen does not close properly in IE (when publishing items). It works fine with Chrome however.

I have updated the downloadable code with the fix. This now works with IE and Chrome. I’m pretty sure it works with Firefox also.
————

OOTB in SharePoint 2010 you can bulk approve/reject and unpublish multiple items using the Content and Structure tool (under Site Administration). There are a few problems with this however:

  • Obviously this is not intuitive
  • There is no bulk publish
  • There is no bulk cancel approval
  • Bulk approve/reject doesn’t seem to do anything when there is a content approval workflow running on the items (is this happening for you too?)

I went ahead and developed a couple of custom Ribbon buttons that allow you to bulk publish, approve/reject, cancel approval and unpublish multiple items. If an approval workflow is defined for the library, these actions start or stop the workflow appropriately.

The user gets a flyout menu as below:

For bulk publish and approve/reject, the user gets an OOTB-looking dialog that lists the selected items as below:

A result screen lists any item that could not be processed and the reason:

1. Download the source code

You can download the complete Visual Studio solution here.

2. Want to further improve the user experience in SharePoint?

Check out my other custom solutions here.

3. Key and interesting points

I did not go into details about the code for this solution because most of it is actually just straightforward SharePoint & ASP.NET.  I however have highlighted key and interesting points below.

General approach

The general approach is to extract the ID of the selected items, concatenate them into a delimited string, and then open an application page (in dialog mode) and pass the string as a query string parameter. The ID of the list is also passed to the application page. There is one application page for each of the action (publish, approve/reject, etc) and all of the processing is done in these application pages. When the application page closes, the list is refreshed.

Referencing JavaScript for the buttons

There are 2 CustomAction elements. One defines our custom buttons for the Ribbon, the other adds a reference to our JavaScript to the current page (i.e. the list view). This latter element looks like below. Location=”ScriptLink” is the bit that does the magic.

&lt;CustomAction Id="BulkPublishingRibbonCustomActions.Script"
				  Location="ScriptLink"
				  ScriptSrc="BNH.SharePoint.BulkPublishing/BulkPublishing.js"/&gt;

Enable/disable the buttons

The flyout button (the main one) should be disabled if no items are selected. This is straightforward. The child buttons however should be enabled/disabled depending on the settings of the list. Publish for example should be disabled if minor version is not enabled.

To get the settings of the list we need to make async calls using the SP JavaScript API. To make the EnabledScript for the button works with async however, we need to make use of the OOTB JavaScript method RefreshCommandUI(). This is described in this post: http://www.itidea.nl/index.php/using-async-call-to-enable-a-custom-ribbon-button.

The RefreshCommandUI() method essentially forces all the EnabledScript to be re-evaluated. However, it only seems to do it for the EnabledScript of the main button, not the child buttons. Furthermore, the EnabledScript of the main button is fired when the page loads or when items are selected. The EnabledScript of the child buttons are fired when the main button is clicked, i.e. when the flyout menu actually “flies out”.

The approach I have taken is to make the async calls in the EnabledScript of the main button to gather all the relevant settings and store them into variables. The EnabledScript of the child buttons simply check these variables.

Achieving the OOTB look and feel

If you have ever looked at the OOTB application pages, you’d noticed that special user controls are used to display each section on the page. Below for example is one section.

The two OOTB user controls used to create these sections are wssuc:InputFormSection and wssuc:InputFormControl. These controls are registered on the ASPX page as follow:

&lt;%@ Register TagPrefix="wssuc" TagName="InputFormSection" Src="~/_controltemplates/InputFormSection.ascx" %&gt;
&lt;%@ Register TagPrefix="wssuc" TagName="InputFormControl" Src="~/_controltemplates/InputFormControl.ascx" %&gt;

The below markup demonstrates how to use these controls:

&lt;wssuc:inputformsection id="formSectionCheckInComment" title="This is the bold heading on the left hand side" runat="server"&gt;
			&lt;Template_Description&gt;
&lt;asp:Literal runat="server" text="This section is the explanatory text that appears beneath the bold heading on the left hand side."/&gt;
			&lt;/Template_Description&gt;
			&lt;Template_InputFormControls&gt;
&lt;!-- This section contains the controls to appear on the right. --&gt;
				&lt;wssuc:InputFormControl LabelText="Label for the particular input field" runat="server"&gt;
					&lt;Template_Control&gt;
&lt;!-- Define the control(s) that represent your input field in this section --&gt;
						&lt;textarea id="txtComment" class="ms-long" rows="5" cols="45" title="&lt;%$Resources:wss,checkin_checkincomment_title%&gt;" name="CheckinDescription" runat="server"&gt;&lt;/textarea&gt;
					&lt;/Template_Control&gt;
				&lt;/wssuc:InputFormControl&gt;
			&lt;/Template_InputFormControls&gt;
		&lt;/wssuc:inputformsection&gt;

There is also a special user control for the buttons at the end. This user control is wssuc:ButtonSection. This is registered as:

&lt;%@ Register TagPrefix="wssuc" TagName="ButtonSection" Src="~/_controltemplates/ButtonSection.ascx" %&gt;

This control renders a Cancel button by default (although you can switch this off), which will close the modal dialog if the page is being displayed in dialog mode. This user control can be used as follow:

&lt;wssuc:ButtonSection id="buttonSectionDefault" runat="server"&gt;
			&lt;template_buttons&gt;
&lt;!-- Define your additional buttons here. The default Cancel button will be rendered in addition to these. --&gt;
				&lt;asp:Button UseSubmitBehavior="false" runat="server" class="ms-ButtonHeightWidth buttonOK" Text="&lt;%$Resources:wss,multipages_okbutton_text%&gt;" id="btnOK" OnClick="btnOK_Click" accesskey="&lt;%$Resources:wss,okbutton_accesskey%&gt;"/&gt;
			&lt;/template_buttons&gt;
		&lt;/wssuc:ButtonSection&gt;

There are 2 important things to remember when using these controls:

1. All the form sections should be wrapped in a table tag as follow:

&lt;table class="ms-propertysheet" border="0" width="100%" cellspacing="0" cellpadding="0"&gt;
&lt;!-- Form section controls go here --&gt;
&lt;/table&gt;

2. Controls in the template sections need to be server controls, i.e. runat=”server”, otherwise they won’t be rendered.

Displaying and closing wait dialog after button post back in dialog mode

When the OK button is clicked (while the page is being displayed in dialog mode) a time consuming operation is launched and I wanted to display a wait dialog. When the post back is completed (i.e. the time consuming operation has finished) I wanted to close the wait dialog but remain on the original page (in dialog mode) to display the result.

I used the OOTB SP.UI.ModalDialog.showWaitScreenWithNoClose() JavaScript method but had some problems closing the wait dialog properly. I solved this in the end and wrote about it here: How to close SharePoint modal wait screen after postBack when page is in dialog mode.

Making the custom buttons available for all libraries

CustomActions typically can be registered against a list template, list URL or content type. I wanted to make these buttons available for the Pages library, document libraries (OOTB and custom templates), master page gallery, etc. The only way this could be achieved is to register the CustomActions with a base content type, such as Document. This is because when the CustomActions are registered against a content type, it will also be displayed for content types inherited (directly or indirectly) from the registered content type.

Posted in Custom Actions, Ribbon, SharePoint 2010 | 31 Comments

SPListItem.Workflows also returns completed workflows

I needed to retrieve all the running workflows for a list item. I tried SPListItem.Workflows and according to MSDN this should give me what I need. It however doesn’t – I found that it also includes completed workflow instances.

I found that I can use the SPWorkflowManager.GetItemActiveWorkflows() method instead to achieve what I needed.

The MSDN documentation for SPListItem.Workflows says:

Gets the collection of the workflow objects that represent instances of the item workflows that are currently running, but does not get the workflow associations.

The MSDN documentation for SPWorkflowManager.GetItemActiveWorkflows() says:

Returns a collection of the workflow instances currently running on the specified list item.

One would expect that they would give the same results – it however seems that the former doesn’t work as documented.

Posted in SharePoint 2010, Workflow | Leave a comment