Tuesday, July 17, 2012

SharePoint 2013 is here!

Finally! During the spring we here in Sweden we got July 20 as the date for the beta release. Almost a month later it is here.

Download SharePoint Server 2013 preview: http://technet.microsoft.com/en-us/evalcenter/hh973397
Download SharePoint Foundation 2013 preview: http://www.microsoft.com/en-us/download/details.aspx?id=30345

It will take some time to download the files. In the meantime it is a good idea to have a look at the training videos.

SharePoint 2013 IT pro traning videos: http://technet.microsoft.com/en-US/sharepoint/fp123606
SharePoint 2013 Developer training videos: http://msdn.microsoft.com/en-US/sharepoint/fp123633

It will be interesting if to see I can run the server since the hardware requirements has shot through the roof, http://technet.microsoft.com/library/cc262485(office.15)?ocid=fwlink#hwforwebserver. I "only" have 16 GB RAM, which also is maximum. I'll probably have to ask my boss for a new computer.

Yet another day in SharePoint paradise...

Friday, July 13, 2012

Replace New Page menu item for publishing sites

Back in SharePoint 2007 when you created a new publishing page in a publishing site you got to a page where you had to enter a title and choose a page layout.


In 2010 you just get a pop-up where you enter the name of the new page.


The new page will get the "default" page layout. If you want to change the layout, which is true in a lot of cases, you have to do that in the ribbon menu after the page has been created. Thank you Microsoft, but this is not how anyone wants to work with their publishing pages. Thankfully there is hope. There is a page in the layouts-folder called CreatePage.aspx, which is the exact same page as in 2007!


So now you, of course, want to hide the old New Page menu item with a HideCustomAction element and add a new menu item with a CustomAction element which just points to CreatePage.aspx. Well... Unfortunately Microsoft has cut some corners implementing the three menu items you get when you enable the publishing feature, i.e. New Page, New Document Library and Manage Content and Structure. Instead of adding them as three independent custom actions they have created one custom action and added the menu items in code behind. This makes it impossible to hide one of the three since all are registered with the same Id.

The solution to this madness is to create a new custom action and change the action for the New Page menu item via the object model in the code behind.

Oh, and another thing. It is impossible to add the new custom action in the exact same spot as the old New Page menu item since Microsoft does not expose the property MenuGroupId in the custom action xml, http://msdn.microsoft.com/en-us/library/ms460194.aspx. So we have to add our new custom action in code behind.

Here is my CustomAction element:

  <CustomAction
    Id="SharePoint.Paradise.CustomActions.NewPage"
    Location="Microsoft.SharePoint.StandardMenu"
    GroupId="SiteActions"
    Rights="AddListItems"
    ControlAssembly="$SharePoint.Project.AssemblyFullName$"
    ControlClass="SharePoint.Paradise.CustomActions.NewPage">
  </CustomAction>

Here is the code behind for the custom action:

namespace SharePoint.Paradise.CustomActions
{
    public class NewPage : WebControl
    {
        // Hide the old "New page" menu item
        // Menu items for the publishing feature is not added properly so we can hide them in Elements.xml with HideCustomAction, thank you Microsoft
        protected override void OnPreRender(EventArgs e)
        {
            ToolBarMenuButton menu = ToolBarMenuButton.GetMenuControl(this);
            MenuItemTemplate item = menu.GetMenuItem("wsaCreatePage");
            if (item != null)
            {
                menu.MenuControl.HiddenMenuItems.Add(item);
            }
        }
        
        // Add a the new "New page" menu item
        // MenuGroupId in not exposed to Elements.xml so we can add "New page" in the same location as the old one, thank you Microsoft
        protected override void CreateChildControls()
        {
            MenuItemTemplate item = new MenuItemTemplate();
            item.Text = HttpContext.GetGlobalResourceObject("wss", "siteactions_createpage", CultureInfo.CurrentUICulture).ToString();
            item.Description = HttpContext.GetGlobalResourceObject("wss", "siteactions_createpagedesc", CultureInfo.CurrentUICulture).ToString();
            item.ImageUrl = SPContext.Current.Web.Url + "/_layouts/images/crtpage.gif";
            item.MenuGroupId = 200;
            item.Sequence = 100;
            item.ClientOnClickNavigateUrl = SPContext.Current.Web.Url + "/_layouts/CreatePage.aspx";

            this.Controls.Add(item);
        }
    }
}

Yet another day in SharePoint paradise...

Move a document into a document set

Document set is a new feature in SharePoint 2010. It is very neat to be able to group documents together with metadata, workflows, etc. Just one small thing. There is no way to move existing documents into document sets. I recently had to come up with a solution to this for a customer and I found this gem after some searching, http://gilleslauwers.wordpress.com/2011/05/31/move-a-file-to-a-document-set/.

I changed two things to make the solution perfect.

1. Added {SiteUrl} to options.url in Elements.xml to make it work for site collections with a managed path:

options.url = '{SiteUrl}/_layouts/Sam.MoveToDocumentSet/ChooseDocumentSet.aspx?ListId={ListId}&amp;ItemId={ItemId}';

2. Changed the CAML query to display all document sets, even those of custom content types:

query.Query = "<Where><Eq><FieldRef Name='FSObjType' /><Value Type='Lookup'>1</Value></Eq></Where>";

I would rather develop features that does something customer specific than do this, which should be included in the product.

Yet another day in SharePoint paradise...

True is false, but TRUE is true

I had the craziest idea the other day. What if I write "True" or "true" instead of "TRUE" for boolean properties that should be true in my Elements.xml. I have always written "TRUE" because that's what everyone does. I hadn't given it much thought before, so I just went bezerk and wrote "True".

To my biggest suprise the property became false.

It apperas that the only true true is TRUE. I would very much like to have a chat with the retard that wrote the parser for boolean properties in SharePoint.

Yet another day in SharePoint paradise...

Separator in CustomAction for EditControlBlock

I thought I was assigned the easiest of tasks: Add a separator between our custom action and the other menu items.

I had this custom action in the ECB-menu for documents that was working perfectly. All I had to do was to add a separator. How hard could it be? Well... Apparently Microsoft has left out the possibility to add separators in the custom action xml, http://msdn.microsoft.com/en-us/library/ms460194.aspx. The only possibility to add a separator is to create it code behind with a MenuSeparatorTemplate, http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.menuseparatortemplate.aspx. This would have been all fine and dandy if code behind was an option for ECB-menus, but it isn't allowed. You can only attach UrlAction to ECB-menus.

There is a solution where you can add a separator by changing core.js, http://weblogs.asp.net/jan/archive/2009/09/03/customizing-the-sharepoint-ecb-with-javascript-part-1.aspx, but this isn't a viable option for me. The only really doable solution I found was to add our custom action dead last in the ECB-menu by setting Sequence="2000" since the delete option apparently adds a separator after itself. I found this out just by coincidence.

Here is my CustomAction element:

  <CustomAction
    Id="SharePoint.Paradise.CustomAction.DoStuff"
    Location="EditControlBlock"
    Title="Do stuff"
    RegistrationType="ContentType"
    RegistrationId="0x0101"
    Sequence="2000">
    <UrlAction Url="javascript:alert('Hello World!');"/>
  </CustomAction>

This is how it turned out in SharePoint:



Yet another day in SharePoint paradise...