Wednesday, June 29, 2011

SharePoint 2010: pages in folders get renamed when created (aka: why can’t I create default.aspx in a subfolder in the Pages library)

Sharepoint 2007 didn’t support using folders in the pages library on a publishing site (http://support.microsoft.com/default.aspx?scid=kb;EN-US;948614), but 2010 explicitly does (http://technet.microsoft.com/en-us/library/ee721053.aspx):

Pages libraries in SharePoint Server 2010 now support creating folders and storing pages within folders...

Great!  Now I don’t have to create a bunch of sub-sites just because I want my URLs to look a certain way.  Unfortunately, like so many things that seem great, it’s a little more complex than that in practice…

 

I can create new folders in the pages library, and pages in those folders:

image  image

image

But when I do, Sharepoint is sometimes renaming them on me – what I wanted as default.aspx became default0628-5180.aspx:

image

But I can go to 'Edit Properties', change the name back to ‘default’, and it works:

image

image

image

So, I can have a page named ‘default’ in a folder in my pages library, but I can’t create it – I have to create it with a different name and rename it.

Why?  Well, let’s look at the code…  /_layouts/CreatePage.aspx is the page I’m on when I create it, so I check C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\template\layouts\CreatePage.aspx.  It inherits from Microsoft.SharePoint.Publishing.Internal.CodeBehind.CreatePagePage, so I fire up my trusty copy of ILSpy (http://wiki.sharpdevelop.net/ILSpy.ashx), and dig into that class in Microsoft.SharePoint.Publishing.  Let’s see if we can figure out what’s going on.  Let’s start in the button click event handler:

image

Depending on PageType, we go different places – what is PageType?

image

Ok, so PageType will be “GenericPage” unless VariationsPageBase or FileName are set in the querystring (which they aren’t), or PageType is set in the viewstate elsewhere (which it isn’t).  This means CreateStandardPage gets called from ButtonCreatePage_Click.

image

Since we know PageType is “GenericPage”, the first if statement applies, which calls PublishignPage.GetUniquePageName to make our page name unique.  But notice – it does *not* pass in the folderUrl (which it gets from the query string on the next line), so it’ll have no way to know it needs to be unique in the folder, not at the root of the library.  From here, we should be able to guess at what the real bug is, but let’s keep digging to verify.

image

GetUniquePageName then uses CommonUtilities.DoesFileExistInDocLibRootFolder to determine if the file already exists.

image

Which, as one would suspect, checks if the file is unique at the *root* of the pages library, not in the subfolder where it’s actually going to be created.

 

There you have it – the real reason Sharepoint is messing with my page name – it checks the wrong folder to make sure the name is unique.  From the looks of this, the workarounds are pretty simple:

  1. Let Sharepoint rename the page as I’m creating it, then rename it back manually.
  2. “Don’t do that” – change the name of the page at the root that I’m conflicting with (or the name of the page I’m creating).  Remember, the homepage of a site does not *have* to be named ‘default.aspx’.

Note: Sharepoint 2010 SP1 was just announced yesterday (http://sharepoint.microsoft.com/blog/Pages/BlogPost.aspx?pID=984), and I haven’t been over the change list with a fine-toothed comb (especially since I can’t find a consolidation of the lists on the 20-some KBs this rolls up), but this may have been fixed in it (or the June CU that is recommended to be applied).