SharePoint Internals – Hristo Pavlov’s Blog

10 December, 2008

Deploying WebParts with a DelegateControl

Brian Farnhill talks about an interesting approach of deploying zoneless web parts by using a Delegate Control in your master page or page layout. See his blog post here:  http://pointstoshare.spaces.live.com/Blog/cns!AEC42F315B4528B0!3247.entry

The idea is that you add a DelegateControl in your master page or page layout and configure it’s ControlId to a unique id that you are going to define in a separate feature by using a Control element. This way you can replace the control/web part without the need of changing the master page but only by updating your feature. Even more you can activate different controls in different sites by activating different features in those sites, which define different controls with the same Id that matches the ControlId configured in the DelegateControl.

When SharePoint is searching for the control specified in the DelegateControl it can also search only features of a specific scope i.e. Web, Site, etc. This can be configured from the Scope attribute of the DelegateControl. Also you can configure only one control to be rendered or all controls with this id to be rendered with the AllowMultipleControls attribute. If no matching Control element could be found, then no control is rendered i.e. if you want to remove the web part, just deactivate the feature. Additionally the DelegateControl allows a PrefixHtml and SuffixHtml to be defined.

You will probably want to use this approach when you need for different sites to show different web parts on the same location of the page. You do this by using a single page layout (or master page) with a single DelegateControl and then activating different features on those sites which will activate the different web parts to be rendered. Very nice indeed!

Delegate controls are used for defining the search controls in SharePoint. The web controls that are going to be hosted must be registered as safe. You can also host ASCX web user controls the same way.

8 December, 2008

UrlAction Tokens of the CustomAction Feature

Filed under: SharePoint — Tags: , , , , , , , , , — hristopavlov @ 1:07 am

I was looking today for the complete list of tokens that can be used in the UrlAction element when building a CustomAction feature but I couldn’t find much. So I decided to put together this blog entry to help other people that may be looking for the same thing.

As you know some tokens can be used when specifying the Url of the custom action: 

<UrlActionUrl=”~site/_layouts/ItemAudit.aspx?ID={ItemId}&amp;List={ListId}”/>

Those token will be replaced by SharePoint at runtime with values derived from the current context. To get the complete list we just need to find the function that does the replacement. Luckily this function is in the .NET libraries of SharePoint and can be disassembled with Reflector. So here is the complete list of the tokens:

Token Replaced By
~site/ SPContext.Current.Web.ServerRelativeUrl
~sitecollection/ SPContext.Current.Site.ServerRelativeUrl
{ItemId} item.ID.ToString()
{ItemUrl} item.Url
{SiteUrl} web.Url
{ListId} list.ID.ToString(“B”)
{RecurrenceId} item.RecurrenceID

For the records the method that does the replacement is Microsoft.SharePoint.SPCustomActionElement.ReplaceUrlTokens() and looks like this:

private static string ReplaceUrlTokens(

    string urlAction,

    SPWeb web,

    SPList list,

    SPListItem item)

{

    string recurrenceID;

 

    if (!string.IsNullOrEmpty(urlAction))

    {

        if (item != null)

        {

            string newValue = item.ID.ToString(CultureInfo.InvariantCulture);

 

            urlAction = urlAction.Replace(“{ItemId}”, newValue);

            urlAction = urlAction.Replace(“{ItemUrl}”, item.Url);

            recurrenceID = newValue;

 

            if (!string.IsNullOrEmpty(item.RecurrenceID))

            {

                recurrenceID = item.RecurrenceID;

            }

        }

    }

    else

    {

        return urlAction;

    }

 

    urlAction = urlAction.Replace(“{RecurrenceId}”, recurrenceID);

 

    if (web != null)

        urlAction = urlAction.Replace(“{SiteUrl}”, web.Url);

 

    if (list != null)

        urlAction = urlAction.Replace(“{ListId}”, list.ID.ToString(“B”));

 

    // Replaces ~site/ and ~sitecollection/ with the site and site collection urls

    urlAction = SPUtility.GetServerRelativeUrlFromPrefixedUrl(urlAction);

 

    return urlAction;

}

The web, list and item arguments are taken from the context before the user is redirected to the custom action page.

2 December, 2008

The file is currently checked out or locked for editing by another user

Filed under: SharePoint — Tags: , , , , — hristopavlov @ 12:52 am

This is a nasty one. If you try to rename a folder from the SharePoint UI sometimes you may get an error saying “The file is currently checked out or locked for editing by another user”. If you enable  the callstack in the Web.config the full stack trace will be something like this:

[COMException (0x81020036): The file is currently checked out or locked for editing by another user.]
   Microsoft.SharePoint.Library.SPRequestInternalClass.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish) +0
   Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish) +411

[SPException: The file is currently checked out or locked for editing by another user.]
   Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish) +556
   Microsoft.SharePoint.SPListItem.AddOrUpdateItem(Boolean bAdd, Boolean bSystem, Boolean bPreserveItemVersion, Boolean bNoVersion, Boolean bMigration, Boolean bPublish, Boolean bCheckOut, Boolean bCheckin, Guid newGuidOnAdd, Int32& ulID, Object& objAttachmentNames, Object& objAttachmentContents, Boolean suppressAfterEvents) +3032
   Microsoft.SharePoint.SPListItem.UpdateInternal(Boolean bSystem, Boolean bPreserveItemVersion, Guid newGuidOnAdd, Boolean bMigration, Boolean bPublish, Boolean bNoVersion, Boolean bCheckOut, Boolean bCheckin, Boolean suppressAfterEvents) +636
   Microsoft.SharePoint.SPListItem.Update() +194
   Microsoft.SharePoint.WebControls.SaveButton.SaveItem(SPContext itemContext, Boolean uploadMode, String checkInComment) +1806
   Microsoft.SharePoint.WebControls.SaveButton.SaveItem() +111
   Microsoft.SharePoint.WebControls.SaveButton.OnBubbleEvent(Object source, EventArgs e) +476
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +50
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +32
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3215

 It turns out that SharePoint will not allow you to rename a folder if there is a file under it which is currently checked out. The trouble is SharePoint doesn’t tell you which is the file.

To find out which is the file you can use SharePoint Designer to rename the same folder. Then the error message returned by SharePoint Designer will include the file name being checked out and the user it is checked out to.

Blog at WordPress.com.