Removing a Site Column from a Content Type using the Client Object Model

I don’t know how many hours I have spent trying to remove a site column using CSOM. There is a specifc way to do so and you have to do it in the right order. Below is how you would remove a site column that has been provisioned to a SharePoint site, is associated with a Content Type, and is also added to a list.

First you need to get a reference of the field:

ClientContext cc = new ClientContext(siteUrl);
cc.AuthenticationMode = ClientAuthenticationMode.Default;
cc.Credentials = new SharePointOnlineCredentials(userName, pwd);
Web web = cc.Web;

Field field = web.Fields.GetByInternalNameOrTitle(fieldName);
cc.Load(field);
cc.ExecuteQuery();

Next, you need to use the FieldLink object to remove the site column from the content type:

ContentType cType = web.GetContentTypeByName(cTypeName);
FieldLink cTypeField = cType.FieldLinks.GetById(field.Id);
cTypeField.DeleteObject();
cType.Update(true);
cc.Load(cType);
cc.ExecuteQuery();

It is critical to call an Update() on the content type before executing your query.

The next step is to remove the site column from your list as it will be orphaned if you don’t.

List list = web.Lists.GetByTitle(listName);
cc.Load(list);
cc.ExecuteQuery();

if (list.FieldExistsByName(fieldName))
{
     list.Fields.GetByInternalNameOrTitle(fieldName).DeleteObject();
     cc.ExecuteQuery();
}

Finally, remove the site column itself:

field.DeleteObject();
cc.ExecuteQuery();

 

Advertisements

Branding in SharePoint 2013 Session Update

We had a great time presenting today at SharePoint Cincy 2013. It was a fantastic event and we appreciate our engaged audience and all those who asked questions and came to talk to us afterwards.

You will find today’s session presentation at the link below. Please visit my blog post earlier this year at https://thesharedcontext.wordpress.com/2013/02/12/sharepoint-2013-design-tips/ as it does cover some of the topics we discussed today. If you have any questions, please feel free to contact myself or my co-presenter David Ginn. We’ll be happy to help!

Matthew W. Tallman
Twitter: @mwtallman
Email: mtallman@cardinalsolutions.com

 

David Ginn
Twitter: @DavidMGinn
Email: dginn@cardinalsolutions.com

Presentation (PPTX):
SPCincy – Branding In SharePoint 2013 – Final

SharePoint 2013 Design & Branding Tips

I have recently spent some time focusing on the new design features of SharePoint 2013 and have run into some snags and challenges. I thought it necessary to share some of my experiences in hopes that others can use this information to help them along.

SharePoint 2013 has a couple new features around design and branding. There are as follows:

  1. The Design Manager
  2. The Snippet Gallery

Now, designers can design HTML in their favorite HTML editor and turn over that code to SharePoint. By uploading HTML to your master page gallery, you can use the Design Manager to convert that HTML into a workable Master Page. It is important to note that there isn’t a magic wand that converts every conceivable HTML file into a perfect Master Page, so there are some things you need to be aware of when designing your HTML file first.

HTML File Structure

SharePoint 2013 requires that your HTML file be XHTML compliant. In other words, it needs to take on the same structure as XHTML 1.0 transitional files. Be careful with HTML 5 as well, as some of the structure changes may not work during conversion. It’s a good idea to upload your HTML file to an XML validator to ensure it meets the requirements. A good tool to use is located at http://validator.w3.org/#validate_by_upload.

Example of an XHTML 1.0 Transitional file
XHTML 1

In addition to making your HTML file XML-compliant, here are a couple of other tips:

  1. Do not insert <form> tags.
  2. Do not design your navigation menus in HTML, utilize the SharePoint 2013 snippet gallery.
  3. Remember that HTML is converted to a master page, however you can use the Design Manager to create new page layouts as well.

Master Page Gallery

The first thing you will need to do before attempting to upload your HTML files to SharePoint for conversion, is map a drive to the _catalogs\masterpage location within SharePoint 2013.

I ran into an issue with mapping a drive to my local master page gallery in SharePoint 2013. My Virtual Machine was running Windows Server 2012 Standard. If you receive an error when mapping the drive, such as “Your client does not support opening this list with Windows Explorer.” then you will need to install the “Desktop Experience” feature from the Server Manager, shown below in the screenshot.
Desktop Experience

In addition to the feature, make sure your WebClient service is also running from within Server Manager, see screenshot below.Web Client

Once you have successfully mapped the drive, here are a couple of other tips to follow:

  1. It doesn’t really matter where your HTML, images, and CSS files are located. However, to make things easier and to be smart about organization, create sub folders for the following:
    • Images
    • CSS
    • JS
  2. Once a file is converted, SharePoint will manage the association of your HTML file to the Master Page. This means that you can directly edit the HTML file without ever having to touch the Master Page. If you attempt to edit the Master Page in SharePoint Designer, you will get an error.
  3. If you need to remove association of the HTML file to the Master Page, load the Design Manager, click Edit Master Pages and open the context menu (three dots) on the desired file. You will want to click on Edit Properties and scroll down the page and uncheck the Associated File check box.
    • When you remove association, you can edit the Master Page in SharePoint Designer.

Creating a Page Layout

You can now create page layouts with the Design Manager as well. This will allow you to define the layout of the actual content that will be authored within SharePoint on a page. If you are familiar with creating and modifying Page Layouts in previous versions, you will be happy to know that the Design Manager has made it easier.

To create a new page layout, here are the steps:

  1. From the Site Settings page, click on Design Manager
  2. Click on option 6 (Edit Page Layouts)
  3. The screen will give you the option to create a new page layout and list any current page layouts that may have been created. Click on Create a page layout.
  4. Provide a name for the page layout
  5. Associate the page layout with the desired master page and content type
  6. Click OK

Below is a screenshot of the create page layout screen:

Page Layout1After you have created your new page layout, navigate to your _catalogs\masterpage mapped drive. The new page layout .aspx page will be visible along with the .html file. When you edit the page layout HTML file, SharePoint will manage the association with the Page Layout in SharePoint and automatically apply your changes.

Brief Overview of the Snippet Gallery

The SharePoint 2013 snippet gallery is where you can insert SharePoint elements (top bar navigation, edit mode panel, search box, etc.). When you insert the snippets, SharePoint creates commented markup in your HTML file. While it is possible to edit the snippet markup in the HTML file, it is advised not to do so. When you are inserting a snippet, SharePoint provides an interface where you can modify the behavior, styles, and properties of the control you are inserting. Below is a screenshot of my custom design applied with the snippet gallery open.

Snippet Gallery

Once you have selected the appropriate snippet you wish to insert, you can copy it to the clipboard and insert it into your HTML file.

Hopefully these brief, high level tips will help get you on your way with designing sites on the SharePoint 2013 platform.

Registering Custom Event Handlers

If you are looking for a quick way to manage event handlers in SharePoint 2007, please check out my solution at CodePlex and download a WSP package that will allow you to do this using STSADM.

There are many ways to register event handlers and you can certainly pick your flavor. However, please feel free to use this solution I wrote a few years ago (but only recently published to CodePlex).

You can do the following with this solution:

  1. Add event handlers
  2. List registered event handlers
  3. Delete event handlers

All this from the command line ease of STSADM.

Also, please stay tuned as I re-work this solution as PowerShell extensions for SharePoint 2010 in the near future.

Provisioning SharePoint Lookup Columns

There is alot of misinformation out there in the blogosphere regarding SharePoint Lookup Columns and how to provision them correctly with a Feature.

Let me just say that I’ve tried about every technique I have found, including declaritvely defining the lookup column through CAML schema (field and list definition).  Every technique I have tried (declaritvely) doesn’t work. MSDN references that the <Field> tag can have a List property and that it is the “internal name” of the list. Others say it’s the GUID of the list, while others say it has to all be done in the list schema.

So…as a result, let me give you my two cents on the subject. DON’T declaritvely try to provision a Lookup field. It’s more of a headache than its really worth. In my opinion, the best practice is to do it through a Feature Receiver. You will have complete control over how the lookup field will get created and used. Besides, using a list GUID through XML schema is nonsense, unless you are creating a ListInstance with that GUID (but I’ve tried that too and it doesn’t work).

Go the Feature Receiver route, trust me. There are a few posts out there on various blogs, including a downloadable example on CodePlex. They are all great and will work. However, if you don’t want to bother with those…let me just provide you my technique on provisioning a Lookup column.

First, define a feature that will call a custom Feature Receiver like the following:

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns=http://schemas.microsoft.com/sharepoint/
	Id="6B7DB96E-851B-4790-9A54-6B79DC61C0A7"
	Title="Base Feature"
	Description="Provisions base content types and fields for the site."
	Scope="Site"
	ReceiverAssembly="TSC.SharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f1710125c5a87ae6"
	ReceiverClass="TSC.SharePoint.BaseFeatureReceiver"
	Hidden="false"
	ImageUrl="TSC/MyFeature.jpg"
	ImageUrlAltText="TSC Custom Feature">
	<ElementManifests>
		<ElementManifest Location="tscfields.xml"/>
		<ElementManifest Location="tscctypes.xml"/>
	</ElementManifests>
</Feature>

Next, create a class in Visual Studio that will inherit SPFeatureReceiver like the following:

public class TSCBaseFeatureReceiver : SPFeatureReceiver
{
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        using (SPSite site = (SPSite)properties.Feature.Parent)
        {
              using (SPWeb web = site.RootWeb)
              {
                 // Set lookup columns.
                 SPFieldLookup lookupCol = ProvisionLookupField("MyFieldTitle", "My Field Display Name", "My Site Columns", true, true, SPContext.Current.Site.RootWeb, SPContext.Current.Site.RootWeb.Lists["My List Title"], "Title");
                 LinkToCType(SPContext.Current.Site.RootWeb, "My Content Type", (SPField)lookupCol);
              }
         }
    }

    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
    }

    public override void FeatureInstalled(SPFeatureReceiverProperties properties)
    {
    }

    public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
    {
    }
}

The last step is to create the methods the code above calls. You can place these methods in the same Feature Receiver below the “FeatureUninstalling” method.

It is important to have your feature first create the lookup column, then to associate the column to a content type. If you look at my Feature XML, you will see that I have an ElementManifest to provision a “tscctypes.xml” file. Within this file, I have defined a few custom content types. You can follow the same process, just change “My Content Type” to the name of the content type you are defining in your Feature.

Now, here are the remaining pieces of code to get this to work:

public static SPFieldLookup ProvisionLookupField(string fieldName, string fieldDisplayName, string group, bool required, bool allowMultipleValues, SPWeb web, SPList lookupList, string lookupField)
{
    web.Fields.AddLookup(fieldName, lookupList.ID, lookupList.ParentWeb.ID, required);
    web.Update();
    SPFieldLookup lookup = (SPFieldLookup)web.Fields.GetFieldByInternalName(fieldName);
    lookup.AllowMultipleValues = allowMultipleValues;
    lookup.LookupField = lookupField;
    lookup.Title = fieldDisplayName;
    lookup.Group = group;
    lookup.Update(true);
    return lookup;
}

public static void LinkToCType(SPWeb web, string contentType, SPField field)
{
    SPContentType ct = web.ContentTypes[contentType];
    ct.FieldLinks.Add(new SPFieldLink(field));
    ct.Update();
}

That’s it!