Creating a Custom Metadata Editor Plugin for Colligo for SharePoint

Just wrapped up a project developing a custom metadata editor to plugin to the Colligo Contributor for SharePoint client.

If you aren’t familiar with Colligo, it’s a desktop client application/outlook add-in/explorer file manager, that enables users to save documents or emails directly to SharePoint, and be prompted for metadata at the time of saving.

Colligo reads the content type of the target lists/libraries, and generates a default form very similar to what SharePoint does with the default EditForm.aspx ListForm web part. If you don’t like the default form, or need to customize the metadata entry experience (for example custom validation, pulling from external data sources, inter-dependent controls), you can develop a custom editor and show your own Windows Forms-based form to the user.

Colligo default editor form
The default Colligo Editor form, shown here when adding a new Announcement.

How to Start

To start developing a custom editor, begin by installing Colligo Contributor, and obtaining your product and sdk keys from Colligo.

Create a new Visual Studio Class Library project, and add a reference to the Colligo dlls in the GAC.

Add the necessary using statements:

using Colligo;

using Colligo.Properties;

using Colligo.Util;

using Colligo.WML.MetaData;

Change your class to inherit from the ICustomEditor class:

namespace MyNamespace

{

    public class MyCustomEditor : ICustomEditor

    {

 

    }

}

Implement the Interface methods:

namespace MyNamespace

{

    public class MyCustomEditor : ICustomEditor

    {

 

        // SDK Key

        private const string SDK_KEY = "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX";

 

        #region ICustomEditor Members

 

        public string GetSdkKey()

        {

            return SDK_KEY;

        }

 

        public EditorResult ShowEditor(IEditContext context)

        {

            // Show your form here

 

        }

 

        public ResolveConflictResult ShowResolveConflictDialog(IResolveConflictContext context)

        {

            return ResolveConflictResult.UseDefaultResolveDialog;

        }

 

        #endregion

 

    }

}

In the ShowEditor method, this is where you can create an instance of a Windows Form, and call the ShowDialog method on it. You can also pre-validate and avoid showing your form for situations that are not appropriate.

public EditorResult ShowEditor(IEditContext context)

{

 

    // Check if this is something we care about

    if (!context.List.IsDocumentLibrary)

    {

        return EditorResult.UseDefaultEditor;

    }

    if (!string.Equals(context.List.Name, "Private Documents", StringComparison.CurrentCultureIgnoreCase) &&

        !string.Equals(context.List.Name, "Public Documents", StringComparison.CurrentCultureIgnoreCase))

    {

        return EditorResult.UseDefaultEditor;

    }

 

    // Only show for Create/Edit (use the default Colligo form for Viewing)

    if (context.EditorMode == EditorMode.Create || context.EditorMode == EditorMode.Edit)

    {

        using (myCustomWindowsForm myForm = new myCustomWindowsForm(context))

        {

            DialogResult createResult = DialogResult.None;

 

            createResult = myForm.ShowDialog(context.Parent);

 

            switch (createResult)

            {

                case DialogResult.Cancel:

                    return EditorResult.Cancel;

                case DialogResult.OK:

                    return EditorResult.OK;

                case DialogResult.No:

                    return EditorResult.UseDefaultEditor;

            }

        }

    }

    else

    {

        // View - Show the default editor

        return EditorResult.UseDefaultEditor;

    }

 

    // Fall through

    return EditorResult.OK;

 

}

Notice I am passing in the IEditContext instance into my form’s constructor. The IEditContext object has all the goodies in it, and will give you access to the list, the web, the content types, list item metadata, etc.).

What to Consider

Some basic things to consider are:

  • Which scenarios will your editor cover? View, Create, Edit?
  • Is this only for documents, or list items, or both?
  • Will you support content types? A list/library can be configured with multiple content types, which you will need to create a UI for selecting/changing if you decide to support that.
  • How will you handle multiple files? Will you enable setting different data for each item, or will you force all items to use the same entered metadata? Think carefully about the “Name” field for documents in document libraries. You want to make sure that the same name is not used for multiple documents.
  • Will you allow changing folders (for document libraries with folders enabled)? If so, you’ll need to build this UI.

There are a number of ways/methods that may kick off the display of your form, and you need to consider each of these:

  • User selects New > Item from within Colligo Contributor
    • This is similar to the New > [Content Type] menu directly in SharePoint. You can expect that EditorContext.ContentType and EditorContext.ListItems[0].ContentType will not be null.
  • User selects Upload from within Colligo Contributor
    • This is similar to Upload Document from within SharePoint. EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User drags/drops a single file onto Colligo Contributor
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User drags/drops multiple files onto Colligo Contributor
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User performs a single File > Save As from within an application
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User drags/drops multiple files onto the Colligo area in Windows Explorer
    • EditorContext.ContentType and EditorContext.ListItems[0].ContentType may be null.
  • User selects Edit Properties from within Colligo Contributor
    • Need to grab existing values and prepopulate your controls. EditorContext.ContentType and EditorContext.ListItems[0].ContentType will not be null.


Some Gotchas

Following are some gotchas to be aware of:

Check for Null

Don’t make any assumptions about any of the items in the IEditContext object. ContentTypes may be null, Fields may not exist or be null, other relevant ILists in the Web may not be synchronized locally, and will be null, etc., etc., etc. Check everything for null first, and test everything that returns a collection/array for Count and Length > 0. If there are fields/lists/lookup column values that your form expects, check for the existence of these things right away, and exit if you don’t find them.

Parent Windows

If your form is called via the Save As dialog from an application (or via the FileManager), the ParentWindow handle may not be valid, so be careful with the ShowDialog(IWin32Window) overload, which threw a System.ComponentModel.Win32Exception for me. I had to wrap my ShowDialog(context.Parent) in a try>catch, and then try it without any parameters (ShowDialog() ).

Custom Field Types

If you are using any custom field types, be really careful to make sure and store the data in the proper format. My customer was using a couple of custom field types found on CodePlex, and one of them extended the Lookup field, and it took me a few traces with Fiddler to figure out that it wanted its values in lookup column format (“52;#ItemName”);

Site Lookup Columns

If you have any lookup columns that are defined in higher-level sites, and you are using those site columns in lists located in subsites, then Colligo will not be able to see the lookup values. In order to implement these scenarios, you will have to force your users to synchronize the higher level sites as well as the subsites.