Home > Not CodeFluent Related :), SharePoint > Adding a document template to a SharePoint 2010 List Template

Adding a document template to a SharePoint 2010 List Template


Did you ever get a “This file could not be found” error in Microsoft Word after trying to declaratively set a document template for a list template?

Solution04

I did! And as I didn’t find any satisfying solution on the web, here is mine.

Typically you get this error when creating a custom content type – let’s say “Expense” – to which you attach a document template – “ExpenseTemplate.docx” – that you import with a Module – “ExpenseTemplateModule”.

As you’re obviously following SharePoint best practices (see chapter “Finalizing the Definitions”), you decided to put your document template in the “_cts” hidden folder in the “Expense” subfolder.
Though I don’t recommend it, I’ve put all components above in one “element.xml” file for simplicity’s sake:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="ExpenseTemplateModule">
    <File Path="ExpenseContentType\ExpenseTemplate.docx" Url="_cts/Expense/ExpenseTemplate.docx" />
  </Module>
  <!-- Parent ContentType: Document (0x0101) -->
  <ContentType ID="0x0101007565c5a8bf1244838e8c8d3b3ea430cb"
               Name="Expense"
               Group="My Content Types"
               Description="Create a new Expense from a content type"
               Inherits="TRUE"
               Version="0">
    <Folder TargetName="/_cts/Expense" />
    <FieldRefs>
    </FieldRefs>
    <DocumentTemplate TargetName="ExpenseTemplate.docx" />
    <XmlDocuments>
      <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
        <FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
          <Display>DocumentLibraryForm</Display>
          <Edit>DocumentLibraryForm</Edit>
          <New>DocumentLibraryForm</New>
        </FormTemplates>
      </XmlDocument>
    </XmlDocuments>
  </ContentType>
</Elements>

Then you create a list definition from content type – “ExpenseListDefinition” – with a list instance – “Expenses” (OK, give me a 9 for my creativity).
Following are the two “Element.xml” files automatically generated by Visual Studio 2010.

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <!-- Do not change the value of the Name attribute below. If it does not match the folder name of the List Definition project item, an error will occur when the project is run. -->
    <ListTemplate
        Name="ExpenseListDefinition"
        Type="10001"
        BaseType="1"
        OnQuickLaunch="TRUE"
        SecurityBits="11"
        Sequence="110"
        DisplayName="Expense List Definition"
        Description="List definition for the expense document library"
        Image="/_layouts/images/itdl.png"
        DocumentTemplate="121"/>
</Elements>
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Title="Expenses"
                OnQuickLaunch="TRUE"
                TemplateType="10001"
                Url="Expenses"
                Description="Document library to manage expenses.">
  </ListInstance>
</Elements>

Icing on the cake, you implement a feature event receiver to automatically enable content type on list instance.

using System.Runtime.InteropServices;
using Microsoft.SharePoint;

namespace ExpenseAccountLibrary.Features.Expense_Library
{
    [Guid("08e11c2c-7273-4b55-962b-db3704e70552")]
    public class Expense_LibraryEventReceiver : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;

            if (site == null)
                return;

            SPList invoiceList = site.RootWeb.Lists["Expenses"];
            invoiceList.ContentTypesEnabled = true;
            invoiceList.Update();
        }
    }
}

At this point, your Visual Studio solution should look like this:

Solution01

Once successfully deployed, you probably expect that creating a new “Expense” in your “Expenses” library should open ExpenseTemplate.docx in Word…

Solution02

Well, it doesn’t!

Solution03

Apparently, SharePoint is looking for the document template inside the library folder itself. I played with the Folder and DocumentTemplate nodes of the ContentType element (see first code snippet) with no luck.

Some people found an alternative solution by saving their folder in the LAYOUTS folder, but that’s not an option in my case as I want my templates to be locally saved and not accessible in every single site of my SharePoint farm.

I then wondered how SharePoint handles this when doing the same thing from web site administration. Well, it just duplicates the document template inside the “Forms” folder of the library in a subfolder that has the same name than the content type.

So let’s just do that, it’s quite simple, we only need to modify two files. First the “Schema.xml” underneath the ExpenseListDefinition element. The ContentType node has been copied from the first “Elements.xml” file (see first code snippet). Just modify the “Folder” node as the following:

<?xml version="1.0" encoding="utf-8"?>
<List xmlns:ows="Microsoft SharePoint" Title="Expense List Definition" Direction="$Resources:Direction;" Url="ExpenseAccountLibrary-ExpenseListDefinition" BaseType="1" xmlns="http://schemas.microsoft.com/sharepoint/">
  <MetaData>
    <ContentTypes>
      <ContentType ID="0x0101007565c5a8bf1244838e8c8d3b3ea430cb" Name="Expense" Group="My Content Types" Description="Create a new Expense from a content type" Inherits="TRUE" Version="0">
        <Folder TargetName="Forms/Expense" />
        <FieldRefs>
        </FieldRefs>
        <DocumentTemplate TargetName="ExpenseTemplate.docx" />
        [...]

Then edit the “Elements.xml” file that define the list instance and add a new Module element to duplicate the document template:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Title="Expenses"
                OnQuickLaunch="TRUE"
                TemplateType="10001"
                Url="Expenses"
                Description="Document library to manage expenses.">
  </ListInstance>
  <Module Name="ExpenseListInstanceTemplateModule">
    <File Path="ExpenseContentType\ExpenseTemplate.docx" Url="Expenses/Forms/Expense/ExpenseTemplate.docx" />
  </Module>
</Elements>

Re-deploy your solution, and “voilà”, everything works great:

clip_image009

Thomas Ledan

  1. February 4, 2012 at 10:46 pm

    Thanks for a great post. But I found one problem when I tried this solution: when I saved the document created with custom content type it pop up a dialog box asking for the content type for the document. This dialog box should not pop up because I already choose the content type by choosing the correct template when creating new document.

    • Thomas Ledan
      February 6, 2012 at 10:57 am

      Hi ganagus,

      Thanks for your reply. Let me check if we aggreed on this. If you set some required properties on your content type, when you first save your document you have a Word error message stating that “some properties are missing or invalid” ?

      If so, I don’t have a definitive answer at the moment about this, I’ll check for a solution.

      In the meantime, perhaps you can check this: http://aftabashaikh.com/2011/12/10/document-information-panel-not-displaying-in-sharepoint-2010/

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s