Developer FAQ

How to attach actions to the elements in the tree using ActionExecutor (without form dialogue)?

Answer:

There is possibility to add new commands to existing tree elements, like pages, items, datatypes, media items, file system folders or files...

The commands can execute tasks like displaying a custom ASP.NET page in the C1 console or launch C1 / Workflow Foundation based UI like wizards or editors.

A typical scenario where this would come in handy is adding a "Manage extranet security" command to page and media elements which can launch a customized UI relating to the selected item.

In sample below we attached command to page element in the tree using ActionExecutor without using form dialogue.

using Composite.C1Console.Elements.Plugins.ElementActionProvider;
using Composite.C1Console.Security;
using Composite.C1Console.Elements;
using Composite.Data;
using Composite.Data.ProcessControlled.ProcessControllers.GenericPublishProcessController;
using Composite.Data.Types;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Collections.Generic;
using Composite.C1Console.Actions;
using Composite.Data.ProcessControlled;
using System.Linq;
using System;

namespace Composite.Pages.PublishTree
{
	[ConfigurationElementType(typeof(NonConfigurableElementActionProvider))]
	public sealed class PublishTreeElementActionProvider : IElementActionProvider
	{
		private static readonly ActionGroup _actionGroup = new ActionGroup("Workflow", ActionGroupPriority.PrimaryLow);

		public IEnumerable<ElementAction> GetActions(EntityToken entityToken)
		{
			DataEntityToken dataEntityToken = entityToken as DataEntityToken;

			// check if it's really data entity token
			if (dataEntityToken != null)
			{
				// we need only IPage - doing our check
				if (dataEntityToken.Data.DataSourceId.InterfaceType == typeof(IPage))
				{
					// add our action token
					ElementAction action = new ElementAction(new ActionHandle(new PublishTreeActionToken()))
					{
						VisualData = new ActionVisualizedData
						{
							// right click menu icon settings - label, tooltip, image and display location settings
							Label = "Publish pages tree",
							ToolTip = "Publish pages tree",
							Icon = GenericPublishProcessController.Publish,
							ActionLocation = new ActionLocation
							{
								ActionType = ActionType.Edit,
								IsInFolder = false,
								IsInToolbar = false,
								ActionGroup = _actionGroup
							}
						}
					};

					yield return action;
				}
			}
		}

        public sealed class PublishTreeActionExecutor : Composite.C1Console.Actions.IActionExecutor
		{
            public Composite.C1Console.Actions.FlowToken Execute(Composite.C1Console.Security.EntityToken entityToken, Composite.C1Console.Security.ActionToken actionToken, Composite.C1Console.Actions.FlowControllerServicesContainer flowControllerServicesContainer)
			{
				// doing our magic with data here
				DataEntityToken token = (DataEntityToken)entityToken;
				UpdateTreeRefresher treeRefresher = new UpdateTreeRefresher(token.Data.GetDataEntityToken(), flowControllerServicesContainer);
				IPage page = (IPage)token.Data;
				
				// call our functions
				PublishPagesTree(page.Id);

				// call refresh tree
				treeRefresher.PostRefreshMesseges(page.GetDataEntityToken());
				return null;
			}

			#region Our functions executed here
			private void PublishPage(Guid pageId)
			{
                using (DataConnection connection = new DataConnection())
                {
                    var page = connection.Get<IPage>().Where(p => p.Id == pageId).FirstOrDefault();
                    IPublishControlled publishControlled = page as IPublishControlled;
                    if (publishControlled != null)
                    {
                        if (publishControlled.PublicationStatus != GenericPublishProcessController.Published)
                        {
                            // publish page
                            publishControlled.PublicationStatus = GenericPublishProcessController.Published;
                            connection.Update<IPublishControlled>(publishControlled);
                        }
                    }
                }
			}

			private void PublishPagesTree(Guid pageId)
			{
				// publish page
				PublishPage(pageId);

				// get childrens for current page
                using (DataConnection connection = new DataConnection())
                {
                    IEnumerable<Guid> childPageIds = (from ps in connection.Get<IPageStructure>()
                                                      where ps.ParentId == pageId
                                                      orderby ps.LocalOrdering
                                                      select ps.Id).ToList();

                    // publish childrens
                    foreach (var childPageId in childPageIds)
                    {
                        PublishPagesTree(childPageId);
                    }
                }
			}
			#endregion
		}
		#region We add here action token PublishTreeActionToken
		[ActionExecutor(typeof(PublishTreeActionExecutor))]
		public sealed class PublishTreeActionToken : ActionToken
		{
			// publish permissions required to execute action
			static private IEnumerable<PermissionType> _permissionTypes = new PermissionType[] { PermissionType.Publish };

			public override IEnumerable<PermissionType> PermissionTypes
			{
				get { return _permissionTypes; }
			}

			public override string Serialize()
			{
				return "PublishTree";
			}

            public static Composite.C1Console.Security.ActionToken Deserialize(string serializedData)
			{
				return new PublishTreeActionToken();
			}
		}
		#endregion
	}
}

Download the sample code

How to make it work

  1. Add the following references to the project:
    • System.Configuration
    • Microsoft.Practices.EnterpriseLibrary.Common
    • Composite
  2. Compile your code and copy the assembly to /Bin directory
  3. Register your provider in Composite C1's configuration: \App_Data\Composite\Composite.config (see below)

The "Publish pages tree" command will appear in the context menu of a selected C1 page and will publish it as well as all its children etc.

Register Element Action Provider in Composite.config

To register your action provider in the Composite configuration file:

  • add an <add /> element to the plug-ins list of the Composite.C1Console.Elements.Plugins.ElementActionProviderConfiguration element.

Below is how the sample provider shown above would look like.

<Composite.C1Console.Elements.Plugins.ElementActionProviderConfiguration>
  <ElementActionProviderPlugins>
    <add name="PublishTree" type="Composite.Pages.PublishTree.PublishTreeElementActionProvider, Composite.Pages.PublishTree.Lib" />
  </ElementActionProviderPlugins>
</Composite.C1Console.Elements.Plugins.ElementActionProviderConfiguration>
Please note that you should make sure to set the correct value for the "type" attribute of the "add" element:
  • type="Namespace_name.Class_name, Assembly_name”
  • name is the assembly's name