Friday, April 25, 2008

Adding a custom content type to a site definition

Today we'll be a adding a custom content type to our site definition we created in this post. The project that we're working with is an STSDEV project, so my project file structure reflects that. If you aren't using STSDEV you may need to make a few modifications. If you don't know what custom content types are, here's a good overview.

The content type we develop here will extend the Document content type. We'll call it a Project Proposal. Now let's get to work.

Step 1: Project Set up

Aside from basing this project on the site definiton I created earlier, we'll need to add the Feature folders that reflect the structure on the server.
  1. Right click on the TEMPLATE folder in your project and choose 'Add New Folder', name this folder 'FEATURES'.
  2. Then add a folder under 'FEATURES' called 'ProjectProposalContentTypes'.

Step 2: The feature definition file

Since we want to deploy this as a feature we'll need to create the feature definition file.
  1. Right click the 'ProjectProposalContentTypes' folder and 'Add a New Item'. Choose XML document and name it 'feature.xml'.
  2. Paste the following code into the 'feature.xml' file:

    <?xml version="1.0" encoding="utf-8" ?>
    <!-- _lcid="1033" _version="12.0.4017" _dal="1" -->
    <!-- _LocalBinding="" -->
    <Feature Id="BC91162B-EB3D-4412-BBE0-E5547CAB05CA"
    Title="Project Proposal Content Types"
    Description="Project Proposal Content Types"
    Version="1.0.0.0"
    Scope="Site"
    xmlns="http://schemas.microsoft.com/sharepoint/">
    <ElementManifests>
    <ElementManifest Location="contentTypes/columns.xml" />
    <ElementManifest Location="contentTypes/ctypes.xml" />
    </ElementManifests>
    </Feature>

    There are a few things to note:
    • You should put your own GUID into the feature 'ID' attribute (you can generate a GUID from the tools menu in Visual Studio, just make sure to use Registry format and delete the curly brackets)
    • In the <ElementManifests> node there are two <ElementManifest> nodes that refer to files that we haven't created yet. The locations indicate that they will be in the 'contentTypes' folder which will be in the same directory as the feature.xml file.

Step 3: The columns.xml file (The columns/'Elements' file)

To keep things organized, we'll be defining the columns in a separate elements file from the content type definition. We'll then refer to the columns from the content type definition file in the next step.

  1. Right click on your 'ProjectProposalContentTypes' folder and add a new XML document called 'columns.xml'
  2. Add the following xml to your 'columns.xml' file:

    <?xml version="1.0" encoding="utf-8" ?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <Field ID="7F80D077-A4FF-4ad0-8F21-432957A6E39C"
    Name="ProjectType"
    StaticName="_ProjectType"
    Group="Project Proposals"
    DisplayName="Project Type"
    Type="Choice"
    Required="True"
    Sealed="TRUE">
    <CHOICES>
    <CHOICE>General Software Development Project</CHOICE>
    <CHOICE>Web Development Project</CHOICE>
    <CHOICE>Systems Architecture Project</CHOICE>
    </CHOICES>
    </Field>
    <Field ID="DED5654C-975C-4278-B198-978CE295454A"
    Name="TimeEstimate"
    StaticName="_TimeEstimate"
    Group="Project Proposals"
    DisplayName="Time Estimate (in hours)"
    Type="Number"
    Format="FALSE"
    Required="True"
    Sealed="TRUE"
    />
    <Field ID="AB47551C-CF14-4823-849A-4BB6E834A3E7"
    Name="Rate"
    StaticName="_Rate"
    Group="Project Proposals"
    DisplayName="Rate (/hr)"
    Type="Currency"
    />
    </Elements>

    What does this all mean? The Field 'ID' attribute uniquely identifies each field with a GUID. The 'Name' attribute is the name of the field. The 'StaticName' is the internal name of the field (used when using the API to get the field value). 'Group' is the column group that the column belongs to. The 'DisplayName' attribute is the column name as it appears in the UI. The 'Type' attribute is the data type that is contained within the field. ALSO NOTE: I broke out the custom Field Definitions into a separate file (above), but if you wanted to organize your project differently you could put your field definitions into the ctypes.xml file.
Step 4: The ctypes.xml file (the content type definition element file)

This file is the main content type definition file. We'll add the fields necessary for this content type. We'll be including 2 kinds of Field References: one for the built in fields that come with SharePoint and one that refers to the fields we defined in the step 3, above.
  1. Right click on your 'ProjectProposalContentTypes' folder and add a new XML document called 'ctypes.xml'
  2. Paste the following code into your 'ctypes.xml' file:

    <?xml version="1.0" encoding="utf-8" ?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
    <ContentType ID="0x010100817535AA5D8F4d47BC9AAE0507E045E7"
    Name="Project Proposal Content Type"
    Group="List Content Types"
    Description="A content type for managing project proposals"
    Version="0"
    Hidden="FALSE"
    >
    <FieldRefs>
    <FieldRef ID="fa564e0f-0c70-4ab9-b863-0177e6ddd247" Name="Title"/>
    <FieldRef ID="52578FC3-1F01-4f4d-B016-94CCBCF428CF" Name="_Comments"/>
    <FieldRef ID="7F80D077-A4FF-4ad0-8F21-432957A6E39C" Name="ProjectType" />
    <FieldRef ID="DED5654C-975C-4278-B198-978CE295454A" Name="TimeEstimate" />
    <FieldRef ID="AB47551C-CF14-4823-849A-4BB6E834A3E7" Name="Rate" />
    </FieldRefs>
    </ContentType>
    </Elements>

    Things to note:
    • The ContentType ID attribute is the string "0x010100" followed by a GUID (with no dashes. This leading "0x010100" is important. (It specifies that we'll be extending a document content type) This number breaks down as follows (from left to right). 0x = system, 0x01 = item, 0x0101 = document. The final '00' before the GUID is a spacer.
Step 5: Test it out.

Make sure your build configuration is set for DebugDeploy (this is an STSDEV setting) and build the project. After the solution has built correctly, you should be able to go to your SharePoint site, choose Site Actions > Site Settings > Site Collection Features and activate your feature. Then you can see your new content type in the 'Site Content Types' area. Note that this content type is based on the 'Document' content type.

If you'd like to apply this content type to a list. Create a new document library. Go to the list settings for that document library and under Advanced Settings choose to enable content type manangement. Then, back on the list settings for that document library, choose to add a content type from the existing site content types. You should see your content type listed there.

Step 6: Add the content type to your site definition automatically

The steps described above basically explain how to create a Custom Content Type and deploy it as a feature, but since I'm building off my original project (if you haven't done it and want to keep up, go here) I want this feature to be automatically associated with my site definition I'm creating. Here's how:

  1. Open your onet.xml for the site definition
  2. In the <Configurations><Configuration><SiteFeatures> tag, add a <Feature ID='insert your feature id here' /> (if you scoped your Custom Content Type feature at the 'Web' level, you'd put the Feature tag into the <WebFeatures> tag (we had to scope at the 'Site' level because the feature is defining Fields).
  3. That's all you should have to do to get your custom feature auto activated on site creation.
  4. Now do a DebugDeploy (or ReDeploy) and test it out by creating a new site collection based on the site definition and checking the Site Settings page to ensure the Site Feature is activated.

3 comments:

Yu Ping Gang said...

Thanks for the article, especially on the Content Type ID part.

Brian said...

Braces {} are missing from field IDs. New content type would be created, but without new site columns.

Anonymous said...

I've created a small tool which generates a feature with multiple contenttypes and document templates.

See http://spfg.codeplex.com for the source code and download.

Comments,hints and tips are welcome !

Regards,
Stef