When developing widgets within a team, either internally or for distribution, working with an existing source control system is beneficial.  To support developing widgets with a file-based source control system, a factory default widget provider should be created following the recommended implementation for factory default widget plugins.

When following the recommendation, all widget definitions and supplementary files are stored on the file system and within a Visual Studio project file.  This allows for simple inclusion with most source control systems.

When developing widgets for distribution, a factory default widget provider should be created.  This document outlines the recommended approach to developing widgets in a factory default widget provider to support easy development and deployment.

Benefits of this approach

This document outlines an approach to implementing a factory default widget provider in a way that supports:

  1. Working within Visual Studio.  Visual studio provides text editing and source management functionality that is useful and familiar to developers.
  2. Easy development.  Files can be directly edited in Visual Studio and changes are applied immediately to the development Telligent Evolution site (with respect to caching -- see Clearing the Widget Cache below)
  3. Easy deployment.  When the provider is complete, the output DLL contains all of the widget source files.  Only the DLL needs to be deployed to production sites.  When the associated plugin is enabled, the widget files are installed into the appropriate locations in the production environment.
  4. Source control.  Whether using Visual Studio-based source control or an external source control system, all sources files are stored in the file system and can be versioned using existing source control techniques.

Creating the Visual Studio solution

First, a new solution should be created to manage the code associated with the factory default widget provider.  To do this,

  1. Open Visual Studio (These steps assume Visual Studio 2010 is being used).
  2. Select File > New > Project.
  3. Within the New Project window, towards the top of the window, ensure that .Net Framework 4 is selected in the framework drop-down.
  4. Select the desired language > Windows > Empty Project from the template browser.
  5. Give the project a Name, for example CompanyName.Evolution.Extensions
  6. For Location, select the web/ folder for an existing Telligent Evolution installation.
  7. Uncheck the option to Create directory for solution.
  8. Click OK.
  9. When the project is shown in Visual Studio, close Visual Studio.
  10. Navigate to the folder created for the new project within the web/ folder of the Telligent Evolution installation.
  11. Copy the files of the folder (it should include a CompanyName.Evolution.Extensions solution file and a project file).
  12. Paste the contents into the web/ folder of the Telligent Evolution installation.
  13. Delete the folder created for the new project.
  14. Navigate into the web/filestorage/defaultwidgets/ folder
  15. Get a new GUID to represent the factory default widget provider (see development tips below).
  16. Create a folder within the web/filestorage/defaultwidgets/ folder with the value of this GUID (exclude any hyphens and ensure that letters are lowercase).
  17. Open the solution file for the new project in Visual Studio.
  18. In the Solution Explorer panel, select the project file and then click the Show All Files toolbar item.
  19. Expand the filestorage/defaultwidgets/ folder.
  20. Right-click the sub-folder created in step 16, and select Include in Project.
  21. Click Show All Files again to hide other core files.
  22. In the Solution Explorer panel, right-click the project and select Properties.
  23. Within the project's properties, select the Application tab.
  24. Change Output type to Class Library.  Ensure the Target is set to .NET Framework 4
  25. Within the project's properties, select the Build Tab.
  26. Ensure Platform Target is set to Any CPU.
  27. Within the project's properties, select the Build Events tab.
  28. Place the following within the Post-build event command line:
    copy "$(TargetPath)" "$(SolutionDir)bin\"
  29. Save the solution. 

Defining the factory default widget provider

With the solution and factory default widget storage location set up, the factory default widget provider can be defined using the following steps:

  1. Within the Solution Explorer panel, right click the References node and select Add Reference...
  2. From the Add Reference window, select the Browse tab.
  3. Navigate to the web/bin folder of your Telligent Evolution installation.
  4. Select Telligent.Evolution.Api.dll, Telligent.Evolution.Components.dll and Telligent.Evolution.ScriptedContentFragments.dll (holding down the shift key while selecting) and click OK.
  5. Within the Solution Explorer panel, right click the project and select Add > Class...
  6. In the Add New Item window, give the class a name, for example FactoryDefaultWidgetProvider.cs and click Add. The new class file should open.
  7. Add the following using statements at the top of the file: 
    using Telligent.Evolution.Extensibility.UI.Version1;
    using Telligent.Evolution.Extensibility.Version1;
  8. Update the class declaration to be public and implement the IScriptedContentFragmentFactoryDefaultProvider and IInstallablePlugin interfaces.
  9. Paste the following into the body of the class definition: 
    // TODO: set this to the GUID created in step 15 when creating the solution
    private readonly Guid ID = new Guid("813e530adae540c4911cc8f5b78bc79e");
    
    #region IScriptedContentFragmentFactoryDefaultProvider Members
    
    public Guid ScriptedContentFragmentFactoryDefaultIdentifier
    {
        get { return ID; }
    }
    
    #endregion

    #region IInstallablePlugin Members

    public void Install(Version lastInstalledVersion)
    {
    // This installs the factory defaults into the appropriate location when the plugin // is deployed and enabled. Func<string, Guid> getGuidFromResourceString = delegate(string inGuid) { Guid outGuid; if (Guid.TryParse(inGuid.StartsWith("_") ? inGuid.Substring(1) : inGuid, out outGuid)) return outGuid; return Guid.Empty; }; var assembly = GetType().Assembly; var assemblyNameLength = assembly.GetName().Name.Length + 1; foreach (string resourceName in assembly.GetManifestResourceNames()) { string[] path = resourceName.Substring(assemblyNameLength).Split('.'); if (path.Length > 3 && string.Compare(path[0], "filestorage", true) == 0 && string.Compare(path[1], "defaultwidgets", true) == 0 && getGuidFromResourceString(path[2]) == ScriptedContentFragmentFactoryDefaultIdentifier) { Guid instanceId = getGuidFromResourceString(path[3]); if (path.Length > 4 && instanceId != Guid.Empty && (string.Compare(path[4], "xml", true) != 0 || path.Length > 5)) FactoryDefaultScriptedContentFragmentProviderFiles.AddUpdateSupplementaryFile( this, instanceId, string.Join(".", path.ToList().GetRange(4, path.Length - 4)), assembly.GetManifestResourceStream(resourceName) ); else if (string.Compare(path[path.Length - 1], "xml", true) == 0) FactoryDefaultScriptedContentFragmentProviderFiles.AddUpdateDefinitionFile( this, string.Join(".", path.ToList().GetRange(3, path.Length - 3)), assembly.GetManifestResourceStream(resourceName) ); } } }

    public void Uninstall()
    {
    FactoryDefaultScriptedContentFragmentProviderFiles.DeleteAllFiles(this);
    }

    public Version Version
    {
    get { return GetType().Assembly.GetName().Version; }
    }

    #endregion #region IPlugin Members public string Description { get { // TODO: Update description. This is shown within the plugin management area of // the Telligent Evolution control panel. return "Factory default widgets by CompanyName."; } } public void Initialize() { } public string Name { get { // TODO: Update name. This is shown within the plugin management area of the // Telligent Evolution control panel. return "CompanyName Widgets"; } } #endregion
  10. Review the TODO comments and update appropriately.  Specifically:
    1. Update the ID field to use the GUID created in step 15 when setting up the project.
    2. Update the Name and Description fields to accurately identify the plugin and its purpose.
  11. When the TODOs are resolved, build the solution.  The plugin will be deployed to the Telligent Evolution web site automatically.
  12. Within the Telligent Evolution site, go to Control Panel > Administration > Site Administration > Site Configuration > Manage Plugins.  Locate the newly created factory default widget plugin, check its enabled box, and save the plugins page.  This enables the plugin and allows widgets defined within the provider to be available when editing pages.

    The project is now ready to start defining new factory default widgets.

    Defining new widgets

    Each widget should be represented by an XML file within the GUID-defined folder created in step #16 when setting up the solution.  Factory default XML definitions look like non-factory-default widget exports created in the Control Panel without their embedded files.  

    Adding a new factory default widget

    To add a new factory default widget:

    1. From the Solution Explorer panel, expand the filestorage/defaultwidgets/ folder, right-click the GUID-defined folder, and select Add > New Item...
    2. From the Add New Item window, select XML file from the template browser and give the file a name, for example SampleWidget.xml (avoid spaces).
    3. Click OK.
    4. From the Solution Explorer panel, right-click the newly created XML file and select Properties.
    5. From the Properties panel, change Build Action to Embedded Resource.
    6. Paste the following sample widget definition into the body of the newly created XML file: 
      <scriptedContentFragments>
        <scriptedContentFragment 
          name="[NAME]"
          cssClass="[CSS CLASS]"
          description="[DESCRIPTION]"
          instanceIdentifier="[WIDGET GUID]"
          isCacheable="true"
          varyCacheByUser="true"
          showHeaderByDefault="true">
          <contentScript>
            <![CDATA[
      
            ]]>
          </contentScript>
          <headerScript>
            <![CDATA[
      
            ]]>
          </headerScript>
          <configuration>
            <![CDATA[
      
            ]]>
          </configuration>
          <additionalCssScript>
            <![CDATA[
      
            ]]>
          </additionalCssScript>
          <requiredContext>
            <context id="[CONTEXT GUID]" />
          </requiredContext>
          <languageResources>
            <language key="en-us">
              <resource name="[RESOURCE NAME]">[RESOURCE VALUE]</resource>
            </language>
          </languageResources>
        </scriptedContentFragment>
      </scriptedContentFragments>
    7. Update the XML definition to represent your new widget.  Only name and instanceIdentifier are required.  instanceIdentifier should be set to a new GUID (see Get a New Guid below).  Other values, of unset, should be removed.
    8. When the widget is defined or unused fields are removed and the instanceIdentifier is set, save the XML file and the solution.

    Adding a supplementary file to a factory default widget

    Supplementary files are stored within sub-folders representing the widget to which they are associated.  To add a new supplementary file to a widget:

    1. Within the Solution Explorer panel, navigate into the filestorage/defaultwidgets/[PROVIDER_GUID]/[WIDGET_GUID] folder where [PROVIDER_GUID] is the GUID created in step #15 when the solution was setup and [WIDGET_GUID] is the instanceIdentifier GUID within the widget's XML definition.  If the [WIDGET_GUID] folder doesn't exist, create it by right-clicking the [PROVIDER_GUID] folder and selecting Add > New Folder (ensure that the folder name uses lowercase letters and omits hyphens sometimes present in GUIDs).
    2. Right-click the [WIDGET_GUID] folder and select either Add > New Item... to create a new file or Add > Existing Item... to add an existing file (for example, an image).  When adding files of the following types, the identified extension should be used:  

      Velocity Script .vm
      HTML .html
      Cascading Style Sheet .css
      Javascript  .js
      XML .xml
    3. Within the Solution Explorer panel, right click the newly-added file and select Properties.
    4. From the Properties panel, change Build Action to Embedded Resource.
    5. Save the solution.

    Development tips

    In general, development of factory default widgets should follow the steps:

    1. Add/Edit a widget definition or its supplementary files.
    2. Clear the widget cache.
    3. Review the change in the Telligent Evolution site.
    4. Repeat.

    The Telligent Evolution control panel provides tools for factory default widget developers to clear the widget cache, generate GUIDs, and lookup context IDs.

    Clear the widget cache

    When editing factory default files, it is not necessary to recompile the factory default provider plugin or restart the web application.  Instead, edits can be made directly to the files within Visual Studio, and, once those changes are complete, the widget cache can be expired by going to Control Panel > Administration > Site Administration > Widget Studio > Manage Widgets and selecting Developer Tools and from the Developer Tools page, clicking Clear Cache.

    Get a new GUID

    New GUIDs for factory default widget providers and individual widgets can be retrieved by going to Control Panel > Administration > Site Administration > Widget Studio > Manage Widgets and selecting Developer Tools.  From the developer tools page, the Generate GUID button can be clicked to generate a new GUID.

    Look up required context IDs

    When defining factory default widgets using the XML format, required contexts are identified using their GUID values instead of their textual values as they are selected through the widget editor in the control panel.  To look up a contexts ID, go to Control Panel > Administration > Site Administration > Widget Studio > Manage Widgets and select Developer Tools and from the Developer Tools page, use the Lookup Context ID form.

    Deployment

    Using the steps above, all widget files are stored as embedded resources in the resulting assembly.  To deploy to a testing or production site,

    1. In Visual Studio, ensure the Solution Configuration is set to Release.
    2. Rebuild the solution.
    3. Copy the DLL associated to the factory default widget provider's project to the desired site's web/bin folder.
    4. Enable the plugin by going to Control Panel > Administration > Site Administration > Site Configuration > Manage Plugins.
    5. When the plugin is enabled, all of the associated widget files will be installed into the correct locations and the widgets will be available to the site.
    6. If necessary, enable the newly added widgets for use in specific theme types by going to Control Panel > Administration > Site Administration > Widget

    Related information

    1. Factory default widgets
    2. Creating factory default widgets