Monday, July 12, 2010

How to modify URL in QuickLaunch links programmatically

A MOSS 2007 project has been deployed into production and I need to provide them a patch to fix up some Quick Launch links and some other functionality. The only way I had is to build a WSP with code to make my changes to the Serve where ever it is deployed. During achieving QuickLaunch Fixes I faced a little issues and decided to publish the solution to help others

We can access the quick launch from the "navigation" object available in "web" object.

web.Navigation.QuickLaunch
The QuickLaunch object is of type SPNavgationNodeCollection wich contains the collection of SPNavigationNode. There is a built in method "Update" provided in SPNavigationNode class to save any changes made in SpNavigationObject properties to the database. I tried to use the method after updating the URL of QuickLaunch link

SPNavigationNode Node = web.Navigation.QuickLaunch[Counter];
Node.Url = "NewURL/Confirmation.aspx";
Node.Update();
But it didn't work for me. I googled this issue a lot but no luck :(. After a lot of thinking on this issue and exploring the Update method using reflector I came to know that update method actually calls UpdateNavigationNode() that resides inside SPRequest object.

this.Navigation.Web.Request.UpdateNavigationNode(this.Navigation.Web.Url, this.Id, this.m_dtParented, this.Title, this.Url, ref this.m_PropertyArray, out str)





Unfortunately SPRequest object is marked with "internal" access modifier and we can not access it from another assembly. but i have to call it directly to update the content database with my URL change so I decided to use reflection to access the internal object

Object Request = null;
Request=web.GetType().GetField("m_Request",System.Reflection.BindingFlags.NonPublic |System.Reflection.BindingFlags.Instance).GetValue(web);

After successfully getting the Request object I also need to execute the UpdateNavigationNode() method using reflection because it is also marked with "internal" access modifier

Request.GetType().GetMethod("UpdateNavigationNode").Invoke(Request, new Object[] { node.Navigation.Web.Url, node.Id, node.LastModified, node.Title, URL, (m_PropertyArray), str });
Finally the method looks like this
void UpdateQuickLaunchNodeURL(SPWeb web, SPNavigationNode node, string URL)
{
Object Request = null;
Request = web.GetType().GetField("m_Request", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(web);
object m_PropertyArray = new object();
string str = "";
Request.GetType().GetMethod("UpdateNavigationNode").Invoke(Request, new Object[] { node.Navigation.Web.Url, node.Id, node.LastModified, node.Title, URL, (m_PropertyArray), str });
web.Update();
}
And this code worked for definitely. Hope it will help others.

2 comments: