C H A P T E R  3

images

Exploring Feature Basics and Not-So Basics
Getting Down with the Feature Framework of SharePoint

Listen carefully. I shall say this only once...well, I will probably repeat myself endlessly during the course of this book, but I will say it now anyway: use features as much as possible.

There! Said and done. And now you are probably expecting an explanation. OK, I will give you one later, but first let’s take a look at what’s in store for this chapter.

This chapter will show you several aspects of the SharePoint feature framework and make sure we are on a level playing field regarding features. You will learn the basics and a few more advanced techniques of authoring features, and then, oh yes, I will tell you exactly why I think features are more important than water in a desert.

We need to have a starting point for our feature bonanza, so let’s start with something simple.

Creating a Basic Feature in Visual Studio

Creating a feature from scratch is not just a good learning experience; it is downright required in some cases. If you are using tools such as WSPBuilder, Visual Studio Extensions for WSS, or STSDEV, you may be tempted to skip this section. Fine, go ahead, but don’t blame me the day you are given a third-party feature that has an error and you need to debug the files by hand.

If, on the other hand, you choose to use tools only because you have created so many features by hand that you have worn out the F, E, A, T, U, and R keys on your keyboard, feel free to skip ahead and blame whomever you want.

Later in this book I may ask you to create a feature and add something to the elements file. When I say that, here’s what I want you to do:

  1. Create a new project in Visual Studio. I prefer using the class library project since I can attach deployment to the Build actions and then just hit Build to deploy the feature.
  2. Add a new folder to the project, and call it Feature. Then add a subfolder to the Feature folder, and give it a name you like, such as MyFeature. The MyFeature folder will become the feature folder. The reason we add this folder structure is that we will automate copying our feature files into the [12]TEMPLATEFEATURES folder.
  3. Add a new text file to the project, and rename it to setup.bat. We will put our deployment code in this file and run it whenever we build the solution.
  4. Open the project properties, and go to the Build Events tab. In the post-build events, enter the following:
    cd $(ProjectDir)
    setup.bat

    This will automatically run setup.bat when we build our solution.

  5. Open the setup.bat file, and enter the following:
    @SET FEATURES="c:Program FilesCommon FilesMicrosoft Sharedimages
    web server extensions12TEMPLATEFEATURES"
    @SET FEATURENAME=[Your feature name]
    @SET STSADMEXE="c:Program FilesCommon FilesMicrosoft Sharedimages
    web server extensions12instsadm.exe"
    %STSADMEXE% -o deactivatefeature –name %FEATURENAME%–url http://localhost/
    %STSADMEXE% -o uninstallfeature –name %FEATURENAME%
    xcopy Feature /E /Y %FEATUREDIR%
    %STSADMEXE% -o installfeature –name %FEATURENAME%
    Rem %STSADMEXE% -o activatefeature –name %FEATURENAME% –url http://localhost/

    In the previous code, substitute [Your feature name] in line 3 with the folder name you chose in step 2, and substitute http://localhost/ with the URL of your site. Mine is http://lab-s02:10000/ or http://localhost:10000/.

  6. In the MyFeature folder, add an XML file, and name it Feature.xml. Open the file, and add the following code:
    <Feature Id="[Create guid]"
              Title="MyFeature"
              Description="My description"
              Version="12.0.0.0"
              Hidden="FALSE"
              Scope="Web"
              DefaultResourceFile="core"
              xmlns="http://schemas.microsoft.com/sharepoint/">
      <ElementManifests>
        <ElementManifest Location="elements.xml"/>
      </ElementManifests>
    </Feature>

    Substitute [Create guid] with a unique GUID. And yes, you can substitute the Title and Description attributes as well.

  7. Still in the MyFeature folder, add a new XML file, and name it elements.xml. Add the following code:
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    </Elements>

    The actual contents of the Elements element will vary, so leave it empty for now.

That’s it. Using this feature as a template, you should have few problems when you need to create a feature to test something. Oh, and again, if you use tools, most of this may be unnecessary, but you should still know how to do this by hand if required. Now it is time to learn what you just created.

What Are SharePoint Features?

A SharePoint feature is a technical term not to be confused with a feature in the software. Think of a SharePoint feature as a deployable set of content, functionality, files, and so on, that you can activate or deactivate on demand. Think plug-in.

imagesTip The dual meaning of the term feature will be confusing. Prepare yourself.

Site or farm administrators can activate and deactivate these features as they please, thus adding or removing functionality on demand.

The Site Settings page has links for activating site-scoped and web-scoped features. The link for site-scoped feature management, called “Site collection features,” is present only on the root site in a site collection. The link for web-scoped feature management, called “Site features,” is present on all sites. Figure 3-1 shows both.

Application-scoped features cover all site collections and all sites within a single SharePoint web application, while a farm-scoped feature covers everything within a single SharePoint farm. The management of farm-scoped and application-scoped features is done through the Central Administration web site.

Oh, you’re wondering what scope means? I’ll tell you in a little while.

images

Figure 3-1. Feature management links

A feature usually consists of at least two files located in a folder under the [12]TEMPLATEFEATURES folder. Contrary to popular belief, these files do not need to have special names; only convention states that they should be called feature.xml and elements.xml. So, for ease of reference, I will call these files just that.

The first file, feature.xml, contains the metadata of the feature such as the identifier, title, description, and scope. The second file, elements.xml, contains the content of the feature, such as the list instances, fields, list templates, content types, and so on, that the feature is installing or adding.

Features are activated and deactivated through the web interface. You can also activate or deactivate a feature simply by adding the feature definition to the Features collection of an SPWeb, SPSite, or SPWebApplication:

SPWeb web = SPContext.Current.Web;
web.Features.Add([YOUR FEATURE GUID HERE]);

This is useful if you want to create your own interface for feature management or activate multiple features at once using a feature event handler. We will use this technique in Part 3 when we create our own site setup experience.

It may seem logical, based on the previous pattern, that to add farm-scoped features you simply add a feature GUID to the SPFarm object. However, the SPFarm object does not have a Features collection. Instead, the Features collection for a farm is located inside to the SPWebService object. For example, to get the farm-scoped features activated for a given site, you might use the following code:

SPFeatureCollection features = site.WebApplication.WebService.Features;

Although a feature is usually comprised of at least two files, you can in theory have a feature with only a single feature.xml file and no elements file at all. This is useful if you intend to use the mentioned feature event handlers to deploy the actual content of the feature using code.

imagesNote Feature event handlers will be covered in the “Advanced Feature Concepts” section of this chapter.

Now, let’s clear up that scope question of yours.

Feature Scope

Features are scoped, meaning you can have a feature activated at the farm, web application, site collection, or site level. When a feature is activated at a scope, it also affects subscopes, so if you use a web application–scoped feature to add a custom action somewhere, then every site collection and every site beneath the web application will have the same custom action.

It’s a bit confusing, perhaps, but when scoping features, the WSS 2–style names are used. That is, site is used for site collections, and web is used for web sites. This is very strange, especially since features were introduced in WSS 3 and didn’t even exist in WSS 2.

For the sake of being consistent with other information, I will use the WSS 2 names for the scopes, that is, web-scoped, site-scoped, web application–scoped, and farm-scoped.

The scoping of a feature is important, because scoping defines which types of elements can be deployed with a feature. For instance, content types, to be covered more in Chapter 8, make sense only in a site-scoped feature, since content types are stored in the site collection.

This does lead to a bit of a challenge when you want to add a web-scoped list template where you add some custom fields, which are site-scoped. One way to solve this is to have two separate features. You can then use feature activation dependencies to make sure the fields are activated before the list template. You’ll learn more about that a bit later in the chapter.

imagesTip You can find an online table of all feature elements by scope at www.understandingsharepoint.com/url/10025. Or just google feature elements by scope.

Advanced Feature Concepts

Although features can be as simple as adding a list or a field, features offer far more bang for the buck than any other SharePoint...feature. I told you it would be confusing.

The following sections contain some slightly more advanced feature topics for your reading pleasure.

Feature Event Handlers

Another powerful feature of features is the ability to add event handlers directly to the feature so that you can have code executed when the feature is activated, deactivating, installed, or uninstalling. Note the subtle differences in word stemming. The FeatureActivated event happens asynchronously, while the FeatureDeactivating event is synchronous. The events ending in ed happen after the fact, while the ones ending in ing happen during the fact.

To add an event receiver to your feature, you simply add the ReceiverAssembly and ReceiverClass properties of your receiver to the Feature element in feature.xml as such:

<Feature Id="[Create guid]"
         Title="MyFeature"
         ReceiverAssembly="[YOUR STRONG NAME HERE]"
         ReceiverClass="[YOUR CLASS NAME HERE]"
         Description="My description"
         Version="12.0.0.0"
         Hidden="FALSE"
         Scope="Web"
         DefaultResourceFile="core"
         xmlns="http://schemas.microsoft.com/sharepoint/">

Your class should inherit from the SPFeatureReceiver base class. When writing your class, you have access to the site, site collection, web application, or farm on which the feature is activated or is deactivating through the properties.Feature.Parent property. This property returns only an object type, however, so you would need to cast the parent to a class matching the respective scope. For a web-scoped feature (remember, that means it is activated on a site in WSS 3 terms), you could write something like this:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  SPWeb web = (SPWeb)properties.Feature.Parent;
}

Since you have access to the parent object, you can do virtually anything in the event handler itself, including anything you would normally do in the CAML in the elements.xml file such as creating list instances, adding fields or content types, provisioning pages, and so on. In fact, you can usually do plenty more in a feature event handler than you can with a CAML elements file. For example, you can have a feature create subsites or add SharePoint user groups in code, but not in CAML. Creating custom views, however, is one thing you would probably want to do in CAML rather than in code, especially if you are looking to make your views a bit more complex than the default experience.

Feature event handlers are very powerful. As an exercise for yourself, you should try once to do an entire site creation process in code, just to see how the different parts of a site can be created. I will cover the CAML part of site creation in Part 3 of this book and also talk about how you can use code to set up features in a site in Chapter 14.

Feature Activation Dependency

Some features may depend on each other. For instance, you may have a feature to deploy a customer list. That list may be useless unless you have activated a customer management interface through another feature.

You may think that you could put these two features into a single feature, and you might be right. Even if separating features is preferable for the sake of flexibility, tightly coupled features might be put together.

There is another problem, however, and that is the problem of scope. If you are going to add a content type–enabled list to a web, you first need to add the content type, which is site-scoped, and then add the list, which is web-scoped. The problem, of course, is that a feature can have only a single scope, so you are forced to have two separate features.

If you have two separate features, both must be activated for the full feature to work properly. And you need to activate the features in a specific order, lest errors be abundant.

But...was it the content type first and then the list, or was it the list first and then the content type? And even if you can cheat and look back now, how about a year from now, or when you hand over the site to a completely new administrator?

Enter ActivationDependencies—your ticket to activation chain nirvana. By setting one or more activation dependencies, you can make sure that other features are activated before this feature can be activated:

<ActivationDependencies>
  <ActivationDependency FeatureId="CF54600B-0050-4702-BA19-E901653E6FD9"/>
  <ActivationDependency FeatureId="1DF77300-CA9F-4689-BC37-738CD08B6327"/>
</ActivationDependencies>

You can have as many or as few activation dependencies as you like, or you can have none at all.

imagesCaution Avoid circular dependencies, where feature A depends on feature B, which depends on feature C, which depends on feature A. Actually, you might want to try that once, but be warned that it might get messy and you will not be able to activate any of the features.

Resources

Although not strictly a feature-specific technology, resources are very useful for creating dynamic user experiences using features. You may already have seen resources in action; whenever you happen upon a string that looks like $Resources:wss,fldedit_changesitecolumn, you’ll see how resources can be used.

Resources are XML files that contain a key and value mapping, just like a hash table. Because the XML files are separate from the feature or solution, you can change the resource file and thus change which values the keys represent. This is very useful for creating language packs or in any other scenario where you want to have dynamic values.

There are two types of resources: runtime resources, which are just normal ASP.NET resources, and provisioning resources, used in CAML when provisioning sites, pages, lists, and anything else you would provision outside of ASP.NET. Resource management in ASP.NET is outside the scope of this book, but I’ll explain at least the basics of provisioning resources.

To make sure anyone who does not read all the text will be utterly confused, I will from here on refer to provisioning resources only as resources.

Resources, despite being seldom used, are actually quite simple. The format of a resource file is just very simple XML. You have a data element with a name attribute and a child value element. In addition, you can have a child comment element to ease understanding. All this is stored in a root element, conveniently named root. Here is a simple resource file:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="MyKey">
    <value>MyValue</value>
  </data>
</root>

imagesNote Because resource files are very well explained in various ASP.NET books and documentation, I will skip explaining all the various authoring steps.

Features can use such files by referencing the resource file and the key directly in the feature CAML code. Remember that $Resources:wss,fldedit_changesitecolumn string we looked at earlier? This string reference has three parts. $Resources states that we will be using a resource reference rather than a regular string, wss is the first part of the resource file name (such as wss in wss.resx), and fldedit_changesitecolumn is the key name to use.

If you have defined a default resource file, you need not include the file name part of the resource reference, so you can just use $Resources:keyname in your CAML file.

Placing resources is also important. You can place resources either in the feature itself or in the [12]Resources folder. If you place your resources in the feature folder, as we will do in a short exercise in a moment, name the resource file Resources.resx, and set the DefaultResourceFile to _Res to be able to omit the file name part of the resource name.

The true beauty of resources is perhaps in the automatic handling of multiple language localizations. By adding .resx files with the culture between the file name and .resx, Share-Point will automatically use the localized version of the resource file. For instance, if you want to have localized strings for US English and the two Norwegian languages Bokmål and Nynorsk, you could add the resource files listed in Table 3-1 to your feature.

Table 3-1.Sample Resources Files and Cultures

File Name Culture Description
Resources.resx None/default Default file used if no culture defined
Resources.en-US.resx en-US US English
Resources.nb-no.resx nb-no Norwegian Bokmål
Resources.nn-no.resx nn-no Norwegian Nynorsk

imagesNote Yeah, Norway has two languages. Actually, we have four. That is almost one language per person. In addition, everyone learns at least two foreign languages and understands every Scandinavian language. Chances are, if you are in Norway and speak your native tongue, people will understand.

To test all this, follow this procedure:

  1. Create a blank feature, as explained in the first section of this chapter.
  2. In your MyFeature folder, create a folder called Resources, and in that folder create a new resource file called Resources.resx.
  3. Open your Resource.resx file, and add the two keys and values shown in Table 3-2.

    Table 3-2. Resource File Keys and Values

    Key Value
    featuredescription Description from resource
    featuretitle Title from resource

    images

  4. In your feature.xml file, modify the Description attribute to $Resources: featuredescription; and your Title attribute to $Resources:featuretitle;. Modify your DefaultResourceFile attribute to _Res. Your feature element should now look like this:
    <Feature Id="[Create guid]"
              Title="$Resources:featuretitle;"
              Description="$Resources:featuredescription;"
              Version="12.0.0.0"
              Hidden="FALSE"
              Scope="Web"
              DefaultResourceFile="_Res"
              xmlns="http://schemas.microsoft.com/sharepoint/"/>

    For this example, don’t worry about the lack of an elements file. We won’t actually deploy anything; we’re just checking that our resources are used properly.

  5. Build and deploy your feature. If you followed the recipe in the beginning, this should be as easy as hitting Build in Visual Studio.
  6. Verify on the Site Features page of a site that your feature now retrieves its title and description from the resource file.

images

Using resources to provision your string is highly recommended. Besides allowing easy localization of text, you can also very easily upgrade resource files and update names and values without modifying the CAML files. The extra overhead of creating resource files repays itself after the first upgrade of your solution.

Strong buy!

imagesTip Never take stock tips from me.

Feature Stapling

Features can be activated through the web interface or through code, but we also have another powerful option called feature stapling.

Feature stapling allows you to add a feature to an already existing site definition. You may think this would be a complete waste of time, because you can simply add the feature into the site definition using far less code than having a feature staple, but when I tell you that Microsoft does not support modifying a site definition in any way after a single site has been provisioned from that site template, you may reconsider.

That’s right, folks. Write up a fancy site definition, like we will later in the book, and once you have created even a single site from that site definition, Microsoft will refuse to support your solution if you modify a single bit of that definition. So don’t—at least not in production environments.

So, what if you made a mistake and forgot to add a feature or you create a “golden goose” feature that you desperately need in all of your sites? Well, you can always manually activate the feature for all sites. It would just take 30 seconds per site, and with only 10,000 sites that would not set you back more than, oh, the better part of a month?

Or, you could turn to feature stapling. Feature stapling will be discussed in more detail in Chapter 5 when we investigate how to modify the default user experience, but in short, feature stapling allows you to attach a new feature to an existing site definition without modifying the site definition at all.

Combine this with good resource usage, and you can actually do quite a bit of modifying the site definition without breaking your supportability.

imagesNote Feature stapling will be discussed more in Chapter 5, but you need some more knowledge before exploring the details. Keep reading—your patience will be rewarded.

Site Definitions vs. Features

There are two dominant schools of thought when it comes to features and site definitions.

It all comes down to what you put into your site definitions, really. Site definitions are the core building block of new sites; they define the content that will be present when you create a new site. You can add stuff such as lists, libraries, views, pages, folders, and data using nothing but site definitions. In fact, until WSS 3 came along, everything revolved around creating site definitions, because the feature framework did not exist.

That has all changed since the introduction of the feature framework in WSS 3, and we should embrace the change, but as I said, there are two schools of thought on how far that embracing should go. Do we just pat each other on the back to recognize each other’s existence, or should we go all in and French kiss on the first date?

First there are those who think that features are cool, but you can do most of what you want in a site definition. Rather than having to maintain perhaps as much as 20 rather similar features to create different sites, you can put the common denominators in a site definition and save yourself time.

This makes sense if you create one-off sites that are basically similar every time. Consider a specific legal document tracking solution in which all the required functionality is set in stone once the site is created. Why would you want to create features that need to be activated after the site has been created? Even if you could automatically activate the features when the site is created, all you accomplish by moving everything into features is overhead to account for a situation that will never happen.

Reuse is good, and features provide good reuse facilities, but if your requirements are specific enough, chances are your reuse will be limited or nonexistent. And even allowing features to be added could be a problem, since features can modify existing functionality, and in a solution where trackability and accountability is paramount, modifying how data works or is stored is not a good thing.

If you should find out you were wrong to abandon features from the beginning, it is possible to use feature stapling to add a feature to an already existing site definition. Any new site will automatically have your new feature added, and you can always activate features manually for the sites already provisioned.

Then there are those who say that the best site definition is an empty site definition—empty as in absolutely nothing...no pages, no lists, no features, no nothing. Then, use features to put together the site you want, including adding master pages, lists, libraries, and so forth, only after the basic site has been created.

I tend to lean toward the latter method. Features are much more powerful and flexible than site definitions. You can do pretty much everything you can in site definitions using a feature, and what you can’t do directly in a feature can always be done using a FeatureActivated event receiver.

In theory, you could have a single feature activate everything you need for a site, including adding subsites, activating other features, dynamically creating data, and so on. You’d lose the benefit of features, however, since one of the most important reasons to use features is to have granular control over what gets added. You would basically be back at the site definition level.

What most people of the “simple site definition” camp seem to champion is that features should add only what you need. Add a list template as a feature, but add the list instance based on that template as a separate feature. This makes sense from a granularity point of view but means you would have to activate a whole lot of features to get some basic functionality going.

You could balance the two approaches and have “packs” of features. For instance, create a “publishing pack” to add the lists, templates, pages, and content types you need to create functionality for a publishing site. This is what Microsoft does in essence in MOSS. That’s fine if you want the whole pack, but it’s not so fine if all you really want is a useful content type or a page from that pack.

My point here is that you need to weigh the benefits of granularity against the overhead of creating multiple features. There is no clear-cut answer that works in every situation, and the debate of what is better—having multiple features, feature packs, or just sites—is rather pointless from a general point of view. Your best approach is to evaluate the needs of the solution and not be overly religious about one particular point of view.

Featured Finale

Features are cool, features are great, love your features, use them as much as possible.

It may seem strange to recommend building your entire solution based on something that is little more than a plug-in to an existing architecture. However, keep in mind that Share-Point is an evolving technology. The Feature is a great new addition to the version 3 editions of SharePoint; it provides us with a great option for building scalable solutions far better than what was possible in previous versions of SharePoint.

Now that we have gone through this rather short introduction to some basic topics of SharePoint development, it is time to shift focus. Going forward, we will be spending most of our time with the user experience in mind. We want to explore how sites are built and what opportunities await us.

Oh, and there will be dragons and monsters.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.117.207