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.

16 September, 2008

The Id attribute of a ListInstance feature is ignored by SharePoint

Filed under: SharePoint — Tags: , , , — hristopavlov @ 7:22 am

A developer asked me today why SharePoint doesn’t use the Id specified in the ListIntance feature manifest for the guid of the list to be created. I checked the MSDN documentation and found out that the Id should be actually an integer number rather than a Guid: http://msdn.microsoft.com/en-us/library/ms476062.aspx

Looking at the SharePoint code with reflector revealed that the class that is responsible for activating a ListInstance feature is Microsoft.SharePoint.SPListInstanceElement which actually completely ignores the Id attribute. It creates the list the “normal” way and the list instances will always come with a different and unique guids.

internal SPList Microsoft.SharePoint.SPListInstanceElement.EnsureListExists(SPWeb web)

{

    SPList list2;

    try

    {

        return web.Lists[this.Title];

    }

    catch (ArgumentException)

    {

        Guid guid;

        int num;

        string str;

        string documentTemplate;

        SPListTemplate.QuickLaunchOptions off = SPListTemplate.QuickLaunchOptions.Off;

        if (string.IsNullOrEmpty(this.TemplateType))

        {

            return null;

        }

 

     

 

        num = int.Parse(this.TemplateType, NumberFormatInfo.InvariantInfo);

        str = base.FeatureDefinition.Id.ToString();

        documentTemplate = null;

      

        guid = web.Lists.Add(this.Title, this.Description, this.Url, str, num, documentTemplate, off);

        if (!(guid != Guid.Empty))

        {

            return null;

        }

        return web.Lists[guid];

 

    }

}

The Shocking Blue Green Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.