Provisioning SharePoint Sites with Feature Receivers – Part 1

December 14, 2009 Leave a comment

Developers can create sites in code, users through the UI but do you allow site creation at will? (most companies dread the though of ad hoc site creation and if they don’t, they should). What about site creation in the initial deployment versus ongoing?

I’d like to touch on a specific piece of this, namely site configuration and creation during the initial deployment. Post deployment might be handled with a 3rd party product or custom workflow to gather site requirements, get approval and provision the site. During deployment however, you know which sites you need and which lists etc but simply adding these to a deployment guide and calling it good is limiting not to mention time-consuming. And what about multiple environments, you then have to repeat the same steps moving from dev to qa to staging to prod. Painful even if you’re using various site and list templates and/or site definitions.

The solutions? Feature receivers. This is a bit of a non standard approach and is how I’ve currently been implementing this process though other options such as a console app could work. I’m curious how others have approached this as well. Essentially I build custom features (mainly meant to remain hidden and be used once each) that contain feature receivers that build my sites, lists etc…. Usually features are meant to be reused however the ones I’m creating are specialized feature receivers that only get used once each.

The Process

The process is fairly straight forward. I create all my standard features that I’ll need such as content types, site columns, site definitions, list definitions, page layouts, master pages, event handles, workflows etc… (call these the building blocks so to speak). Next I create a series of features that contain feature receivers that are meant for one purpose and for one time use only. They contain all the code required to create the sites, the lists, the views and the web parts for the initial deployment. I usually also create a separate SharePoint solution containing generic class files, event handlers and application pages that I reuse between my feature receivers.

I then use a set of deployment scripts containing stsadm commands that add and deploy all the solutions, install the features and then activate in a specific order all the features starting with the building blocks, things like site columns and content types and ending with the custom feature receivers that build and confugre the sites. The script can also be used to create the web application and site collection and have a retraction option for reversing the whole process (i.e. deactivate and uninstall all the features, retract and delete all the solutions and delete the site collection/web app).

Note: I break my code up into multiple feature receivers to allow for more flexibility in creating and customizing sites. I also tend to use blank or empty site definitions so that I can build what I need rather than having to delete items.

First I’ll illustrate how we can create SharePoint structure within the feature receiver. I’ll then show a feature Receiver creating a publishing site. 

Site Configuration

Using STSDEV (or whichever tool or manual process you prefer for creating SharePoint features/solutions) I create a web scoped feature with a feature receiver. Next I add code to the featureactivation override. This is what will run when the feature is activated. Note that you can also add code in the feature deactivation override however I’m creating these features with the intent of not having to ever remove them or deactivate them so I expressly don’t add code here. My scripts will create a web app and a site collection with a root blank team site and I’ll activate the feature on this site.

using Generic.MOSS;
namespace ClientSiteConfig
{
  public class FeatureReceiver : SPFeatureReceiver
  {
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
      using (SPWeb currentWeb = properties.Feature.Parent as SPWeb)
        {
          this.customizeSite(currentWeb);
          currentWeb.Update();
        }
    }
  }
...

Generic.MOSS is my generic set of tools I mentioned above. Within this feature receiver in this.customizeSite I’ll add code to create a list and a web part. The following creates a team document library, customizes and adds the My New Content Type (a custom content type) to the library, configures the send to, adds the approve and review workflows and adds it as a web part to the default page.

private void customizeSite(SPWeb currentWeb)
  {
    ///  Document Library
    System.Guid tdGuid = currentWeb.Lists.Add("Team Documents", "", "documents", "00BFEA71-E717-4E80-AA17-D0C71B360101", 101, "101", SPListTemplate.QuickLaunchOptions.On);
    SPList tdDocLib = currentWeb.Lists.GetList(tdGuid, false);
    SPContentType tdType = currentWeb.AvailableContentTypes["My New Content Type"];
    customizeDocLib(tdDocLib, tdType)
    /// custom send to
    tdDocLib.SendToLocationName = "Published Documents";
    tdDocLib.SendToLocationUrl = http://www.company.com/documents";

    /// Approval Workflow
    doclib.AddWorkflow(currentWeb, tdDocLib, "Approve", "Approve", true);
    /// Review Workflow
    doclib.AddWorkflow(currentWeb, tdDocLib, "Collect Feedback", "Review", true);
    /// add check out column to default view
    SPView tdView = tdDocLib.DefaultView;
    tdView.ViewFields.Add("CheckoutUser");
    tdView.Update();
    tdDocLib.Update();

    /// Add as Web Part to default page
    SPLimitedWebPartManager wpm = currentWeb.GetLimitedWebPartManager("default.aspx", PersonalizationScope.Shared);
    ListViewWebPart tdWP = new ListViewWebPart();
    tdWP.ListName = currentList.ID.ToString("B").ToUpper();
    tdWP.Title = "Documents";
    tdWP.ChromeType = PartChromeType.TitleAndBorder;
    tdWP.ViewGuid = tdView.ID.ToString("B").ToUpper();
    wpm.AddWebPart(tdWP, "Left", 1);
  }

customizeDocLib looks like this:

private static void customizeDocLib(SPList currentList, SPContentType currentType)
  {
    currentList.ContentTypesEnabled = true;
    currentList.EnableFolderCreation = false;
    currentList.EnableVersioning = true;
    currentList.EnableMinorVersions = true;
    currentList.EnableAttachments = false;
    currentList.ForceCheckout = true;
    currentList.AllowDeletion = false;
    /// add content type to list
    ContentType.AddToList(currentList, currentType);
    /// remove item default content type
    ContentType.RemoveFromList(currentList, "Document");
    currentList.Update();
  }

Outside the feature receiver (since it’s code I can reuse) doclib.AddWorkflow and ContentType.AddtoList and .RemoveFromList are found in Generic.MOSS and look like this:

public class doclib
  {
    public static void AddWorkflow(SPWeb currentWeb, SPList currentList, string strTemplateName, string strWorkflowName, bool allowManual)
      {
        SPWorkflowTemplate baseTemplate = currentWeb.WorkflowTemplates.GetTemplateByName(strTemplateName, CultureInfo.InvariantCulture);
        SPWorkflowAssociation assoc = SPWorkflowAssociation.CreateListAssociation(baseTemplate, strWorkflowName, currentWeb.Lists["Tasks"], currentWeb.Lists["Workflow History"]);
        assoc.AllowManual = allowManual;
        currentList.AddWorkflowAssociation(assoc);
      }
  }
public class ContentType
  {
    public static void AddToList(SPList list, SPContentType contentType)
      {
        list.ContentTypesEnabled = true;
        list.ContentTypes.Add(contentType);
        list.Update();
      }      
    public static void RemoveFromList(SPList list, string contentTypeName)
      {
        foreach (SPContentType type in list.ContentTypes)
          {
            if (type.Name == contentTypeName)
              {
                list.ContentTypes.Delete(type.Id);
                list.Update();
                break;
              }
          }
      }
  }

Site Creation

The following shows a feature receiver that creates and configures a publishing  site as a sub site of where the feature is activated.

namespace MyNewSite{
  public class FeatureReceiver : SPFeatureReceiver {
    private void createSite(SPWeb currentWeb)
      {
        /// create new Publishing site
        using (SPWeb newSite = currentWeb.Webs.Add("newsite", "My New Site", "", 1033, "CMSPUBLISHING#0", true, false))
          {
            newSite.Navigation.UseShared = true;
            PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(newSite);
            pWeb.InheritCurrentNavigation = true;
            pWeb.NavigationShowSiblings = false;
            pWeb.IncludePagesInNavigation = false;
            pWeb.IncludeSubSitesInNavigation = false;
            pWeb.Update();
            newSite.Update();
          }
      }

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
      {
        using (SPWeb currentWeb = properties.Feature.Parent as SPWeb)
          {
            this.createSite(currentWeb);
          }
      }
    ...

Note that I’ll then create (and activate) a separate feature receiver on this new site to add code for manipulating the lists within the site due to SharePoint’s order of creation. The order seems to be roughly:

  1. On feature activation, FeatureActivated code runs
  2. Code to create a site
  3. Site definition features activate
  4. The feature receiver completes
  5. Site definition applied to site (lists, items, web parts etc… created)

Summary

Pretty much everything you can do through the UI you can do through code (and more) however there are some limitations. For example, manipulating existing web parts through a feature receiver and specifically their views is extremely tricky (I’ve only seen unsupported hacks for this). Configuring other things list a Summary Links Web Part gave me some headaches and I have yet to find a good solution through code.

For the most part though you can create quite complex site structures and lists and web parts (as well as content is desired) through a non standard approach to feature receivers.

In Part 2, I’ll dive in to the deployment scripts that can be used to deploy custom feature receivers in conjunction with building block features.

SharePoint Toolkit Added

December 4, 2009 Leave a comment

Just a quick note. Added a page to list all the useful SharePoint tools I use. There’s links to download them and a description of what they’re useful for.

https://jamesmacesp.wordpress.com/sharepoint-toolkit/

I’ve used all the tools listed and as I come accross new ones that I like, I’ll add them to the list. If there’s any you recommend, let me know, and I’ll check it out.

Categories: MOSS 2007, WSS 3.0 Tags: , ,

SharePoint DevConnections 2009 Post Conference Thoughts

November 23, 2009 1 comment

Vegas and SharePoint (and my birthday) all in one week!

The SharePoint DevConnections 2009 conference was held at the Mandalay Bay hotel in Los Vegas from Nov 8th to 13th (including pre and post workshops). I attended the SharePoint track from Tues to Thurs along with the pre-conference workshop on Performance Point dashboards and scorecards and I must say I was impressed with all of it aside form the content of the workshop.

The pre-conference workshop was a little misleading as it seemed like it would be focused on designing dashboards and scorecards yet it was more of an entire overview of data warehousing, SSIS, SSAS, SSRS and Performance Point with the last hour or so actually spent on design. Which was great since I’m not that familiar with BI and I gained insight into how all the pieces fit together. I think a more descriptive title would have helped.

Other sessions of note:

  • HMS10: SharePoint Development Application Life cycle Management
  • HDV303: Improvements to the SharePoint Developer Story
  • HDV315: Client Side Programming in SharePoint 2010
  • HDV302: Exploring SharePoint as a Service with Improvements in SharePoint Server 2010
  • HIT301: Best Practices for SharePoint Governance and Design
  • HDV301: Exploring Improvements to Enterprise Content Management in SharePoint Server 2010

The majority of these sessions were given by Andrew Connell and Scot Hillier both of whom I’d recommend as presenters/instructors and to attend one of their sessions or courses if you get the chance. The session on best practices and a later session on social networking by Dan Holme were also enlightening.

Getting a look at Visual Studio 2010 specifically the Test Centre was really cool. I had a brief conversation with one of the Microsoft guys on the Visual Studio application life cycle team about extending the test capabilities to UAT scenarios (either through a web based or package solution) however it looks like we’ll have to wait for this. I think this would be a huge enhancement so that not only could you author ALL test cases within Test Centre but you could then get it out of the developers hands and over to the users for the next stage of testing. Even without this feature, the ability to view the recording the of test being performed was very cool.

My new VM with SharePoint 2010 beta is in the works and can’t wait to dive in and explore some of the new enhancements such as the ad-hoc subscription based Service Application Architecture, ECM tools (such as Documents Sets and Metadata Manager Service) and the new Business Connectivity Services (BCS).

Other then that the sessions ran on time and the food was great. The Mandalay Bay is huge and Vegas was fun for the small amount of it I got to see. The week capped off for me with a dinner with Scot and some friends I met at the conference. I would have liked to attend the post conference workshop with Scot Hillier and Andrew Connell however my birthday plans took precedence. I did win a Critical Path Training Webcast however so that makes up for it!

Sessions in SPCONN 2009

November 6, 2009 Leave a comment

Decisions, decisions. Which sessions to attend while at the DevConnections Conference 2009 in Las Vegas next week. There’s so many to choose and all or most seem quite useful.

I’ve decided that rather than double up on topics, I’ll aim for a wider spread of material. While attended topics of the same subject may be useful in gaining a deeper insight as well as multiple points of views form different speakers, I think attending a wider variety of subjects will be more useful. I can then dig deeper into the subjects of interest post conference mayhem.

The only problem is can’t quite cover all the topics. For instance on the 1st day I’ll likely have to skip the Silverlight and Custom Office Solutions in favor of Social Networking and the SharePoint AppDev life cycle.  On the last day I’m having difficulty deciding between Office Document Assembly and SQL Optimizations for SharePoint. You almost need there to be duplicate presentations of all the subjects just to be able to plan to catch them all.

The sessions I know I’ll be attending and am looking forward to are the pre-conference workshop on scorecards, dashboards and BI and the conference sessions presented by Andrew Connell and John Holliday. Both of whom’s blogs I reference quite frequently. I’m really excited about all the new advancements in 2010 and can’t wait to see them in action.

It’s unfortunate that I’m missing the post-conference workshop: Dev deep dive into SharePoint 2010, however it is my birthday that day and I’ll be back in TO to celebrate so it’s not a total loss.

DevConnections Conference 2009 in Las Vegas

November 3, 2009 Leave a comment

So after just missing the SharePoint 2009 conference a few weeks ago (was sold out!), I’m on my way to Las Vegas for the DevConnections conference. I’m looking forward to this for a few reasons.

First, it’s the next SharePoint conference after SPC 09 and there are a few of the same speakers as well as different ones. I’m looking forward to Andrew Connell’s and John Holliday’s sessions as well as the pre-conference workshop from Jessica Moss on Scorecards and BI. I’m hoping I can catch up on what I missed, hopefully dive even deeper into SharePoint 2010 and add to my existing 2007 knowledge base.

Secondly, it’s Vegas. And I’ve never been to Vegas so this should be fun! Though I’ll have minimal time to experience Vegas, I’m hoping I can maybe take in the sights or perhaps a show on the sun before the conference.

Third, this will be my first conference of this size and I’m looking forward to meeting people, attending the sessions and enjoying the experience and taking it all in. I’m hoping I can absorb as much as possible and bring back and digest the rest. I’m also looking forward to what I can bring back to the team here at Buchanan and hopefully enhance their SharePoint expertise as well.

Finally a SharePoint blog!

October 19, 2009 Leave a comment

This has been on my to do list for quite some time now. To create a blog on all things SharePoint.

So now that it’s created I can now start blogging about all the things I have been wanting to blog about but haven’t  as well as anything new that comes along.

It’s a coincidence and a bit of unfortunate timing in that I am not at this years SharePoint conference as I’m writing this however there’s always next year. And the opportunity for many blogs between now and then is great!

Categories: Uncategorized