Chapter 8. Web Content Management

WHAT'S IN THIS CHAPTER?

  • Understand how the Publishing Framework supports web content management

  • Develop site columns and content types for Publishing content

  • Develop Page Layouts and Master Pages for Publishing sites

  • Configure Navigation for Publishing sites

  • Customize the Content by Query Web Part

  • Setup and Use Content Conversion in Publishing sites

Web Content Management is a subset of Enterprise Content Management in SharePoint 2010. The conceptual models that we use for defining, administering, and managing enterprise content are equally relevant to web content systems. Whereas Enterprise Content Management systems typically focus on Document and Records management functions, Web Content Management tends to focus on Page management functions. Fundamentally, the approaches between the two are differentiated only in the artifacts that you process.

THE CONTENT LIFECYCLE IN WEB CONTENT MANAGEMENT

Understanding the conceptual models for content management begins with a clear definition of the content lifecycle. The content lifecycle defines the process by which content is created/captured, managed, distributed, and retained. It is a process model that is familiar to most developers because it is related to and mirrors the Software Development Lifecycle that is typically employed in projects.

In SharePoint 2010, creating and capturing content encompasses many different roles and forms. Developers are concerned with the creation of taxonomies in the form of site collections and sites, Information Architecture in the form of site columns and content types, templates in the form of master pages and page layouts, and content retention in the form of lists and libraries. Designers are concerned with the creation of branding, the user experience, and navigation artifacts. Business content owners are concerned with the creation of content, using templates to create the pages that end users view on the sites, and the creation of reusable content artifacts such as text, HTML, and images. Finally, site visitors and members are concerned with the creation of social content through comments, personalization, and rating systems.

Considering the variety of mechanisms that SharePoint 2010 provides to create and capture content in its Web Content Management system, it is important to understand the procedures for managing all of the content channels that are available. In the past, content management was handled by the developers who were the sole gatekeepers of the static pages. Later, management of the content was handed over to the content owners, who used web-based technologies to manage the content that appeared on the pages, while the developers continued to be the gatekeepers of the templates. SharePoint 2010's content management procedures add to the existing model by modularizing the locations of content in the system, allowing each role to manage its own content in the system.

Controlling distribution over a large variety of content sources and management processes is very important. Distribution policies provide a mechanism for determining who will see content, where content is deployed, and when content is available. It is the function of the Web Content Management system to provide mechanisms that allow the content creators to indicate whom content is intended for and when content is valid in the system. The web content system also allows the business to encapsulate all new content within a framework of workflows and governance that manages the variety of content inputs into the system.

Retention policies govern the final phase in the content's lifecycle; as content ages and becomes obsolete in the system, or is no longer published for general consumption because of the dictates of the distribution policy, the retention policies define how content is disposed of in the system. This may include the removal of content from the system, the storage of content in specified libraries or repository locations, or even the movement of content into durable archive systems.

For the SharePoint developer, the content lifecycle is an important conceptual model. This model assists the developer in identifying and using the capabilities that SharePoint offers in support of the content lifecycle. It also assists the developer in defining the components necessary to support the four phases of content life: 1) content types, site columns, and page layouts provide the means to create and capture content in the system; 2) workflows and information policies attached to content types provide the means to manage content as it is created in the SharePoint site; 3) workflows and policies also provide the means to distribute content; and 4) Record Management policies and custom code provide the means to manage the retention of content and pages as they leave the system.

Finally, the content lifecycle helps the developer to identify the taxonomy needed to support each phase of the content lifecycle. The taxonomy represents the logical categorization of content, lists, libraries, and pages in a SharePoint site, which is normally represented in a site model. SharePoint provides the Pages library and reusable content libraries that support the capture/creation of content in the system, but the developer will need to consider other lists and libraries to handle the movement of content through the system at its various stages. Having a view of content as a living entity that is conceptually modeled in a lifecycle helps the developer to understand the system as it grows.

Separation of Content and Development

Web Content Management in SharePoint 2010 includes technologies that allow you to separate the design and development of the website from the content that makes up the website. These technologies give greater control to both IT and business users over the parts of the website that they are most concerned about.

Before the creation of web content systems, websites consisted of static web pages. These pages included styling, layout, and content mingled together. This mingling later included client programming and server programming as technologies advanced and added more capabilities to the systems. In these systems, the pages were developed and deployed to the web by designers and developers.

The challenge of static systems is that the creation of sites and pages is a burdensome process whereby business stakeholders provide content to the developers, who in turn integrate the content into the design and programming of individual pages. Testing and approval of sites and pages was equally burdensome because it included an additional step of getting business sign-off on the content. In some organizations, this included the involvement of legal departments.

SharePoint 2010 addresses the issues of static site development by separating the three main roles of actors in website creation: Designers, Authors, and Approvers. SharePoint allows Designers/Developers to leverage the software development techniques and lifecycle that they are familiar with to create web assets and templates that are independent of business content. Authors are able to use these assets and templates to create sites and pages, focusing only on the content of the pages. Finally, the deployment of designed assets and content is managed by version control mechanisms and approval workflows that allow Approvers to review assets and content independent of the creation process.

The Important Role of Information Architecture

Information Architecture provides the conceptual models that facilitate Web Content Management and mediates the activities and roles of the Designers, Authors, and Approvers. It is the information architectural model that informs the development of templates and workflows, and the creation of lists and libraries; and provides an overall framework for user interaction within the system.

The development of Information Architecture in SharePoint tends to begin with the development of the site's hierarchy. The hierarchy provides a common model that is understandable by designers, developers, content authors, and business stakeholders. When developed visually with a tool such as Microsoft Visio, the hierarchy is solidified in the minds of the team and provides a basis from which to develop the remaining assets in the taxonomy.

Working with a model of the site's hierarchy, the designers and content authors begin to separate the components of the site's Information Architecture into asset categories, such as site columns and content types, that can be subjected to detailed design. This will result in design documents or models that identify page layouts needed for content authoring; content types and site columns needed to support the layouts; Master Pages, style sheets, and images needed for branding; lists and libraries to store content; and web parts to display content aggregations.

As well as identifying the necessary assets that make up the web content system, the hierarchical model will demonstrate the important distinction between the physical hierarchy and the user experience through navigational constructs. Using SharePoint's built-in navigational components and web parts, designers can achieve an effective navigational structure that is independent of the physical location of lists, libraries, sites, and pages.

Time spent developing complete Information Architecture models for a SharePoint web content system will ensure a robust and effective implementation. Poor planning will result in unanticipated changes to underlying components of the system, which will often lead to excessive refactoring in the site, such as changes to content types that are in use requiring additional effort to deploy, or changes to the data types of site columns that affect code in the page layouts. More than anything else, a solid Information Architecture will spare you many headaches.

FOUNDATIONS OF WEB CONTENT MANAGEMENT

SharePoint Server 2010 implements Web Content Management using the Publishing Site features. These features, when activated, add SharePoint components that enable Web Content Management on the site. These components include Master Pages, layout pages, content types, reusable content lists, and custom actions.

Activating the Publishing Features

SharePoint Server 2010 provides two site templates that activate the Publishing features during site provisioning: Publishing Portal and Enterprise Wiki. The Publishing Portal template is a generic template that you can use as a foundation for both internal and public-facing publishing sites. The template provisions a site that contains a single home page with a few instructional notes included in the Page Content field and the Publishing features activated. The Enterprise Wiki site is a specialized intranet site that implements wiki-based publishing.

The Publishing features are not limited to the two templates that are available during site creation; they can be activated on any existing site. To enable the Publishing features on an existing site, activate the Office SharePoint Server Publishing Infrastructure feature in the site collection features list (Site Actions

Activating the Publishing Features

Note

When enabling the Publishing feature manually, the Site Collection feature must be activated before the Site feature, because the Site feature has a registered dependency on hidden features that are activated by the Site Collection Publishing feature.

Publishing Feature Components

Activating the Publishing features in your site provisions a number of components, which include site columns, content types, layouts, Master Pages, and lists. It also makes a number of changes to the way in which the sites work by applying workflows, limiting provisioning, and adding publishing-specific permission groups. Taken together, these components implement Enterprise Content Management methodologies.

The Pages library is the document library that provides the document management functionality for all web pages in the managed site. As authors create pages using the Page Layouts, the completed pages are saved to this library. The library manages the publishing process by implementing two key components of content management. First, the pages in the library are subject to versioning with check-in/check-out support. Authors check out web pages to collaborate on the content of the web page and check in changes as they are completed. The checked-in changes are saved as minor versions of the web page that are not visible to the public until the page is published as a major version and approved by a content approver.

The second key component implemented in the Pages library is the application of an optional approval workflow that is automatically launched when a content author publishes a major version of a web page. When the author clicks the Publish button on the Ribbon or uses the actions menu in the Pages library, the workflow will launch the Start Workflow page, which prompts the author to enter some basic workflow information. This is a parallel approval workflow that ensures controlled publication of content to the site.

Besides adding document management capability to the web pages in the site, the Publishing features also provide controls over the look and feel of the site using Master Pages, Page Layouts, and Cascading Style Sheets, which allow designers to manage branding of the site as well as the templates that are available to content authors. Using the Page Layout and Site Template settings page (Site Actions

Publishing Feature Components

The Publishing framework differentiates content authors, content approvers, and designers/developers by implementing an Approvers group and a Designers group; it leverages the Members group for authors. The Publishing features implement these groups in the libraries and workflows that are created during the provisioning process.

Page Processing Model

When a site visitor requests a page, SharePoint combines content and templates from the site to render the final page. SharePoint begins by retrieving the requested page from the Page library. This provides SharePoint with the metadata that identifies the web page, as well as the content that the author entered into the page. Next, SharePoint retrieves the Master Page and the Layout page from the Master Pages and Page Layouts gallery. SharePoint determines the correct page layout by examining the content type of the requested web page. Finally, SharePoint combines the Master Page, Layout page, and content into a rendered HTML page that it sends back to the end user's browser as shown in Figure 8-1.

Figure 8-1

Figure 8.1. Figure 8-1

There is an important relationship between the templates and content that is defined by content types, as shown in Figure 8-2. The content type is a container for the site columns that define the content and metadata for the web pages. As the container for this information, the content type acts as the glue between the content and the templates. The content type is assigned to both the template and the Pages library. This allows the template to use placeholders that align to the site columns, and it allows the author to use the template within the site.

Figure 8-2

Figure 8.2. Figure 8-2

Site Columns

Site columns are an important part of the Publishing framework because they represent content and metadata in the site's web pages. Site columns do not actually contain the content of the web page — that is the function of the list or library that houses the site column. Rather, the site column defines the data format of the content contained in the list or library.

Site columns are used in two distinct ways in a Publishing site. First, the Pages library uses the site column definition to store content and metadata about the page. In this way, the Pages library uses site columns consistently with all other lists in SharePoint. The second way in which site columns are used is as placeholders for content in layout pages. Authors enter content into content locations specified by the designer. The designer makes these content placeholders available by associating the placeholder with the site column. It is this match between the field placeholder and the site column in the Page library that allows SharePoint to save content to the library as well as to retrieve it for page rendering.

The challenge to working with site columns in a Publishing site is differentiating between site columns that define content storage fields in a list from site columns that define metadata content that helps to identify the content container. For example, the Scheduled Start Date field of a Publishing Article page is a metadata field that describes when the page should be published. The Page Image field is a content storage field that holds the URL to an image that will appear with the article text on the rendered web page. Some fields represent a gray area between content and metadata, in particular the Title field, which is metadata for the page but is also the HTML title tag content that appears in the browser's window caption.

As a developer, creating site columns that will represent metadata and site columns that will represent web page content is identical; SharePoint makes no differentiation between the usage models for the site columns. The differentiation becomes important when you begin developing layout pages that provide the input fields to the author. Considering the difference at this stage will save you time and debugging later in the development process.

Browser-Based Site Column Development

SharePoint 2010 allows designers to define site columns from the browser-based site settings interface (Site Actions

Browser-Based Site Column Development

To create a site column, execute the following steps:

  1. Click the Create button at the top of the Site Column Gallery listing.

  2. Enter the Name, Type, Group, and Additional Column Settings for the site column.

  3. Optionally, SharePoint 2010 adds the ability to include validation logic for each site column.

Browser-based site column development presents three substantial problems for the developer. The first is limited portability of the site column definition. When created by the browser interface, the site column is added directly to the site's content database. In cases where it is necessary to define a site column across many site collections, the designer will need to define the site column in each site collection. For enterprises that use multi-staged environments, this means that the site column will need to be created many times, which is an error-prone approach. Finally, site columns defined in the browser limit the ability to upgrade solutions that rely on the browser-created column, such as content type definitions and list definitions.

The second substantial problem with the browser-based approach to site column development is the lack of source control that is typical in most development shops. This makes differentiating custom site columns from SharePoint-defined site columns difficult. It is equally difficult to track changes over time, a task that is normally managed using a source control system such as Team Foundation Server.

Finally, the site column definition page does not differentiate between the internal name of the site column and the display name; rather, it presents only the display name and uses that value as the internal name. This results in what is known as the "space problem." The internal name for a site column cannot contain space characters; therefore, when SharePoint saves the site column in the browser interface, it will replace each space in the name field with the value _x0020_. This creates problems later when you reference the name in a Content Query web part or in your source code. The workaround in the browser interface is to create the site column with no spaces in the name, save it, and then edit the site column to add the spaces back into the name. This will cause SharePoint to save an internal name without spaces and then update the display name with spaces.

Feature-Based Site Column Development

Using a SharePoint Feature is the most common approach to developing site columns for a solution when the developer wants a source control-manageable code file. The developer uses Collaborative Application Markup Language (CAML) to define Field elements in the Feature's Elements file. When the Feature is activated within a site collection, all of the fields defined in the Elements file are deployed to the site collection as site columns.

Visual Studio 2010 includes improved integration and tools for SharePoint development that makes the process of creating a SharePoint Solution and Feature to hold site columns easier than in the past. Although Visual Studio 2010 does not include a specific template to create site columns, it does include a blank template that will allow you to add site columns to the Feature's Elements file.

To develop a CAML-based site column in Visual Studio, create a new project (File

Feature-Based Site Column Development

Note

When you create a SharePoint project in Visual Studio 2010, it will change your Framework target for you. You can see this if you open the project properties dialog and look in the Target framework selection. It will read 3.5 even if you had 4 selected in the New Project dialog. I also noticed that if you select 2.0 or 3.0 in the New Project dialog, all of the SharePoint project templates disappear.

The following example presents a web content management solution for a Human Resources department. The purpose of the solution is to allow Human Resources personnel to add web pages to the site that provide benefits information to employees. The following site columns provide metadata and content for page instances in the Human Resources site. Later the sample will add Content Types that will be tied into the Page Layouts.

Figure 8-3

Figure 8.3. Figure 8-3

SharePoint 2010 introduces the concept of Sandboxed Solutions. These are solutions that can be deployed to a specific site collection as a user solution and are managed in the Solutions gallery (Site Actions

Figure 8-3

Note

If you opt to deploy as a sandboxed solution and would like to change to a farm solution later, you may do so by selecting the project in the Visual Studio Solution Explorer, then change the Sandboxed Solution property in the Properties pane to False.

Visual Studio 2010 creates a new project that includes references to Microsoft.SharePoint.dll and Microsoft.SharePoint.Security.dll. It is strongly named and includes two special folders specific to SharePoint projects: Feature and Package. The Feature folder represents the SharePoint Features included in this project. The Package folder represents the SharePoint Solution which is compiled into a WSP file that will deploy the Features to the designated solution store.

Figure 8-4

Figure 8.4. Figure 8-4

The Empty SharePoint Project template does not include any Features in the Features folder. To add a new Feature to this project, right-click the Features folder, and click Add Feature. This adds a new Feature component to the folder; double-click the Feature1 icon in Solution Explorer to modify the Feature's metadata using the Feature designer as shown in Figure 8-5. The Title and Description values appear on the Features pages in Site Settings. It is a good idea to make these values descriptive so that administrators will know what they are adding to the site when they activate the feature.

Figure 8-5

Figure 8.5. Figure 8-5

The feature's scope determines where the feature can be activated within SharePoint. There are four possible scopes that you may select for a feature:

  1. Farm: Activates a feature for the entire SharePoint farm and is available in Central Administration.

  2. WebApplication: Activates a feature for all sites in a web application and is available in Central Administration.

  3. Site: Activates a feature for all sites in a site collection and is available in Site Collection Features in the site collection root site's site settings.

  4. Web: Activates a feature for a web site and is available in Site Features in the web's site settings.

Certain components, such as site columns, content types, Master pages, and Page Layouts, are installed at the site collection level and made available to all sites within the collection. These components require that the scope for the feature be set to "Site."

Next, add a new item to the project (Right-click project name

Figure 8-5
Figure 8-6

Figure 8.6. Figure 8-6

The Empty Element template is an XML file where you can enter CAML Field definitions. The following example shows the CAML definition for site columns. The DisplayName, Description, and Group attributes define the values that display in many of the browser-based interfaces including the site column gallery, and site column pickers in List properties. The type attribute indicates the data type of the site column; the available data type values are documented in the CAML section of the MSDN library.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Field ID="{76C140E1-D827-433B-AD38-257F9594B846}"
         Name="BenefitProvider"
         DisplayName="Provider Name"
         Group="Human Resources"
         Type="Text"
         Required="FALSE"/>
  <Field ID="{A1758D70-B479-469C-90BB-C3038ED42B15}"
         Name="BenefitProviderLogo"
         DisplayName="Provider Logo"
         Group="Human Resources"
         Type="Image"
         Required="FALSE"/>
  <Field ID="{5F516D92-969C-4661-81B9-C9210E2A2FDC}"
         Name="BenefitType"
         DisplayName="Benefit Category"
         Group="Human Resources"
         Type="Choice"
         Required="FALSE">
<CHOICES>
      <CHOICE>Medical</CHOICE>
      <CHOICE>Dental</CHOICE>
      <CHOICE>Vision</CHOICE>
      <CHOICE>Insurance</CHOICE>
    </CHOICES>
  </Field>
  <Field ID="{521D5F12-16BC-4E82-997C-F28933ABE59E}"
         Name="BenefitDescription"
         DisplayName="Benefit Description"
         Group="Human Resources"
         Type="HTML" RichText="TRUE" RichTextMode="FullHtml"
         Required="FALSE"/>
</Elements>
Figure 8-6

Note

Because CAML provides attributes for both the DisplayName and Name, you avoid the "spaces problem" that the browser-based interface presents. Using CAML, you can define a Name field that does not contain spaces; however, if you place spaces in the Name attribute, then SharePoint will save the name with the _x0020_ string as it does with the browser-based approach.

To deploy the Site Columns defined in the Elements file, right-click the project name in the Visual Studio Solution Explorer, and select Deploy. This will deploy the solution file to the solution store and activate the Feature in the targeted site collection. You can validate the installation of your site columns in SharePoint Designer or by viewing the Site Columns gallery in the Site Settings of the target Site Collection.

Feature-based site column development also avoids the problems of portability and synchronization of browser-based development. Using a SharePoint Solution for deployment, a feature can be installed across multi-stage environments with minimal effort. Portability becomes a matter of site administration and feature management. Features also ensure that site columns across environments remain synchronized in their metadata, eliminating the possibility of misspellings.

Object Model-Based Site Column Development

Using the SharePoint object model is a very powerful method for implementing site columns in SharePoint, as well as other SharePoint customizations. The object model is also a more familiar model to seasoned .NET developers who prefer to work with code rather than CAML. Finally, the object model provides additional flexibility for the developer, because it allows the creation of assets from entry points other than SharePoint Features, such as Application pages and .NET applications.

The most significant problem with developing site columns in CAML occurs when you are modifying or enhancing a Feature that has already deployed site columns into the site collection. In this situation, site columns are often assigned to content types and/or lists and may have data in place. Because the CAML feature does not validate the contents of the site, it may experience problems or cause exceptions when you attempt to upgrade the Feature.

Using object model code in a feature Receiver will allow you to perform validation on your site and additional data-massaging work before upgrading your Feature. Also, you have the option to include the definition and creation of the site columns in object model code rather than in CAML, in which case your Feature may consist solely of a receiver with no elements file attached.

Creating Site Columns in code using a Feature Receiver in Visual Studio 2010 is very similar to creating a CAML feature to create site columns. Create a new project (File

Object Model-Based Site Column Development
Figure 8-7

Figure 8.7. Figure 8-7

Rather than add the Empty Elements, right-click on the Feature in the Features folder and select "Add Event Receiver" from the drop-down. This will add a class under the .Features folder in Solution Explorer as shown in Figure 8-7.

The Visual Studio–generated class contains commented override methods for each of the Feature's events. Uncomment the methods you wish to add code to and add the code. In this example, the FeatureActivated method will create two site columns and add them to the site collection.

public override void FeatureActivated(SPFeatureReceiverProperties Sproperties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    using (SPWeb web = site.RootWeb)
    {
      try
      {
        string benefitsDescription = web.Fields.Add(
          "Benefits_Description", SPFieldType.Note, false);
        string benefitsYear = web.Fields.Add(
          "Benefits_Year", SPFieldType.DateTime, false);
        web.Update();

        SPField benefitsDescriptionField = web.Fields[benefitsDescription];
        benefitsDescriptionField.Title = "Description";
        benefitsDescriptionField.Description = "Describe the benefits document";
        benefitsDescriptionField.Group = "Human Resources";
        benefitsDescriptionField.Update();

        SPField benefitsYearField = web.Fields[benefitsYear];
        benefitsYearField.Title = "Year";
benefitsYearField.Description = "Year the benefits document is valid";
        benefitsYearField.Group = "Human Resources";
        benefitsYearField.Update();
      }
      catch (Exception ex)
      {
        Console.Write(ex.ToString());
      }
    }
  }
}
Figure 8-7

The code begins by connecting to the site collection using the properties of the Feature rather than using the SPContext class. The SPContext class will return a reference to a site collection only when the code is running within a SharePoint site; otherwise, no context exists. In the case of a Feature, a system administrator may not be using the Site Settings pages to activate Features; rather, she may be using a command-line script to activate the feature, in which case there is no SharePoint context. Therefore, FeatureActivating methods should use the Feature's properties to get the site collection.

The root web of the site collection contains the collection of SPFields (site columns) defined in the site collection. To create a site column in code, simply use the collection's Add method to define a new site column. The first argument is the name of the site column, the second is the data type, and the last flags whether the site column is required. A call to the SPWeb's Update method saves the site column to the site collection.

To configure additional attributes of the site columns, you need to reference each one, modify its properties, and update it. If this code is in the same method that you created the site column, getting the reference is easy because the field collection's Add method returns the internal name of the site column as a string. Using this string, you can instantiate an SPField object with a reference to the internal name. Finally, modify the site column's properties and call the Update method to save the completed site column.

Unlike site columns defined using CAML, when this Feature is deactivated, it does not remove the site columns from the site collection. To add this behavior, you need to override the FeatureDeactivating method and add code to remove the site columns that you created in code.

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
  if(properties.Feature.FeatureDefinitionScope != SPFeatureDefinitionScope.Site)
  {
    throw new Exception("This feature must be a 'Site' feature");
  }
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    using (SPWeb web = site.RootWeb)
    {
      try
      {
web.Fields["Benefits_Description"].Delete();
        web.Fields["Benefits_Year"].Delete();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
Figure 8-7

This simple example replicates the behavior demonstrated in the CAML code; however, it could easily include code that iterates through the lists in the site collection and that cleans up existing data that might be using these site columns. The code could also create lists, content types, or other related assets that are necessary to the web content solution.

Content Types

Content types are a conceptual container for content and processes in the system. They encapsulate metadata in the form of site columns, and functionality in the form of information policies and workflow. In a publishing site, content types are a bridge between the content-holding site columns and the template-oriented Page Layouts. Without a defined content type, SharePoint has no way of associating a page layout with the content contained in the Pages library.

Note

It is important to remember that you will both assign the content type to the Page Layout and add the content type to the Pages library.

Understanding Content Type Ids

Before you can develop a content type for any use in SharePoint, you must understand how Content Type IDs work. Unlike all other elements in SharePoint where the ID value is a GUID that identifies the element to SharePoint, the Content Type Id also contains hierarchical logic that identifies where the content type exists within the system.

Every content type in SharePoint must inherit from a parent content type. Similar to object inheritance in code, content types inherit all site columns, workflows, and information policies from their parent content type.

There are two approaches to defining Content Type Ids: the Hex approach and the GUID approach. The Hex approach defines a Content Type Id by adding a two-digit Hex value other than "00" to the end of the Parent's Content Type Id. The GUID approach adds the value "00" followed by a GUID (with all special characters stripped out) to the Parent's Content Type Id.

Hex: [Parent Content Type Id] + [2-digit Hex value]

GUID: [Parent Content Type Id] + 00 + [GUID with no {} or - characters]

For example, suppose you create a content type for an HR Benefits Document that inherits from the Document content type. Using the Hex approach would result in a Content Type Id that begins with the Document Content Type Id "0x0101" followed by a two-digit hex value "03."

Hex: 0x010103

Using the GUID approach for the same content type would also begin with the Document Content Type Id "0x0101" but it would be followed by "00" and then a GUID that is stripped of special characters "24CB1116BE6D49e9B482D492532921F2."

GUID: 0x01010024CB1116BE6D49e9B482D492532921F2

Note

There are three approaches to finding the Content Type Id of a parent content type. First, you can open the content type properties page from the Content Types gallery and then look in the page URL for the ctype attribute. Second, you can go into the Features folder of the SharePoint Root in Windows Explorer and open the Elements file, where the content type is defined. Finally, if you have SharePoint Designer 2010, it contains a Content Type section that will show the properties of every content type in your site, including the ID.

The best practice recommended by Microsoft is to use the GUID approach to define all custom content types in the system. The GUID approach avoids collisions between Content Type Ids that can occur with the Hex approach if the Hex values are not carefully managed by designers of the system. For example, the Hex value provided in the above example "03" for the Benefits Document is acceptable because it is not one of the out-of-the-box Ids; however, a quick look at the SDK documentation in the "Base Content Type Hierarchy" shows that there are a number of out-of-the-box types using neighboring hex values. It would be easy to collide with some of the Microsoft defined content type Ids.

Despite the recommendation, Content Type Ids are limited to a 1024 character size. Given a deep content type hierarchy, you can quickly run out of space for defining a Content Type Id. In these situations, you will need to use an approach that mixes both methods. You will begin with the GUID approach to inherit from the Parent Content Type, which results in a "base" content type that acts similarly to a namespace in code. Then, you will switch to a Hex approach to define internal children types.

Browser-Based Content Type Development

SharePoint provides a browser-based approach to creating content types that is similar to creating site columns in the browser (Site Actions

Browser-Based Content Type Development

After SharePoint creates the content type, it will display the Content Type properties page rather than redirect you back to the Content Type gallery. The Content Type property page provides the links and capabilities to add additional site columns to the content type, as well as to add, modify, or delete workflows and information policies.

Browser-based content type development suffers from the same portability and source management issues that browser-based site column development presents. SharePoint 2010 introduces a content management capability called Enterprise Content Types that will automatically publish content types across site collection boundaries within a SharePoint farm. This is a very powerful feature that merits close examination in your solutions; however, it does not work across multi-environment settings. Likewise, Enterprise Content Types do not provide any form of source control for content type definitions in your development lifecycle. Even when you use Enterprise Content Types, you should still define the content type with either the Feature or object model approaches.

Feature-Based Content Type Development

Feature-based content type development works within the SharePoint Solution and Feature framework in exactly the same way that feature-based site column development works. The content type is defined in the Feature's Elements file using CAML. Because content types are containers for custom site columns, it is a common practice to define the custom site columns at the top of the elements file and then define the custom content types at the bottom. This enables you to deploy both the site columns and their containers in one SharePoint Feature.

Visual Studio 2010's SharePoint tools include a template for content types that provides the basic framework for defining a content type in CAML. To begin creating a content type, create a new project (File

Feature-Based Content Type Development
Figure 8-8

Figure 8.8. Figure 8-8

Next, Visual Studio will ask you to select the Parent Content Type. When creating a content type to use with a page layout, you must inherit from one of the page layouts, as shown in Figure 8-9.

Figure 8-9

Figure 8.9. Figure 8-9

Visual Studio 2010 creates a CAML-based definition for the content type, including a Content Type Id that uses the GUID method. An added benefit is that it includes the parent's ID as a comment for easy reference. In most cases, you will want to modify the generated metadata values to content that is more fitting to your Information Architecture.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Article Page (0x010100C568DB52D9D0A14D9B2FDCC96666E9F200
  7948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D) -->
  <ContentType ID="0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219
  954237AF3900242457EFB8B24247815D688C526CD44D007b07c2cdb6004430bfd2fe7a3eff5ecb"
               Name="Benefits Information Page"
               Group="Human Resources"
               Description="Benefits Information page layout content type"
               Version="0">
    <FieldRefs>
    </FieldRefs>
  </ContentType>
</Elements>
Figure 8-9

To complete the content type definition, add field references within the <FieldRefs></FieldRefs> element. Each field reference element will associate a site column with the content type. Note that it is not necessary to include field references for fields inherited from the parent content type.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Article Page (0x010100C568DB52D9D0A14D9B2FDCC96666E9F200
  7948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D) -->
  <ContentType ID="0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219
  954237AF3900242457EFB8B24247815D688C526CD44D007b07c2cdb6004430bfd2fe7a3eff5ecb"
               Name="Benefits Information Page"
               Group="Human Resources"
               Description="Benefits Information page layout content type"
               Version="0">
    <FieldRefs>
      <FieldRef ID="{76C140E1-D827-433B-AD38-257F9594B846}"
        Name="BenefitProvider"/>
<FieldRef ID="{A1758D70-B479-469C-90BB-C3038ED42B15}"
        Name="BenefitProviderLogo"/>
      <FieldRef ID="{5F516D92-969C-4661-81B9-C9210E2A2FDC}"
        Name="BenefitType"/>
      <FieldRef ID="{521D5F12-16BC-4E82-997C-F28933ABE59E}"
        Name="BenefitDescription"/>
    </FieldRefs>
  </ContentType>
</Elements>
Figure 8-9

The challenge presented with this example is that the content type definition references site columns that are defined in a separate Feature. If the other Feature is not activated first, SharePoint will display an error page when you attempt to run this project. There are two ways to deal with this challenge. The first is to modify the Feature definition to add a Feature dependency between the two Features.

In Visual Studio 2010, adding a Feature dependency is very easy, especially if the Feature is already installed on your targeted SharePoint site. To add the dependency, open the Feature Designer by double-clicking the Feature in Visual Studio's Solution Explorer. At the bottom of the Designer, expand the section at the bottom labeled "Feature Activation Dependencies," then click the Add button to add the dependency. Visual Studio shows a list of the Features installed in the target SharePoint site as shown in Figure 8-10.

Figure 8-10

Figure 8.10. Figure 8-10

You can select one or more of the installed Features to make this Feature dependent. You also have the option to enter the Feature information for dependencies that you have not installed on the target SharePoint site. After you click Add, the Feature will be updated to include the dependencies as shown in Figure 8-11.

Figure 8-11

Figure 8.11. Figure 8-11

The second way to deal with the dependency created by this content type definition is to refactor the Features so that the site columns are included in the same Feature as the content type. This is a matter of either cutting and pasting the Site Column CAML into the content type's Elements file or adding the Site Column Elements file to the current project.

Object Model-Based Content Type Development

As with site columns, you can create content types using the SharePoint object model. The object model provides the flexibility to develop content types with .NET applications, application pages, web parts, and Feature Receivers using a code-based approach.

The most significant challenge when working with content type occurs when business needs necessitate a change to the structure of existing content types. This may be the addition or subtraction of site columns, the inclusion of a workflow, or modification of other elements that content types may contain. If the content type is in use by a list or content, then you will not be able to deploy your modifications.

Object model code provides you with the means to develop mechanisms that will not only deploy updated content type definitions, but also manage existing content. In these cases, a Feature Receiver can iterate through the site to find content and lists that are using a content type, extract those components from the site, modify the content type, and reinsert the content. These procedures are code-intensive and beyond the discussion of Web Content Management, but understanding the basic concept of content type development with the object model will help you deal with upgrade situations when they arise.

To create a content type using object model code and a Feature Receiver, create a new Visual Studio project (File

A NOTE ABOUT TERMINOLOGY

In this example, uncomment the FeatureActivated and FeatureDeactivating methods to include code that will create a content type and remove it when the Feature is activated and deactivated, respectively. Creating a content type in object model code takes three distinct steps that mirror the three steps we followed in the CAML approach: define the parent, create the content type, and add additional components.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    using (SPWeb web = site.RootWeb)
    {
      try
      {
SPContentType parentType = web.AvailableContentTypes["Document"];

        SPContentType contentType =
          new SPContentType(parentType, web.ContentTypes, "Benefits Document");
        contentType.Group = "Human Resources";
        contentType.Description = "Benefits documentation and forms";

        web.ContentTypes.Add(contentType);
        web.Update();

        SPField descriptionField = web.AvailableFields["Benefits_Description"];
        contentType.FieldLinks.Add(new SPFieldLink(descriptionField));
        SPField yearField = web.AvailableFields["Benefits_Year"];
        contentType.FieldLinks.Add(new SPFieldLink(yearField));

        contentType.Update();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    using (SPWeb web = site.RootWeb)
    {
      try
      {
        SPContentType contentType = web.AvailableContentTypes["Benefits Document"];
        contentType.Delete();
        web.Update();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
A NOTE ABOUT TERMINOLOGY

This example begins by getting a reference to the Parent content type, using the AvailableContent Types collection. In this case, the content type will inherit from the document type. The next section of the code creates an instance of SPContentType, passing in the parent content type, the collection that the content type will be added to, and the name of the content type. You can set other properties of the content type such as Group and Description in the next few lines. Finally, the content type is added to the ContentTypes collection of the root web, and the web is updated to save the content type.

The last step in the process is to add the associated site columns to the content type and update it with those changes. The code retrieves each site column from the AvailableSiteColumns collection in the root web. The site columns are added to the content type as SPFieldLink objects that are added to the FieldLink collection in the content type. Finally, the Update method saves the changes to the content type.

As with the CAML-based approach, using existing site columns sets up a Feature dependency that can be handled in the same way as in the previous example, by setting a dependency in the Feature or by including the site column code in this receiver. An additional option available to object model code is to include validation methods that will look for the site columns in the site collection and either activate their Features from code or create them from code.

Client Object Model-Based Content Type Development

SharePoint 2010 includes a client object model that will allow your code to run on a separate server or workstation. This model supports building .NET forms and console applications, as well as WPF, Silverlight, and EMCA script applications. Client object model code operates through a set of classes that represent objects on the SharePoint server rather than interacting directly with the concrete objects as the object model does. This means that you need to establish a connection to the SharePoint server and load the objects that you need into the client application in order to access them.

Initially, this may appear to be more cumbersome than necessary to accomplish the same task as the server object model; however, the client object model opens up some interesting possibilities for Web Content Management. Because the client application does not need to run on the SharePoint server, the designer/developer can set up an authoring environment that is separate from content authoring environments, adding more modularization to the topology.

To create a content type using the client object model in Visual Studio 2010, create a new project (File

Client Object Model-Based Content Type Development
Figure 8-12

Figure 8.12. Figure 8-12

After the project starts, you will add references to the Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll assemblies located in the 14ISAPI folder (also listed under the .NET component listing in the Add References dialog box. Next, you will add code to the Main program that will make the connection to the site collection. Because client object model code can run externally to the SharePoint application server, it works through a ClientContext object. The ClientContext object provides access to objects in the site collection, but they must be explicitly loaded into the context in order to code against them.

static void Main(string[] args)
{
  // Get a reference to the site collection
  ClientContext clientContext = new ClientContext("http://sp2010");
  Web web = clientContext.Web;

  // Load reference to content type collection
  ContentTypeCollection contentTypes = web.ContentTypes;
  clientContext.Load(contentTypes);
  clientContext.ExecuteQuery();
}
Figure 8-12

Unlike server object model code, in which you can create an instance of the SPContentType class and add it to the ContentTypes collection, client object model makes use of an Information class that contains the template of the content type. The information class works in a similar manner to the SPContentType class with the exception of the parent's reference; rather than pass in a reference to the parent's content type, client object model code gets the parent's ID.

static void Main(string[] args)
{
  // Get a reference to the site collection
  ClientContext clientContext = new ClientContext("http://sp2010");
  Web web = clientContext.Web;

  // Load reference to content type collection
  ContentTypeCollection contentTypes = web.ContentTypes;
  clientContext.Load(contentTypes);
  clientContext.ExecuteQuery();

  // Create a Content Type Information object
  ContentTypeCreationInformation benefitArticleInfo =
    new ContentTypeCreationInformation();
  benefitArticleInfo.Name = "Benefits Article";
  benefitArticleInfo.ParentContentType = contentTypes.GetById(
   "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457 EFB8B24247815D688C526CD44D");
  benefitArticleInfo.Group = "Human Resources";

  // Create the content type
  ContentType benefitArticle = contentTypes.Add(benefitArticleInfo);
  clientContext.ExecuteQuery();
}
Figure 8-12

After the Information object is completed, a ContentType object is added to the ContentTypes collection that you loaded with the ClientContext using the Information object. Although this adds the content type, the type does not exist in the site collection until the ClientContext executes the query.

Working with content types is central to Web Content Management development. Understanding all of the ContentType creation objects will give you a greater ability to develop flexible and powerful solutions for your web content systems.

Page Layouts

In its most basic form, a page layout is a template that is used to author content in the web content solution. In this way, it is very similar to an input form. What makes the page layout unique is that it represents a WYSIWYG (what you see is what you get) input form for a web page. The author enters content into the layout pages at the locations on the page where the content will be rendered in response to visitor requests.

The page layout does not implement the overall branding for the site, so an individual layout page will need to implement specific styles and elements that will keep the page consistent with the branding strategy of the site. SharePoint combines the page layout with the Master Page to render the page to the browser. This means that your page layout will consist of content placeholder elements that will instruct SharePoint where to place elements of the page layout inside the Master Page.

From a content-authoring perspective, the page layout dictates how the authoring experience will function. It accomplishes this in two ways. First, every page layout must be associated with a content type that is available in the Pages library and inherits from the Page content type. Second, the page layout implements editable fields that provide authoring areas on the page. These fields match up with the site columns defined in the content type.

Although each page layout can be associated with only one content type, content types are not limited to one page layout. This offers designers a lot of flexibility when designing page layouts for web content solutions. A good example of this flexibility is the Article pages that are included in the Publishing framework. There is a page layout that shows the page image on the left, one with the image on the right, and one with only the body content.

Finally, because the page layout is a template for authoring and rendering content, the Designer may make changes to the page layout without affecting the underlying content.

Developing Page Layouts

The development process for creating page layout consists of two distinct steps. The first is the development of the Page Layout template that SharePoint uses for authoring and rendering content. This step consists of developing an .aspx file with content placeholders that leverage the Master Page's branding, and fields for accepting authored input, as well as other web page elements necessary to achieve the desired functional and design effects.

The second step of the process is the deployment of the page layout in SharePoint, where the content type association is made and the template becomes available for use. Page layouts are uploaded to the Master Pages and Page Layouts gallery (Site Actions

Developing Page Layouts

Create a Page Layout with SharePoint Designer

SharePoint Designer 2010 makes the process of developing templates and deploying them to SharePoint easier by connecting directly to the target website and its associated content database. With SharePoint Designer 2010, you create a Layout page directly in the Master Pages and Page Layouts gallery, thereby allowing SharePoint Designer to save the page layout directly in the gallery.

Figure 8-13

Figure 8.13. Figure 8-13

SharePoint Designer 2010's site navigation pane, shown in Figure 8-13, includes a link to view the page layouts that are loaded in the Master Pages and Page Layouts gallery. When the Page Layouts item is selected in the navigation pane, SharePoint Designer also displays a custom Ribbon which contains actions specific to Layout pages in SharePoint. These include check-in/check-out of existing page layouts, importing and exporting of page layouts, and access to the Master Pages and Page Layouts gallery's list settings.

To create a new Layout page using SharePoint Designer, click the New Layout Page button in the SharePoint Designer Ribbon. As shown in Figure 8-14, the new action will show a dialog box that asks for the basic information necessary to create a page layout, notably the Content Type Group and Content Type Name of the associated content type that defines the authored content fields for the layout, and the file name and Title of the Layout page.

Figure 8-14

Figure 8.14. Figure 8-14

After SharePoint Designer gets the necessary information to create the page layout, it will instantiate the page in the Master Pages and Page Layouts gallery and open it in the Code View window. This is an important point because the deployment is essentially completed. If you open the Master Pages and Page Layouts gallery from within the Site Settings of the SharePoint site, you will see the new Page Layout in the gallery in a draft mode. This means that anyone with the appropriate permissions can see and use the page layout in your site.

SharePoint Designer provides both a Code View and a Design View. The Design Editor is integrated into SharePoint so that it will load the branding that is defined by the Master Page into the Designer, giving you a complete view of the page layout as you develop its design. In Design View, you build the content of the page layout in the area designated by a box containing the label PlaceHolderMain (Custom), as shown in Figure 8-15.

Figure 8-15

Figure 8.15. Figure 8-15

When SharePoint Designer loads the page into the Editor, it examines the associated content type and lists the available fields in the Toolbox pane. SharePoint Designer also separates the available fields into two categories: Page Fields and Content Fields. Page fields are authored fields that indicate metadata for the page and are not rendered to the browser window during page views. Content fields contain the authored content for the page that is rendered to the browser during page views (see Figure 8-16). Using the toolbox, you drag and drop the fields onto the Layout page.

Figure 8-16

Figure 8.16. Figure 8-16

Adding Fields to your page layout in design mode inserts either a SharePointWebControls or PublishingWebControls element into the page. SharePointWebControls are the ASP.NET server controls included as part of the SharePoint Foundation in the Microsoft.SharePoint.WebControls namespace. PublishingWebControls are the ASP.NET server controls included as part of SharePoint Server in the Microsoft.SharePoint.Publishing.WebControls namespace. The specific control depends on the site column and content type associated with the Layout page; most site columns will be rendered with SharePointWebControls, but any publishing field will be rendered with the PublishingWebControls. The connection between the site column and the web control is made with the FieldName attribute of the web control. The value of this attribute is the internal name of the site column that defines the storage model for the field.

SharePoint 2010 is designed to make the migration from SharePoint 2007 easy. It accomplishes this by supporting assets created in SharePoint 2007. In a page layout, SharePoint adds a new web control, UIVersionedContent. The UIVersionedContent control is a container control that holds a ContentTemplate. The template contains the ASP.NET and HTML that renders for the contained section. The UIVersion attribute of the UIVersionedControl informs SharePoint which version the contained code supports: 3 for SharePoint 2007 and 4 for SharePoint 2010. The out-of-the-box Article pages make heavy use of the UIVersionedContent control and merit close examination if you are developing page layouts that may be rendered as a SharePoint 2007 or 2010 Master Pages.

The disadvantage of using SharePoint Designer is that, when it instantiates a new page layout, it is doing so inside the content database. This means that the page layout is limited to the site in which it was created. In scenarios where a multi-stage environment is used, or you are developing locally and then deploying to a SharePoint server, additional steps are necessary to export the page out of SharePoint Designer and to package it into a Feature. This is the subject of the next section.

Create a Page Layout with Visual Studio

Developing a page layout with Visual Studio 2010 requires that you consider the deployment path for the layout. Normally, page layouts are deployed using the Module element in a Feature. The

Feature is then packaged into a SharePoint Solution for deployment. Visual Studio 2010 includes SharePoint tools that simplify the development effort required to build the deployment packages.

Visual Studio 2010 does not include a project template for a page layout; rather, it includes a project template for a module. This template creates all of the necessary Feature artifacts and a Solution package. The purpose of a Module element is to provide a mechanism for provisioning assets into the content database. In this case, the module will provision the page layout into the Master Pages and Page Layouts gallery.

To create a Layout page in Visual Studio, create a new project (File

Create a Page Layout with Visual Studio

There are two approaches to creating the page layout. The first approach is to manually add a Web Form page to the module by right-clicking the Module1 folder and selecting Add

Create a Page Layout with Visual Studio

To build the page layout, start by adding the minimal declarations and content placeholders. This serves as the foundation for the layout.

<%@ Page language="C#" Inherits="Microsoft.SharePoint.Publishing.PublishingLayout
Page,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyT
oken=71e9bce111e9429c" meta:webpartpageexpansion="full" meta:progid="SharePoint
.WebPartPage.Document" %>
<%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.
WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, Publ
icKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"
Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71
e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.
Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.
Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
         <SharePointWebControls:FieldValue id="PageTitle" FieldName="Title"
         runat="server"/>
</asp:Content>
<asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">

</asp:Content>
Create a Page Layout with Visual Studio

Next, add the web content, styles, and layouts necessary for the branding of the page layout. Finally, use SharePointWebControls to identify the locations for Page and Content Fields in the layout.

<%@ Page language="C#" Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPag
e,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71
e9bce111e9429c" %>
<%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.
WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, Publ
icKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"
Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71
e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.
Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.
Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
  <SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server" />
</asp:Content>
<asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">
  <div class="article article-left">
   <div class="captioned-image">
    <div class="image">
       <PublishingWebControls:RichImageField id="ImageField" FieldName= "PublishingPageImage" runat="server"/>
    </div>
    <div class="caption">
       <PublishingWebControls:RichHtmlField id="Caption" FieldName= "PublishingImageCaption"  AllowTextMarkup="false" AllowTables="false" AllowFonts="false" PreviewValueSize="Small" runat="server"/>
    </div>
    <div class="image">
       <PublishingWebControls:RichImageField id="ProviderImageField" FieldName= "ProviderImage" runat="server"/>
    </div>
   </div>
   <div class="article-header">
    <div class="date-line">
       <SharePointWebControls:DateTimeField id="datetimefield3" FieldName= "ArticleStartDate" runat="server"/>
    </div>
    <div class="by-line">
      <SharePointWebControls:TextField FieldName="ArticleByLine" runat="server"/>
    </div>
   </div>
    <div class="article-content">
       <PublishingWebControls:RichHtmlField id="Content" FieldName= "PublishingPageContent" runat="server"/>
   </div>
       <PublishingWebControls:EditModePanel runat="server" id="editmodepanel1" CssClass="edit-mode-panel">
         <!-- Add field controls here to bind custom metadata viewable and editable in edit mode only.-->
         <PublishingWebControls:RichImageField id="ContentQueryImage" FieldName= "PublishingRollupImage" AllowHyperLinks="false" runat="server" />
<asp:Label text="<%$Resources:cms,Article_rollup_image_text%>" runat="server" />
     </PublishingWebControls:EditModePanel>
    </div>
  </asp:Content>
Create a Page Layout with Visual Studio

The second way to create a page layout is to first create the page in SharePoint Designer with all placeholders, content, styling, and fields in place. Then, use the export button on the Ribbon to save a copy of the page layout to a local folder: right-click on the Module folder in the Visual Studio Solution Explorer, and select Add

Create a Page Layout with Visual Studio

The last step in the page layout development process is to modify the module's elements file so that it will provision the page layout into the Master Pages and Page Layouts folder. It is also a good idea to rename the module and Feature folders with more descriptive names and to set the properties of the Feature and package to better indicate what the Module Feature deploys to SharePoint.

In Visual Studio, open the Elements file located in the Module folder. If the sample.txt file is listed in the Elements file, delete the file from the Solution Explorer. To get the Page Layout into the Master Pages and Page Layouts gallery, modify both the Module element and the File element.

The Module element determines where files are provisioned in a SharePoint site collection. Visual Studio 2010 creates a Module element that has no attribute settings that will provision the files into the root of the site collection's root web. You will need to add the Url and RootWebOnly attributes to ensure that the Page Layout is provisioned to the Master Pages and Page Layouts gallery.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="BenefitsLayout"  Url="_catalogs/masterpage" RootWebOnly="TRUE">
    <File Path="BenefitsLayoutBenefitsInformation.aspx" />
  </Module>
</Elements>
Create a Page Layout with Visual Studio

Although the Module element will now provision the layout file into the proper location in SharePoint, you cannot use it as a page layout template. The Layout page needs to be assigned a content type for the page and a publishing content type for the content. This is done by adding Property elements to the File element.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="BenefitsLayout"  Url="_catalogs/masterpage" RootWebOnly="TRUE">
    <File Path="BenefitsLayoutBenefitsInformation.aspx"
          Url="BenefitsInformation.aspx"
          Type="GhostableInLibrary">
      <Property Name="Title"
      Value="Benefits Information Page" />
<Property Name="MasterPageDescription"
      Value="Use benefits page to publish content related to benefits information" />
      <Property Name="ContentType"
      Value="$Resources:cmscore,contenttype_pagelayout_name;" />
      <Property Name="PublishingAssociatedContentType"
       Value=";#Benefits Information Page;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F200
       7948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D007b07c2cdb600
       4430bfd2fe7a3eff5ecb;#" />
    </File>
</Module>
</Elements>
Create a Page Layout with Visual Studio

The ContentType property assigns a content type to the page layout itself. This is the content type that contains metadata and processing logic for the layout page within the gallery. Normally, this is the page layout content type that provides metadata for Title, Description, Contact, Preview Image, and a few other fields that are relevant to the page layout's .aspx file. These properties are viewable and editable from the item menu in the Master Page and Page Layouts gallery.

The PublishingAssociatedContentType is the content type that is added to the Pages library to inform the storage of Authored content using the page layout. This content type provides the fields that the author enters content into when creating a new page using this layout.

Although this example and the Visual Studio 2010 template demonstrate a single file, you may add as many File elements as you have page layouts. Remember that it is the Module element that determines where the files will be provisioned into the site; therefore, if you add File elements for files that should be provisioned elsewhere, you need to create new Module elements for those files.

At this point, the Layout pages are completed and the Feature contains the necessary information to provision the layout page into the site collection. Run or deploy the project into the target SharePoint site. To test the deployment of the page layout, create a new page in the SharePoint browser interface. After SharePoint creates the new page, click the Page Layout drop-down button in the Ribbon. The new page layout will appear in the list. Click the page layout, and SharePoint will reload the page, using the defined layout page. Verify that the expected fields are available and that the layout page appears correctly in SharePoint.

Master Pages

Most Web Content Management solutions include a design specification that dictates the graphic and communication designs for the website. These designs include not only the look and feel of the sites, but also the navigational elements and user experience presented by the design of the site. Taken together, these designed schemes make up the branding of the sites and pages in SharePoint.

Master Pages provide an entry point for branding a site according to a design specification. Master Pages consist of references to Cascading Style Sheets (CSS), navigation control definitions, search control definitions, and content placeholder definitions that provide areas for layout pages to place content in the final rendered page.

In SharePoint, Master Pages are defined within the Site Settings (Site Actions

Master Pages

Within the Publishing framework, there are two Master Pages that you set: Site Master and System Master. The Site Master Page provides the branding for all authored pages on the site, meaning any page created from a page layout. The System Master Page provides branding to the list and library pages, forms, and administrative pages for the site.

Master Pages are deployed to the same Master Pages and Page Layouts gallery as page layouts. This means that the procedures for developing and deploying Master Pages are very similar to those outlined in the previous section for page layouts. The chief difference lies within the construction of the Master Page. Whereas a page layout has an associated content type that provides fields that are placed into the layout, the Master Page provides ASP.NET content placeholders where page layouts are rendered as well as other SharePoint components.

Create a Master Page with SharePoint Designer

Before developing a Master Page, it is important to understand that every Master Page has an assigned content type that describes the Master Page file itself. The assigned content type provides metadata and processes to the Master Page, which can be set or modified within the Master Pages and Page Layouts gallery.

In SharePoint, there are two Master Page content types installed with the Publishing framework. The first is a hidden content type called System Master Page and inherits from the Document content type. This is the Master Page content type that is typically assigned to Master Pages for nonpublishing sites and for System Master Pages. The second content type is called Publishing Master Page and inherits from System Master Page. This content type is typically assigned to Site Master Pages in the Publishing framework.

SharePoint Designer 2010's navigation pane includes a section specifically for Master Pages. This section displays the Master Pages and Page Layouts gallery filtered to show only the Master Pages. The Master Pages Ribbon provides three create options: two for Master Pages and one to create a web page from an existing Master Page. The Blank Master Page button creates a System Master Page that contains a single content placeholder and no other information. The From Content Type button allows you to create a Site Master Page from the Publishing Master Page or other specific content type.

To create a Site Master Page in SharePoint Designer 2010, click on the From Content Type drop-down list and select Publishing Master Page. SharePoint Designer adds an Untitled master page to the Master Pages gallery and sets the file name to rename mode so that you can enter in the name of the Master Page. At this point, a customized Master Page exists within your site and is checked out as a Draft. If you check in and publish this Master Page, it will be available to set in the site; no additional deployment steps are necessary.

The Publishing Master Page that SharePoint Designer creates is a bare minimum Master Page. The bare minimum includes all of the content placeholders expected by the Publishing framework for Site Master Pages, references to SharePoint's core style sheets for the site and the Ribbon, and other declarations and script necessary for the page to work within a Publishing site collection. The result is a Master Page that renders with no styling or layout; it simply renders everything in order from top to bottom.

In SharePoint 2010, pages are standards-compliant; they do not use tables to layout content. Rather, the bare minimum Master Page includes <div></div> elements that mark the major sections of the Master Page with assigned CSS classes that are semantic. This means that you may use the latest styling techniques to achieve nearly any visual effect that is possible on the web today.

As with everything in SharePoint Designer, the greatest limitation is that it saves the Master Page directly to the content database in customized form. This limits your ability to work with the Master Page in multi-stage environments; however, you can export the completed Master Page to a local file system and package it into a Visual Studio created SharePoint project that will deploy the Master Page to other environments in an uncustomized form.

Create a Master Page with Visual Studio

To develop a Master Page in Visual Studio 2010 you follow the same approach that you use for a page layout. You will include the Master Page in a Module project that will provision the Master Page into the Master Pages and Page Layouts gallery when the Feature is activated.

To create a Master Page in Visual Studio, create a new project (File

Create a Master Page with Visual Studio

Master Pages are substantially more difficult to develop than page layouts. For example, a missed field control in a page layout has no more ill effect on the page than providing no data entry field for the author to use; however, a missed content placeholder in a Master Page throws an exception when a page is rendered with the incomplete Master Page which makes any page that attempts to use the missing content placeholder unbrowsable. Because of the complexity and risks involved in developing Master Pages, it is best to import a bare minimum Master Page or a base Master Page from which to work rather than begin with a blank text file.

Using the procedures outlined in the previous section on developing Master Pages with SharePoint Designer 2010, you can create a bare minimum Master Page and export it using the Ribbon's Export File button, or develop a completed Master Page and export it. SharePoint Designer 2010's functionality and design-time workflow is sufficiently advanced and intuitive that there is no reason not to completely develop the Master Page in SharePoint Designer and use Visual Studio only to package and deploy the Master Page in a noncustomized form.

After completing the Master Page in SharePoint Designer and exporting it to your file system, import it into the Module folder in Solution Explorer: right-click the Module folder and select Add

Create a Master Page with Visual Studio

The Module element provisions files into a SharePoint site collection. The module created by Visual Studio provides a definition that will provision the listed Files into the root of the root web in a site collection. To get the Master Page into the Master Pages and Page Layouts gallery, you need to add the Url attribute to the Module element. The Url attribute instructs SharePoint where to provision the files contained in the module. In this case, the Master Page gallery is located at _catalogs/masterpage.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="CorporateMaster"
          Url="_catalogs/masterpage"
          Path="CorporateMaster"
          RootWebOnly="TRUE">
    <File Path="Corporate.master" Url="Corporate.master" />
</Module>
</Elements>
Create a Master Page with Visual Studio

If you deploy the module at this point, it will provision the Master Page into the Master Pages and Page Layouts gallery, but you will not see the Master Page in the gallery. To make the Master Page available to the gallery, you need to add the Type attribute to the File element. The Master Page must be GhostableInLibrary so that it can be customized using SharePoint Designer. Is some cases, it is possible that the master page may already exist in the Master Pages gallery. In cases where you want to preserve any existing Master Page, add the IgnoreIfAlreadyExists attribute and give it a value of FALSE. If you do set this value to FALSE, you must keep in mind that any upgrade to this feature will not provision updates to the Master Page that you may make in your IDE.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="CorporateMaster"
          Url="_catalogs/masterpage"
          Path="CorporateMaster"
          RootWebOnly="TRUE">
    <File Path="Corporate.master"
          Url="Corporate.master"
          Type="GhostableInLibrary" />
  </Module>
</Elements>
Create a Master Page with Visual Studio

Finally, you need to add properties to the Master Page to set its Master Page content type and UI version. The ContentType property sets the system or site content type for this Master Page, as discussed in the previous section. In SharePoint 2010, Microsoft has made the migration path from SharePoint 2007 easier by adding support for SharePoint 2007 assets. This allows organizations to upgrade the SharePoint servers without forcing the organization to completely rebuild all custom development. The UIVersion property tells SharePoint what version of SharePoint this Master Page is compatible with; a value of 4 indicates SharePoint 2010 site content and a value of 3 indicates SharePoint 2007 site content. Notice that these values are consistent with the UIVersionedContent control introduced in the Page Layouts section.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="CorporateMaster"
          Url="_catalogs/masterpage"
Path="CorporateMaster"
          RootWebOnly="TRUE">
    <File Path="Corporate.master"
          Url="Corporate.master"
          Type="GhostableInLibrary">
      <Property Name="ContentType"
                Value="$Resources:cmscore,contenttype_masterpage_name;" />
      <Property Name="UIVersion"
                Value="4" />
    </File>
</Module>
</Elements>
Create a Master Page with Visual Studio

Once you have modified the Module and File elements and added the properties for the Master Page file, deploy the solution to your target SharePoint site. The Master Page will be provisioned to the Master Page and Page Layouts gallery. To test the Master Page, use Site Settings (Site Actions

Create a Master Page with Visual Studio

Setting the Master Page in Code

In many cases, you will want to not only deploy a Master Page to the site collection, but also set the Master Page automatically, without the additional step of going into Site Settings. Using a Feature Receiver and object model code, you can easily set the Master Page.

To add a Feature Receiver to the Master Page project from the previous section, right-click on the Feature and select Add Event Receiver from the drop-down menu; uncomment the FeatureActivated and FeatureDeactivating methods in the receiver's class.

The SPWeb class contains two properties that correspond to the Site and System Master Pages: CustomMasterUrl represents the Site Master Page, and MasterUrl represents the System Master Page. Provide the Url for each Master Page and call the SPWeb's Update method to save your changes.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    using (SPWeb web = site.RootWeb)
    {
      try
      {
        web.CustomMasterUrl = "/_catalogs/masterpage/Corporate.master";
        web.MasterUrl = "/_catalogs/masterpage/v4.master";
        web.Update();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    using (SPWeb web = site.RootWeb)
    {
      try
      {
        web.CustomMasterUrl = "/_catalogs/masterpage/nightandday.master";
        web.MasterUrl = "/_catalogs/masterpage/v4.master";
        web.Update();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
Setting the Master Page in Code

Navigation

Up to this point, this chapter has focused on the physical structure of the Publishing framework: how to provide templates for authored content and branding. These topics are relevant to the designers and content authors of the site, but the site's visitors will interact with the rendered output of these files. Visitors of your website will be more concerned with the presentation of content and the site's navigation.

Navigation in SharePoint 2010 is based on the ASP.NET Provider Model. This model provides an interface between a datasource that contains the navigational structure and the rendering components that display the structure in the web page. The site's Master Page sets up the structure by declaring the menu and providers, which are integrated into the overall branding strategy.

The specific rendering of navigational components is handled in a site-centric manner. Each site's settings allow configuration of navigational components that may inherit settings from the parent site or begin with a new navigational structure based on the site's hierarchy.

SharePoint offers a wide variety of customization mechanisms for sites. Taken together, SharePoint's navigation is flexible and capable of achieving nearly any Information Architecture.

Customizing Navigation with Site Settings

Out of the box, SharePoint 2010 sites provide dynamic navigation in the form of a top navigation tab bar, a left navigation Quick Launch toolbar, and breadcrumbs. By default, the top navigation bar displays a tab for each site and page contained within the root site of the site collection. Additionally, the tabs will form drop-down menus to display the sites and pages contained within each tab. The Quick Launch toolbar will show the same information, but is usually limited to showing only sites and pages that are below the current page.

In many cases, project requirements will necessitate modification of the default navigational behavior. The out-of-the-box navigation settings are changed in the Site Settings (Site Actions

Customizing Navigation with Site Settings

The Global Navigation settings allow you to set what items show in the top navigation bar. Selecting the options to show subsites and/or pages, instructs SharePoint to display the sites or pages as additional tabs across the top navigation bar. The number of dynamic items to show determines the maximum number of tabs that will be displayed in the top navigation. This setting does not affect the number of items that appear in drop-down menus when a tabbed site contains pages and subsites. To set the maximum number of items in the menu, you set the number on the subsite's Navigation Settings page.

At the root site level the only display option is to show the sites and pages below the root as shown in Figure 8-17, but at the subsite level you have the option to use the parent's global navigation or to reset the top navigation to begin with the subsite's content. Most users, through their interactions with other websites, have come to expect the top navigation of a site to remain static across the site, thus the term "Global" navigation. Changing the inheritance pattern for the top navigation may create confusion for your end users.

Figure 8-17

Figure 8.17. Figure 8-17

The Current Navigation settings are nearly identical to the Global Navigation settings, offering the same options to show subsites and pages, as well as to determine the number of items that appear in the Quick Launch toolbar. Where the Current Navigation settings differ is in the display options available to the subsites.

Whereas users expect the top navigation to remain static across a site, most users expect sidebar navigation to dynamically change based on the selected page or subsite. SharePoint provides the option to display the parent's sidebar navigation; at second-level sites, this setting will probably create a confusing experience for the end user, but at the lower levels this may be a valid setting. For example, if you have a benefits site under a Human Resources department site, it may be desirable to show the Human Resources navigation rather than a benefits-specific navigation.

The other two display options begin at the selected site's level when presenting navigation items, but they differ in determining whether to show all of the sibling sites, as shown in Figure 8-18. At the second level of the hierarchy, showing the siblings may replicate links that are available on the top navigation, but at lower levels, showing siblings may make a more effective navigation experience.

Figure 8-18

Figure 8.18. Figure 8-18

The Editing and Sorting section is a powerful configuration component that allows you to go beyond the out-of-the-box dynamic navigation. Editing and Sorting allows you to control where and whether dynamic components appear on the navigation bars. At the root site level, the Editing and Sorting section shows the links for both the Global Navigation and Current Navigation bars; at the subsite level, only Current Navigation is available.

In most cases, you will want to sort the navigation manually rather than automatically. An effective user experience is governed by an Information Architecture that outlines in what order links will appear in the top and sidebar navigation schemes, rather than an alphabetical arrangement. When manual sorting is selected, as shown in Figure 8-19, you have the ability to move pages and sites up and down within the Global and Current Navigation nodes.

Figure 8-19

Figure 8.19. Figure 8-19

You also have the option to delete or hide pages and subsites. While the user experience for both options is the same — no link — there is a substantial operational difference. When a site or page is deleted from the navigation, it is removed from the dynamic navigation scheme. If you change your mind later and wish to have the item back in the navigation, you will need to go into the List or Library's settings (List Settings

Figure 8-19

Finally, the Editing and Sorting section allows you to add headings and static links to the navigation scheme. Static links have a title, URL, and description, and can be targeted to an audience. This allows you to develop a complete navigational scheme that includes other external sites and pages that are relevant to the Global or Current Navigation. One thing to keep in mind is that the difference between a heading and a link is presentational only; headings may have a URL.

While the Navigational Settings in SharePoint 2010 are powerful and offer a lot of flexibility for configuring navigation in a site, they are cumbersome and not portable. If you have a very large site collection with complex Information Architecture, configuring navigation at each site may be too time-consuming. Also, if you are developing in a multi-stage environment, your only deployment options are to migrate the site from one environment to another or to reenter the navigation in each environment. Before exploring the programmatic methods for dealing with navigation, it is important to understand how SharePoint implements navigation.

Implementing Navigation in the Master Page

How and where navigational elements appear in the site is determined by the Master Page as part of the site's branding strategy. In the Master Page, the navigational elements leverage ASP.NET menu controls and site map datasource controls. The datasource control implements the Provider Model to the ASP Menu control which, in turn, renders the navigation on the page.

The attributes available to the SharePoint:AspMenu control are the same as those available to the corresponding ASP.NET menu control, which provides the same functionality. This is a great advantage to ASP.NET developers, who can leverage their existing knowledge of the ASP menu control. In the Master Page, there are four attributes that require your attention.

<SharePoint:AspMenu ID="GlobalNav" runat="server" DataSourceID="SiteMapDataSource1"
  UseSimpleRendering="true" Orientation="Horizontal" EncodeTitle="false"
  StaticDisplayLevels="1" MaximumDynamicDisplayLevels="1"
  CssClass="top-nav-menu band-menu"
  SkipLinkText="<%$Resources:cms,masterpages_skiplinktext%>"/>
Implementing Navigation in the Master Page
  • DataSourceID: This attribute identifies the PortalSiteMapDataSource that the menu should use as its provider.

  • Orientation: This attribute allows you to set the menu to be horizontal or vertical.

  • StaticDisplayLevels: This attribute sets the default number of hierarchical levels to show in the menu.

  • MaximumDynamicDisplayLevels: This attribute sets the default number of menu items to show in the fly-out menus.

The PublishingNavigation:PortalSiteMapDataSource control sets the provider that the menu control will use for rendering menu items. Whereas the menu control determines how the menu items are rendered, the datasource determines what is available to the menu control. The attributes of this control provide instructions to the provider that determines what nodes are provided to the menu.

<PublishingNavigation:PortalSiteMapDataSource ID="siteMapDataSource1" runat="server"
  SiteMapProvider="GlobalNavigation" EnableViewState="true"
  StartFromCurrentNode="true" StartingNodeOffset="0" ShowStartingNode="false"
  TreatStartingNodeAsCurrent="true" TrimNonCurrentTypes="Heading"/>
Implementing Navigation in the Master Page
  • SiteMapProvider: This sets the provider that retrieves nodes from SharePoint.

  • ShowStartingNode: When this is set to true, the menu will receive a node that represents the starting node. For example, the Global Navigation begins at the root site. If this is set to true, the menu will receive a node representing the root site.

  • StartFromCurrentNode: When this is set to true, the DataSource object uses a set of rules for determining where it is in the navigational scheme and uses that as a starting location.

  • StartingNodeOffset: This property works in conjunction with the StartFromCurrentNode property to determine the starting location of the dataset. The value can be positive or negative, depending on whether you want to start lower in the hierarchy or higher.

Out of the box, SharePoint 2010 includes a number of SiteMapProviders. SiteMapProviders are configured in the web.config file in the sitemap section. As with the other components of navigation in SharePoint, you can leverage your knowledge of ASP.NET's Provider Model to create your own providers and add them to SharePoint.

The two most important providers in publishing sites are the CombinedNavSiteMapProvider and the CurrentNavSiteMapProvider, which are associated with the Global Navigation menu and Current Navigation menu, respectively.

Customizing Navigation Using the Object Model

As noted earlier, customizing navigation from within the Navigation Settings page for each site is both cumbersome and not portable. These limitations are easily overcome by using the SharePoint object. Likewise, the object model provides the ability to create static navigational structures and modify the existing structure similarly to the way you perform customizations in the Editing and Sorting section of the Navigation Settings.

To customize navigation in Visual Studio, create a new Visual Studio project (File

Customizing Navigation Using the Object Model

Adding static navigational structures using the object model is a matter of getting a reference to the navigational component that you want to modify and adding nodes to it. The SPNavigation object in each website includes properties for TopNavigationBar and QuickLaunch, which are both SPNavigationNodeCollections.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    // Add a static link to the root site's quick launch bar
    using (SPWeb web = site.RootWeb)
    {
      try
      {
        // Get reference to the left navigation
        SPNavigationNodeCollection leftNav = web.Navigation.QuickLaunch;
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
Customizing Navigation Using the Object Model

When adding items to the Node Collections, there is no difference between a heading node and a link node other than a heading node will contain children. To create a node, instantiate an SPNavigationNode and pass in the Title, Url, and a flag to indicate whether the link is internal or external to the site collection. The SPNavigationNodeCollection provides methods to add a node as the First element, Last element, or at a specific location in the collection.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    // Add a static link to the root site's quick launch bar
    using (SPWeb web = site.RootWeb)
    {
      try
      {
        // Get reference to the left navigation
        SPNavigationNodeCollection leftNav = web.Navigation.QuickLaunch;

        // Create a heading node to hold links
        SPNavigationNode heading = new SPNavigationNode("Links", web.Url,
        true);
        leftNav.AddAsFirst(heading);

        web.Update();
      }
catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
Customizing Navigation Using the Object Model

The SPNavigationNode class has a Children property that returns an SPNavigationNodeCollection. To create a heading node, simply add nodes to an existing node's Children rather than to the Navigation Node collection.

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  using (SPSite site = (SPSite)properties.Feature.Parent)
  {
    // Add a static link to the root site's quick launch bar
    using (SPWeb web = site.RootWeb)
    {
      try
      {
        // Get reference to the left navigation
        SPNavigationNodeCollection leftNav = web.Navigation.QuickLaunch;

        // Create a heading node to hold links
        SPNavigationNode heading = new SPNavigationNode("Links", web.Url, true);
        leftNav.AddAsFirst(heading);

        // Create a new node and add it to the end of the navbar
        SPNavigationNode wroxLink = new SPNavigationNode(
          "Wrox Books", "http://www.wrox.com", true);
        wroxLink.IsVisible = true;
        leftNav[0].Children.AddAsFirst(wroxLink);

        web.Update();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    }
  }
}
Customizing Navigation Using the Object Model

Using the object model, you can move beyond simply adding static links to the navigation bars to iterating through external site collections or a SharePoint list to provide additional navigation options that are not readily available out of the box.

Customizing Navigation with Web Parts

In SharePoint 2010, there is no shortage of navigational options. SharePoint includes two web parts that expand your ability to provide an effective navigational scheme: the Summary Links web part and the Table of Contents web part.

Figure 8-20

Figure 8.20. Figure 8-20

The Table of Contents web part provides an additional level of navigation from a more localized perspective than the top navigation and Quick Launch toolbar, which are included in the Master Page. It is the perfect tool when an additional sidebar navigational element is called for in the Information Architecture, but cannot be included the Master Page.

From a configuration perspective, the Table of Contents web part provides many of the same dynamic options as Global and Current Navigation. In the Content Settings of the web part, shown in Figure 8-20, you establish where the web part will begin listing content, the number of levels to show, and whether to show the starting location. An interesting option that the Table of Contents web part provides is to show hidden pages and sites. Recall from the "Navigation Settings" section that the Editing and Sorting section allows you to hide sites and pages from Global and Current Navigation — the Table of Contents can display those items that are not shown at a global level.

The Presentation Settings, shown in Figure 8-21, allow you to set the styles for headers and items in the Table of Contents. These style settings are defined in XSL files located in the Styles library. You can extend or replace the referenced XSL by exporting and reimporting the Table of Contents web part. This technique for modifying XSL is discussed in the Content by Query web part.

Figure 8-21

Figure 8.21. Figure 8-21

Finally, the Organization section, shown in Figure 8-22, provides sorting options to sort according to SharePoint's navigation settings or according to specific metadata for the items. The ability to change the sorting in the Table of Contents is not as rich as it is in the Editing and Sorting section of Navigation Settings, but it will generally fit most situations.

The Summary Links web part complements the Table of Contents in that it provides the capability to create a static navigational structure. The Summary Links web part adds options for links that are more flexible and extensive than those available when adding static links in the Editing and Sorting section of the Navigation Settings. You can create not only static links to internal and external sites and pages, but also links to People.

The Summary Links web part adds properties to the link, as you see in Figure 8-23, that allow you to display a description with the link, an image with alternative text, and a tooltip. These settings provide a very flexible mechanism for links that you can use to construct static directories of people, pages, documents, or other related links that have a unique styling and a user experience that has an appealing design.

Figure 8-22

Figure 8.22. Figure 8-22

Figure 8-23

Figure 8.23. Figure 8-23

Like the Table of Contents web part, the Summary Links web part gets style information from an XSL file located in the Styles library. The out-of-the-box styles provide different user experiences for the link content that range from displaying a simple list of links to displaying a digest of information for the links.

The number of options that SharePoint provides for defining and customizing navigation in a site is evidence of the importance of constructing a positive user experience for the visitor. Although search capabilities have improved dramatically in the past few years, browsing through the structure of a website remains the primary model for user interaction.

Content by Query Web Part

The Content by Query web part is one of the most important development tools available in SharePoint. Out of the box, the Content by Query web part provides a lot of very powerful configuration options. Content authors are able to configure the web part to roll up and present content across the site collection. From a development point of view, understanding how to configure the Content by Query web part is important when more advanced customizations are necessary for the project. Developers are able to export the XML of the Content by Query web part to achieve more advanced configurations. Rather than exporting an empty Content by Query web part to configure, it is much more effective for the developer to configure the Content by Query web part using the web UI to get the closest possible configuration and then export it. This will save a lot of development time when customizing.

Using the Content by Query Web Part

The Content by Query web part divides the properties into two major categories and a number of more manageable sections, allowing the content author or developer a more organized approach to configuring the part. The two major sections are Query and Presentation: Query provides the web part with the information necessary to perform the content query, and Presentation provides the information to render the query results in the web part.

Figure 8-24

Figure 8.24. Figure 8-24

The first step to configure the Content by Query web part is to define the source that contains the content to execute a query against, as shown in Figure 8-24. This can be the entire site collection, a specific branch of the site collection's hierarchy, or a specific list. The selection of the source is a more global selection that is narrowed by the other settings in the web part. These settings allow the content author to narrow the larger site collection and branch sources down to a specific type of list/library, as well as to narrow down the query by a content type.

Figure 8-25

Figure 8.25. Figure 8-25

In SharePoint 2010, the Content by Query web part allows the content author to apply multiple filters to the query results, as shown in Figure 8-25. The filters allow the author to select fields from the specified content type to filter the query results based on comparison criteria. What makes the filtering noteworthy for the developer is that it supports the use of a page field value and a query string value as the input to the comparison value. In the example that follows, the web part is using the Title field on the page layout to filter the query results where the category is equal to the text entered into the Title field. It is also using the Category variable in the query string to filter the results.

The use of these special tokens allow the developer or author to create a single configuration for the web part that can be added to multiple pages that will present different results. The developer need only to configure the web part one time, export it, and upload it to each page.

Figure 8-26

Figure 8.26. Figure 8-26

Once the author has configured the results that the Content by Query web part will return, the Presentation section allows configuration of the results. The grouping and sorting sections, shown in Figure 8-26, work as one would expect; the author selects the field to group by or sort by, the direction, and a dimensional limit. Although these settings are fundamental, an author or developer can achieve a number of different layouts with these settings alone.

Behind the scenes, the Content by Query web part stores the query results as XML. It uses a set of XSL files that are contained in the site collection's Style library to perform the rendering of the content in the part. The Styles section of the web part properties, shown in Figure 8-27, displays the definitions that appear in these XSL files. The group style selection displays the XSL logic that is stored in the Header.xsl file, and the Item style selection displays the XSL that is stored in the ItemStyle.xsl file. Lastly, the media player style comes from an XSL file that must be developed separately and selected for the web part.

Figure 8-27

Figure 8.27. Figure 8-27

The "fields to display" section defines what site columns in the query results will be displayed for each of the four main fields of the Content by Query web part, as shown in Figure 8-28. Each field can contain more than one site column, and the columns are evaluated in the order of appearance: if the first site column contains no content, then the next column will be checked and so forth until a site column contains content.

Finally, a powerful function of the Content by Query web part is that it supports publication of query results using RSS, as shown in Figure 8-29.

Figure 8-28

Figure 8.28. Figure 8-28

Figure 8-29

Figure 8.29. Figure 8-29

Customize Content by Query Web Part in XML

The Content by Query web part properties available in the SharePoint UI may seem extensive, but these are not the complete set of customizations that can be made to the web part. Developers can customize both the querying behavior and presentation logic in ways that go beyond those provided in the Web Part Properties Pane.

When a content author or developer adds a web part to a Web Part zone in a page, SharePoint inserts an XML document that contains a reference to the web part's assembly and all of the property values that apply to the web part. SharePoint allows the author or developer to export the XML to a local .webpart file. When exporting a .webpart file, SharePoint will save the XML, along with the property settings that are currently active in the Web Part Property Pane.

Although the additional properties in the .webpart file are available to a developer using SharePoint Designer 2010, the more common scenario is to export the .webpart file to a local folder and make modifications using Visual Studio. Visual Studio provides two advantages over all other methods. First, the .webpart code may be entered into a version control system like Team Foundation Server; and second, the .webpart file can be packaged into a SharePoint Feature and Solution for more controlled deployments.

The two categories of properties that are available in the .webpart file tend to match up with the two categories in the Web Part Properties Pane: Query and Presentation. The Query properties affect the behavior of the Content by Query web part and the Presentation properties affect the display of the content. The Query properties provide a great deal more flexibility in defining what is queried within the site collection. When developing these properties in the XML file, the properties defined in the XML will "trump" any settings entered by authors or developers in the Web Part Properties Pane. The Presentation properties also provide more flexibility in defining the display of content in the web part, but unlike the query properties settings made in the Web Part Properties Pane, the Presentation properties will "trump" the XML file.

There are five properties that support the most common developer customizations to the Content by Query Web Part.

  • QueryOverride: Replaces the content source with a CAML-based query that allows for more control over query operation

  • WebsOverride: Dictates whether the query will recurse over subsites

  • ListsOverride: Allows you to query any kind of list, even those that are not defined in the Web Part Property Pane, such as custom lists that you develop

  • ViewFieldsOverride: Requests a specific set of fields from the query

  • DataColumnRenames: Renames column names before the data is passed to the XSL

For many of the properties in the .webpart file, configuring a value is a matter of adding the value to the XML element as you would with any XML document. For example, you can change the Title property by changing the text between the property's opening and closing tags. On one hand, if the element is a closed element, meaning that it is a single tag that ends with the "/>" characters, then make it an open element and insert the value. On the other hand, some properties require a CAML statement between the opening and closing tags, which is the case with the query properties.

Because CAML statements are themselves XML statements, you cannot simply enter them inside the property tags. The CAML must be enclosed in a CDATA section within the property tags. This is done by placing the CAML statement between the "<![CDATA[" and "]]>" characters. For example: <![CDATA[ <Lists ServerTemplate="101"></Lists> ]]>.

The QueryOverride property allows you to insert a custom-developed CAML query into the Content by Query web part. This allows you to build a set of data that can apply filtering and sorting before the web part's presentation categories conduct their operations. Taking into consideration all of the possibilities, the query override offers a more granular solution than the basic settings provided in the Web Part Properties Pane.

<property name="QueryOverride" type="string">
  <![CDATA[
    <Where>
      <Or>
        <Eq>
          <FieldRef Name="BenefitType" />
          <Value Type="Choice">Medical</Value>
        </Eq>
        <Eq>
          <FieldRef Name="BenefitProvider" />
          <Value Type="Text">United Medical </Value>
        </Eq>
      </Or>
    </Where>
    <OrderBy>
      <FieldRef Name="Created" Ascending="False" />
     </OrderBy>
   ]]>
 </property>

The WebsOverride property simply tells the Content by Query web part whether to run the query against the current site only or to recursively search through all subsites under the current site. The implementation of this property is a closed XML tag that either has the Recursive attribute or does not; however, the tag is contained in a CDATA section in the property tag, which may appear somewhat unusual to some developers.

<![CDATA[
   <Webs Recursive="True"/>
]]>
 <![CDATA[
   <Webs/>
]]>

The ListsOverride property allows the developer to define the type of list that the query is executed against. The CAML data in this property defines whether the query executes against a specific list or a list type. Locating a listing of all ServerTemplate options can be a bit tricky. This attribute is based on the SPListTemplateType enumeration in the SharePoint object model. The enumeration values are listed in the SharePoint Foundation 2010 Class Library Reference (Server Class Library Reference

Customize Content by Query Web Part in XML
<property name="ListsOverride" type="string">
  <![CDATA[
    <Lists ServerTemplate="850"></Lists>
  ]]>
</property>

The ViewFieldsOverride retrieves data of the specified type from the fields included in the CAML query. If the nullable attribute is included in the declaration, then the query will return items that do not have this column.

<property name="ViewFieldsOverride" type="string">
  <![CDATA[
    <FieldRef Name="Title" Nullable="True" Type="Text"/>
    <FieldRef Name="PublishingPageContent" Nullable="True" Type="HTML"/>
  ]]>
</property>

DataColumnRenames is a handy property for making XSL easier. This property maps the column name to a different name in the XSL. An example would be a set of properties that will have the same XSL transformation applied. Rather than define the transformation for each property name, the DataColumnRenames allows you to map all of the properties to a single XSL name.

<![CDATA[<property name="DataColumnRenames" type="string">BenefitsProvider,HR</
property>]]

Use Custom XSL to Modify the Presentation of Content

SharePoint 2010 uses XSL files to transform the query result's XML content into rendered HTML. These XSL files are located in the Publishing framework's Style library in a folder called XSL Style Sheets. Out of the box, this folder contains seven XSL files that are used for rendering the content of all three publishing web parts: Summary Links, Table of Contents, and Content by Query. All three web parts share the Header.xsl and ItemStyle.xsl files; the remaining XSL files are specific to each web part.

Although a developer or author may edit these files directly using SharePoint Designer or another editing tool, it is more common to create a separate custom XSL file for rendering customizations that may be necessary for the Content by Query web part. The customized XSL sheet can then be provisioned into the Style library using a Feature and associated with the Content by Query web part by customizing the .webpart file.

Note

Do not let the name of the Style Library folder, "XSL Style Sheets," distract you from what the XSL files accomplish. They provide the logic to render XML data in an HTML format. Conceptually, it may be easier to think of these as layout sheets. The graphical style, or appearance, of the content in the browser remains the province of the Cascading Style Sheets.

The most effective method for creating a custom XSL file is to download one of the existing XSL files from the Style library and add it to a Module element in Visual Studio, then remove all template elements that you do not need. This gives you an abridged version of the XSL that you can then add your own custom templates to.

The styles that each XSL sheet defines and that you will customize are the two selections that appear in the Styles section of the Web Part Properties Pane. The XSL templates defined in the Header.xsl file populate the drop-down selection for the Group style entry in Styles, and each template defined in the ItemStyle.xsl file populates the Item style drop-down selection.

Each XSL template that you define consists of two distinct sections: variables and div. The variables section processes the XML data that is running through the XSL file. SharePoint 2010 includes a number of functions that will help you process the data that is coming in through the query. Table 8-1 includes some of the more common functions.

Table 8.1. Table XSL Variable Functions

FUNCTION

DESCRIPTION

http://msdn.microsoft.com/en-us/library/bb447557(office.14,classic).aspx

OuterTemplate.GetSafeLink

This function returns a safe URL that is derived from the UrlColumnName value. If the URL is not safe, this method returns a blank string.

OuterTemplate.GetSafeStaticUrl

Similarly to GetSafeLink, this function returns a safe URL from an item's UrlColumnName; otherwise, it returns a blank string.

OuterTemplate.GetTitle

This function returns the data in the Title column.

The div section of the XSL template defines the HTML formatting of the rendered output. This section uses a combination of HTML and XSL to provide the layout instructions for SharePoint. Keep in mind that SharePoint 2010 is standards-compliant; therefore, you should use semantic HTML with div tags in your layout. Rely on your Cascading Style Sheets to provide the formatting and branding of your output.

After you have completed your custom XSL file, you will need to associate the file with the Content by Query web part that will be using the styles defined in the file. This is done by modifying the .webpart file; if you have not exported the Content by Query web part, then you will need to follow the steps in the previous section to export your web part.

There are two properties that you will modify to associate your custom style sheet. The first property is the ItemXslLink property. This is the property that points your web part to your custom XSL file. This element expects a string, not a CDATA section; simply add the location of the file.

<property name="ItemXslLink" type="string">
  /Style Library/XSL Style Sheets/HrItemStyle.xsl
</property>

The second property that you will modify is the ItemStyle or GroupStyle property, which sets the selected style in the Style section of the Web Part Property Pane. While changing or setting this property in your .webpart file is not required, it is generally a good idea to make sure that the property value matches an available XSL template in your custom XSL file. At the very least, your custom XSL should include the definition for the default template, and these two properties could be set to the default value. Keep in mind that the settings you provide to these two properties are the initial values that are used when the web part is added to the page. If the content author changes these values, then the web part will use the manually set values.

<property name="ItemStyle" type="string">ImageRight</property>

Before developing custom XSL for your Content by Query web part implementations, it is wise to become familiar with the out-of-the-box XSL files. Microsoft has provided XSL layouts that cover many situations that you will encounter. The underlying XSL files provide ample examples of source code for customizing your own XSL files.

Redeploy the Content by Query Web Part Using Visual Studio

Your customized Content by Query web part can be uploaded manually into SharePoint using the Ribbon, and your customized XSL files can be manually uploaded into the Style library and published. The manual approach suffers from the same portability issues as the SharePoint Designer approach, and it is much more time-consuming. Therefore, in most cases, you will package your customized part and XSL files into a Feature using Module elements that can then be deployed with SharePoint solutions across farms.

To deploy customized web parts using Visual Studio, create a new project (File

Redeploy the Content by Query Web Part Using Visual Studio

Delete the sample.txt file from the Module element, and add the customized .webpart file by right-clicking on the Module folder and selecting Add

Redeploy the Content by Query Web Part Using Visual Studio
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="WebParts"
          Url="_catalogs/wp"
          RootWebOnly="TRUE">
    <File Path="WebPartsModified_HR_Benefits_Articles.webpart"
          Url="WebPartsModified_HR_Benefits_Articles.webpart" />
  </Module>
</Elements>
Redeploy the Content by Query Web Part Using Visual Studio

When you add a file to the Modules folder, Visual Studio will automatically create a File element in the Element file. The URL for the file will match the folder structure that Visual Studio maintains for the project. You will need to change the Url attribute of the File element so that the .webpart file is provisioned to the root of the gallery; also, add the Type attribute with a value of GhostableInLibrary. It is generally a good idea to provide the Group property to the file. This will create a group in the Web Part Picker that will contain your web part; otherwise, your provisioned web part will appear in the same group as the Content by Query web part, which may cause some confusion for content authors.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="WebParts"
          Url="_catalogs/wp"
          RootWebOnly="TRUE">
    <File Path="WebPartsModified_HR_Benefits_Articles.webpart"
          Url="Modified_HR_Benefits_Articles.webpart"
          Type="GhostableInLibrary">
    <Property Name="Group"
              Value="Human Resources"/>
    </File>
  </Module>
</Elements>
Redeploy the Content by Query Web Part Using Visual Studio

If you are deploying both a customized web part and an XSL file, you will need to add a second Module element to the project. Each Module element dictates where its child files will be provisioned in SharePoint; therefore, you will need one module to provision into the Web Parts gallery, and one module to provision into the Style library. The only code difference between the two modules is the Url attribute of the Module element.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="StyleSheets"
          Url="Style Library/XSL Style Sheets"
          RootWebOnly="TRUE">
    <File Path="StyleSheetsHrItemStyle.xsl"
          Url="HrItemStyle.xsl"
          Type="GhostableInLibrary" />
  </Module>
</Elements>
Redeploy the Content by Query Web Part Using Visual Studio

Once you have completed the module files, right-click on the project in the Visual Studio Solution Explorer and click Deploy. In your target SharePoint environment, you will be able to add the customized web part as you would any other web part: place the page in edit mode, select a Web Part zone, and click Add Web Part. If you have provided values for any of the override properties in your .webpart file, then you will see a notification in the Web Part Property Pane that indicates that a content author or developer is no longer able to edit the Query properties of the web part. If you have included a custom XSL file, then the Style section drop-down menus will include entries for the XSL templates defined in your files.

Learning how to customize the Content by Query Web Part and its associated XSL files is an essential skill for all Web Content Management developers. Mastering this one area of SharePoint development will often save you a lot of time and effort when fulfilling a variety of presentation and content roll-up requirements.

Content Conversion

SharePoint 2010 introduces the use of the Ribbon as an authoring and administration component that mirrors the authoring experience of Office applications. The addition of the Ribbon makes authoring content from within a SharePoint site substantially easier, more configurable, and more familiar to the content author. The Ribbon makes SharePoint's browser interface a capable and perhaps desirable authoring environment.

Despite the addition of the Ribbon and its functionality, there will be many situations in which a different authoring environment or offline authoring is desirable or necessary. SharePoint includes the capability to convert a document authored with an external tool into a SharePoint web page. Out of the box, SharePoint includes converters that will convert Word (both .docx and .docm), InfoPath, and XML documents to web pages in SharePoint. Using the object model, developers can add new document converters to SharePoint that allow conversion from other formats.

Setup Document Conversion

To use document converters in your SharePoint site, you will need to first activate the conversion services and then configure your site to use them. Enabling document conversion begins with the Services on the Server (Central Administration

Setup Document Conversion

Document conversions must be explicitly enabled for each web application, as shown in Figure 8-30. To enable the conversions, access the Configure Document Conversions settings in Central Administration (General Application Settings

Setup Document Conversion
Figure 8-30

Figure 8.30. Figure 8-30

Document conversions are made available within the site collection by adding them to content types, as shown in Figure 8-31. The Manage document conversion for this content type link is available in the Content Type Properties page. This provides a great deal of control not only over what content types can be converted, but also over which converters can be used for each content type.

Figure 8-31

Figure 8.31. Figure 8-31

Using Document Conversion

Using document conversion to create a page from a document is a straightforward experience for the content author. Because the converter is associated with the content type, the content author is not limited to a particular document library. Rather, the content author loads the document into a library, assigns the content type to the uploaded document, and then right-clicks and selects Convert Document from the actions menu, as shown in Figure 8-32.

Figure 8-32

Figure 8.32. Figure 8-32

The author also has the flexibility to select the target location where the converter-generated page will be saved by SharePoint, as shown in Figure 8-33. In some cases, the document conversion process can be very resource-intensive. For this reason, the content author has the choice to set the processing in either synchronous or asynchronous modes in the Processing options. The remainder of the properties and options are specific to each converter.

Figure 8-33

Figure 8.33. Figure 8-33

After the conversion is completed, SharePoint maintains a linkage between the original document and the generated page. This two-way linkage allows the content author to run conversions again when the document is updated. SharePoint allows the content author to generate multiple conversions on a document. This can take the form of a single converter being run repeatedly to generate additional pages, or multiple converters being run on a single originating document. In any case, it is only the last conversion that is maintained for the update linkage. All other conversions must be repeated manually.

For the developer, understanding document conversions and how they work in SharePoint will save custom development time when looking at offline or external authoring scenarios.

SUMMARY

Web Content Management in SharePoint 2010 brings together a variety of roles that traditionally were always present in the design and development of web pages, but were often channeled through a design team. The traditional approach had a tendency to make the development of content and design a slow and cumbersome effort that detracted from the dynamism that is necessary for competitive websites. SharePoint addresses the limitations of traditional web design and development by allowing designers to brand sites, developers to build components, and content authors to generate and maintain content independently of each other, yet within a controlled environment.

Building on solid Information Architecture, developers are able to build the site structure, content types, templates, and components that the authors need to build the content that makes up the site. Visual Studio 2010's integration with SharePoint 2010 and the variety of templates available to developers make the development effort easier and more intuitive. The templates in Visual Studio ultimately generate SharePoint Features and Solutions that enhance the portability of the development effort from one environment to another.

Designers are able to build on the information foundation built by the developers to create a unique branding experience with Master Pages, page layouts, and style sheets. The flexibility of defining branding independently of the content or functionality of the site extends to the built-in web parts, which leverage XSL files and CSS styles to define the rendering of web part contents.

SharePoint also offers a rich authoring experience in which content authors can interact with a SharePoint user interface that resembles the familiar Office interface. Yet, when working in Office is necessary or preferred, the author has the option to use converters to create new pages.

For the developer, it is important to remember that content types and Information Architecture take a central role in any successful Web Content Management implementation. Second in importance is to understand what SharePoint provides out of the box in all areas of web management so that costly time and money are not invested on unnecessary solutions.

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

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