So, I love how hindsight is 20/20. I love when I carefully (okay sorta carefully) write code, step through it in the debugger, check values, properly catch errors and dispose of objects and you STILL have some stupid error that humbles me a little. Yeah, welcome to my world. In fact I almost didn’t post this blog because I felt pretty foolish, but I figured if I made the mistake maybe someone else did too and I’m all about looking like an idiot if it helps someone else succeed.
This is also the part of my blog where I encourage everyone to start a blog and write about their “duh” moments. You never know who might benefit from a little common sense. I know I could generally use a healthy dose of it.
What was I trying to accomplish?
Just to give you some backstory and my blog post more verbiage, let me help you understand what I was trying to do. Maybe even a few of you guru’s out there will say “Why the heck didn’t you just do ‘x’??”.
I had the requirement to allow a user to take a SharePoint site located at http://websiteurl/SiteToMove and move it under some other site in the current site collection’s hierarchy such as: http://websiteurl/ParentSite1/SiteToMove or http://websiteurl/ParentSite1/SubSite2/SiteToMove.
I could go into more backstory about why I needed to do this and why other alternatives would not work for us, but it really isn’t germane to the rest of the post. So, let’s assume for the sake of argument there was a good reason, and the other options for achieving the same functionality were not desirable.
How to ‘move’ a SharePoint site?
So, your first question may have been the same as mine, how do you take a SharePoint Site and move it underneath another site? Sounds kind of hairy doesn’t it? I did a few Google.. I mean Bing searches and didn’t find anything very helpful. What are the magic search terms here to get the answer? Well, I went to my second option, which was posting the question on Twitter, and wouldn’t you know it; within 10 minutes I had responses from @Jimmywim, @CraigToThePoint, and of all people @toddklindt (whom I’m convinced is a closet developer) about how this is done.
And when I heard the solution I wanted to facepalm… could it really be that simple? I mean, can anything Todd Klindt say really be trusted? (Yes and Yes by the way).
Apparently all you have to do “move” a site in this instance (same Site Collection) is update the SPWeb.ServerRelativeURL for the site in questions. That’s it… It sounded so easy I was skeptical, but I tried it out on a small scale and it worked brilliantly! I was a happy camper. Thanks again guys…
How I implemented it
Now I needed to give a user an intuitive way to “move” their site.. So, I created the following process:
- User browses to their site
- Using a custom web part, user selects which site in the hierarchy of sites is the “parent” site of their site.
- The user site’s ServerRelativeUrl is updated with new Path using the path of the “parent” site.
Sounds simple enough? Doesn’t it? And it worked… except that after the web part came back from the PostBack it was throwing an error saying my site didn’t exist, but the site did exist, and it was even updated to the correct path.
Can you guess what I did wrong? Here’s my genius code:
SPContext.Current.Web.ServerRelativeUrl = newRelativeUrl;
Now do you see it? I should not have modified the Web object in SPContext. The web part needs SPContext on the reload of the page after it comes back from the postback, and since I modified SPContext it was not able to reload the page properly.
When I instantiated my own SPWeb object and updated THAT object’s ServerRelateiveUrl (and properly disposed of the object), everything worked fine and all was right with the world.
Moral of the story
So, moral of the story, and my “duh” moment is be careful updating SPSite and SPWeb objects within SPContext. In fact, you should probably instantiate new objects when updating SPWeb, SPSite, and other collections from SPContext. I know I learned my lesson and will be more careful in the future.
I love making rookie mistakes. On the bright side, at least it wasn’t another jQuery post.