Saturday, 20 February 2016

Creating a Site Column with managed Metadata in SharePoint2013


Creating a Site Column with managed Metadata

In the last blog I explained to you how to use the Term Store Management Tool. Once you have created a Term Set and terms, you will want to use them within your SharePoint Sites. This blog will explain how to do this via point and click in the UI, and then afterwards I will show you how programmatically you can create a Managed Metadata Column in a SharePoint Feature.

Creating a Managed Metadata Column for a library (Point and Click).

  • Go to your site, and create a new document library.
  • Once created on the ribbon, select Library from the Library Tools and then click Library Settings.
  • Under the columns section click Create Column
  • Name your column, in my instance I’ve called my Location.
  • Select Managed Metadata as the column type.
    • Now if under Term Set Settings you get the message “The required feature is not enabled for this column type”, then you are probably using a blank site and will need to enable a SP Feature in powershell. Type the following in powershell
      1
      Enable-SPFeature –id "73EF14B1-13A9-416B-A9B5-ECECA2B0604C" –Url <SiteURL>
    • Go back to your Create Column page, select a different column type, then select Managed Metadata column again. Under Term Set Settings you will see your Managed Metadata Data Service instead of the above message.
  • Under Term Set Settings, expand the service and group to navigate down to your term set. Mine is called Countries.
  • Under Default Value you can enter a value that is always displayed when creating a new item. For my demo, I’m putting United Kingdom.
  • Back on your list, upload a document. As you can see, in Location by default United Kingdom is entered.
  • If you wish to change this, you can either
    • Delete United Kingdom and type the name of a different term
    • Click the label icon on the right which brings up the term dialog to allow you to select a different Term.
  • I’ve uploaded a few documents in preparation for my part 4 of my Managed Metadata Series. As you can see I’ve set all the locations.

Programmatically create a Managed Metadata Column.

Here we are going to walk through creating a Managed Metadata column via a feature, then we are going to build upon it to create a list Definition and list instance.
  • Open Visual Studio, and create a new Empty SharePoint Project. Name the project ManagedMetadata.
  • Use your SharePoint Site for debugging, I’m using a team site, andDeploy as a Farm Solution.
  • In Solution Explorer right click your project and select Add -> New Item.
  • On the Add New Item dialog, select Empty Element and name itFields. This will create a feature for you too.
  • Open the Elements.xml file and add the following to create 2 fields. The first field of type TaxonomyFieldType is the actual field we are trying to create (TaxonomyFieldTypeMulti for multiple selection, don’t forget to add Multi = True to the element field too). The Show Field will always point to Term1033 for any Managed Metadata Column. You will need to also include the Customization section. This will be identical for every Managed Metadata Column you create, except the Guid which is the same Guid ID of the second field created here, the Note Hidden field. The Note field, is a hidden field that contains a reference to the actual term in the term set that was selected, this is required for each Managed Metadata Column and the name of it is always [ManagedMetadataColumName]TaxHTField0
    <Field ID="{B654D984-187A-471B-8738-F08F3356CFDA}"
             Type="TaxonomyFieldType"
             DisplayName="Countries"
             ShowField="Term1033"
             EnforceUniqueValues="FALSE"
             Group="Demo"
             StaticName="Countries"
             Name="Countries">
        <Customization>
          <ArrayOfProperty>
            <Property>
              <Name>TextField</Name>;
              <Value xmlns:q6="http://www.w3.org/2001/XMLSchema" p4:type="q6:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{67308AC2-9556-456B-BF9E-43E8F23EBEE6}</Value>
            </Property>
          </ArrayOfProperty>
        </Customization>
      </Field>
      <Field Type="Note"
             DisplayName="Countries_0"
             StaticName="CountriesTaxHTField0"
             Name="CountriesTaxHTField0"
             ID="{67308AC2-9556-456B-BF9E-43E8F23EBEE6}"
             ShowInViewForms="FALSE"
             Required="FALSE"
             Hidden="TRUE"
             CanToggleHidden="TRUE"
             Group="Demo"
             RowOrdinal="0"
             />
    </Elements>
  • Now we have created the field if this was deployed it wouldn’t work. This is because you have to hook up the column to the TermSet, and this isn’t something we can do declaratively. It has to be done via a Feature Receiver event. Right click your feature, and select Add Event Receiver.
  • Before we start, we need to add a dll reference toMicrosoft.SharePoint.Taxonomy. Right click References > Add References… and find Microsoft.SharePoint.Taxonomy. Add using Microsoft.SharePoint.Taxnonomy to the top of your Event Receiver class.
  • In the FeatureActivated event add the code
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
 SPSite site = properties.Feature.Parent as SPSite;
 ConnectTaxonomyField(site, new Guid("{B654D984-187A-471B-8738-F08F3356CFDA}", "Continents", "Countries");
}
We are about to create the ConnectTaxonomyField method in a moment. It will pass in the Guid of the Managed Metadata Field ID, and the Group name, and Term Set Name of the Term Set we wish to add. From the below image you can see where I got the string names from.
  • The termStore.Groups.GetByName() and group.TermSets.GetByName() you will find that they don’t exist in your code. That is because these are custom extensions I have created. Add a new class to your project called Extensions, and ensure it is a public static, also add using Microsoft.SharePoint.Taxnonomy to the top of your class. Add the following code.
  • Now we can deploy our solution. First go into the feature, and change the scope from Web to Site. Now click the play button in Visual Studio and deploy the solution.
  • Once your site has loaded up, click Site actions -> Site Settings.Under Galleries, click on Site Columns. As my field was put in the group Demo when I scroll down to that group, I see Countries.
  • Click on Countries. Now if my feature receiver has worked correctly, under Term Set Settings this has been configured correctly.

Create Content Type and List Definition with Managed Metadata

In this step, we are going to create a Content Type, add our new Managed metadata field and required fields to get it all working. Then we are going to create a list definition.
  • Right click on your project and select Add > New Item. Select Content Type and give it the name of Document Location. Click Add.
  • In the SharePoint Customization Wizard select Document as the base type. Click finish.
  • The Elements.xml file should already be displayed for you, for your new content type. We need to update a few items first
    • Name – Document Location,
    • Group – Demo Content Type
    • Description – Demonstration of a content type with a managed metadata field.
  • Now we need to add our field refs. The Managed Metadata Field, the Note field that comes with our Managed Metadata field, SharePoint’s TaxCatchAll column and SharePoint’s TaxCatchAllLabel. The TaxCatchAll and TaxCatchAllLabel columns are lookup fields pointing to the special hidden list in the site collection (TaxonomyHiddenList). They point to the CatachAllData and CatachAllDataLabel fields in the hidden list and are used within each list that has a column of type Managed Metadata. Our final Content Type Elements file should look like below.
<?xml version="1.0" encoding="utf-8"?>
<!-- Parent ContentType: Document (0x0101) -->;
  <ContentType ID="0x010100571ebc0f478a49d5a775039347ee1535"
               Name="Document Location"
               Group="Demo"
               Description="A content type containing Managed Metadata Column."
               Inherits="TRUE"
               Version="0">
    <FieldRefs>
      <FieldRef ID="{B654D984-187A-471B-8738-F08F3356CFDA}" Name="Countries"/>
      <FieldRef ID="{67308AC2-9556-456B-BF9E-43E8F23EBEE6}" Name="CountriesTaxHTField0"/>
      <FieldRef ID="{f3b0adf9-c1a2-4b02-920d-943fba4b3611}" Name="TaxCatchAll"/>
      <FieldRef ID="{8f6b6dd8-9357-4019-8172-966fcd502ed2}" Name="TaxCatchAllLabel"/>
    </FieldRefs>
  </ContentType>
</Elements>
  • Now we are going to create our List Definition. Right Click on your project and select Add > New Item. Select List Definition From Content Type and give it the name of DocLocationCT. Click Add.
  • In the SharePoint Customization Wizard put the Display Name asReference Documents and select your Document Location as the content type to use for your list definition. Ensure the Add a list instance for this list definition is ticked. Click Finish.
  • Open the Schema.xml file from within your DocLocationCT. At the very top of the document you will see <List xmlns:ows=”Microsoft SharePoint”… add the following attribute to enable Content Types on the Document Library.
    1
    EnableContentTypes="TRUE"
  • Underneath <List><Metadata><ContentType><FieldRefs> you will see that all your fields have already been added to the Content Type FieldRefs section at the top of the file.
  • Under the <ContentTypes> section there is the <Fields> section. Near the bottom of the <Fields> section you will find the TaxonomyField Type and Note field for Countries and CountriesTaxHTField0Here is your first Gotcha, you need to add the following to the end of the Countries field.
    1
    webId="~sitecollection" List="TaxonomyHiddenList"
  • To ensure our field shows up in the default view, scroll down Schema.xml file until you reach <View BaseViewID=”1″ Type=”HTML”… Then add the following as an addition FieldRef. The order you add it to in the list, will be the order it will appear on the document library view. I’ (Please note, if you add it to BaseViewID=”0″ it will not show up.
    1
    <FieldRef Name="Countries"></FieldRef>

List instance.

When we created the List Definition, we said to add a list instance for this list definition.
  • Within the List Definition in Solution Explorer, you can see a List Instance has been added with an elements.xml file. Open up this elements file. Change the file to the following. (We will add the featureId value shortly, also note that the TemplateType will match the List Template Type in the Elements.xml file from the List Defintion.
    <?xml version="1.0" encoding="utf-8"?>
      <ListInstance Title="Document Location References"
                    OnQuickLaunch="TRUE"
                    TemplateType="10000"
                    Url="Lists/References"
                    FeatureId="[The Feature ID of the List Definition Feature]"
                    Description="A document library of reference, categorised by Country/Region.">
      </ListInstance>
    </Elements>
  • The last thing that has to be done is add an event receiver for our list instance. This event receiver is fired on item adding or item updating.The events are SharePoint Taxonomy events, and they ensure the hidden columns are updated whenever the values within the Managed Metadata column changes. Right Click the project and select Add > New Item. Select Event Receiver and name it MangedMetadataER, click Add.
  • On the SharePoint Customization Wizard, the event receiver type isList Item Events (Default)The item that should be the event source isReference Documents(ManagedMetadata\DocLocationCT)(Default). Then tick An item is being added and An item is being updated. Click Finished.
  • You will be taken to the .cs file. This file can be deleted. Then open theElements.xml file of the ManagedMetadataER.
  • The current Receivers shown will need to be deleted and replaced. To be honest we could have just created an empty element, however I like the icons in Visual studio to be correct, so this is the reason I created an Event Receiver.
  • Replace the Receivers to so the file looks like the following.
    <?xml version="1.0" encoding="utf-8"?>
      <Receivers ListTemplateId="10000">
        <Receiver>
          <Name>TaxonomyItemSynchronousAddedEventReceiver</Name>
          <Type>ItemAdding</Type>
          <Assembly>Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
          <Class>Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver</Class>
          <SequenceNumber>10000</SequenceNumber>;
        </Receiver>
        <Receiver>
          <Name>TaxonomyItemUpdatingEventReceiver</Name>
          <Type>ItemUpdating</Type>
          <Assembly>Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
          <Class>Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver</Class>
          <SequenceNumber>10000</SequenceNumber>
        </Receiver>
      </Receivers>
    </Elements>
  • Time to put it all together. Create 2 features. One calledManagedMetadataListDefinition and one calledManagedMetadataListInstance. Both of these features are web scope instances. (Gotcha 2! I found that if List Definition and List Instance in the same feature didn’t allow the Managed Metadata field to work when I viewed the list it created on activation, although, any following lists created via the list definition did.)The original feature 1 can be renamed to ManagedMetadataFieldAndCT.
  • In the MangedMetadataFieldAndCT feature, (Site scope) ensure the following items are in the Feature.
    • Fields
    • Document Location (This is the Content Type)
  • In the ManagedMetadataListDefinition feature, (Web scope) ensure the following items are in the Feature.
    • DocLoactionCT (This is the List Definition)
    • ManagedMetadataER (This is the Event Receiver)
  • In the ManagedMetadataListInstance feature, (Web scope) ensure the following items are in the Feature.
    • ListInstance1 (This is the List Instance)
  • Lastly, double click the ManagedMetadataListDefinition and view the properties (F4). Take a copy of the Feature Id. Now open theElements.xml file from the ListInstance1 and add this Guid to the FeatureId property that we left blank earlier.
  • Now deploy your solution. When your site loads up, in the Quick Launch list you will see “Document Location References” this is your List Instance. You should find uploading an item, and being able to pick from the term store something for Countries.
  • If you click Site Actions -> More Options, the Create dialog box will appear. If you filter by Library, in the list you will see Reference Documents. This is your List Definition.
  • If you click Site Actions -> Site Settings. Under Galleries, click onSite Content Types. If we scroll down to the group Demo you will see our Content Type Document Location.
This concludes this blog Creating a Site Column with managed Metadata (gotchas with List Definitions) in the Managed Metadata Series. It highlighted some of the Gotchas when creating the Managed Metadata field declaratively. Our next part in the series will explain about Search Refiners, and how to create one based on a Managed Metadata column.