For a customer project I had to add a custom tab to the Ribbon of SharePoint 2010 for a specific library. In this tab I wanted to have several groups of controls. In one group I needed to have a button that triggers the standard upload functionality of SharePoint (Command="UploadDocument"). So far this is a pretty straight forward process.
If you've ever created a CustomAction to add a tab to the Ribbon, you'll agree that you've to write a looot of XML. I personally believe it's a best practice to comment the code one creates. If you have a XML-document with hundreds of lines of mark-up, usually it makes sense to add a comment here and there. In my case my CustomAction-XML was commented like this:
Group "New" with Button "Upload"
As you can see I've added a comment above the group "Test.Ribbon.Tab.NewGroup" and with this I've entered a world of pain. The Ribbon and the tab including all groups and controls were rendered without any issues. I also was able to click on the button "Test.Ribbon.Tab.NewGroup.Controls.Upload" and the "Upload Document"-dialog was displayed as expected, but after clicking on the "OK"-button in the dialog, I ran into this well-known error:
In the SharePoint log you can find the following entry related to this error:
System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.Web.CommandUI.Ribbon.CreateRenderContext(CUIDataSource uiproc) at Microsoft.Web.CommandUI.Ribbon.Render(HtmlTextWriter writer) at Microsoft.SharePoint.WebControls.SPRibbon.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) at System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) at System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Page.Render(HtmlTextWriter writer) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
The method "Microsoft.Web.CommandUI.Ribbon.CreateRenderContext" throws a "System.NullReferenceException". Whoa! To make a long story short, after digging around for several hours I found the reason for this issue: the comment above the group in the CustomAction-XML. Here is what Reflector tells you about the implementation of "Microsoft.Web.CommandUI.Ribbon.CreateRenderContext":
DataNode node4 = uiproc.GetResultDocument().SelectSingleNode("/spui:CommandUI/spui:Ribbon/spui:Tabs/spui:Tab[@Id='" + this.InitialTabId + "']/spui:Groups");
if (node4 == null)
node4 = uiproc.GetResultDocument().SelectSingleNode("/spui:CommandUI/spui:Ribbon/spui:ContextualTabs/spui:ContextualGroup/spui:Tab[@Id='" + this.InitialTabId + "']/spui:Groups");
Hashtable hashtable = new Hashtable();
if (node4 != null)
foreach (DataNode node5 in node4.ChildNodes)
XmlAttribute attribute2 = node5.Attributes["Id"];
if (attribute2 != null)
hashtable[attribute2.Value] = node5;
} } }…
I will not comment on the quality of this implementation, but if you look at XmlAttribute attribute2 = node5.Attributes["Id"]; it becomes clear: the Attributes-property is the reason why I get the NullReferenceException, because for a System.Xml.XmlNode-Object that is a System.Xml.XmlComment this property is null (http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.attributes.aspx). So if you put a comment above your group in your CustomAction-XML you're doomed. Do yourself a favor and don't do it.
I hope this blog-post will save you save some time and headaches. It took me quite some time to figure out the reason why my button in my custom Ribbon-tab wasn't working.
|Created by Sven Häfker|