Skip to main content

Custom Actions Event Receiver

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Nintex.Workflow;
using Nintex.Workflow.Administration;
using Nintex.Workflow.Common;
using System.Reflection;

namespace CFSP.CustomActions.Features.WebApplication___Custom_Actions
{
    [Guid("07607091-449b-422b-94e4-84e6d863eb9e")]
    public class WebApplication___Custom_ActionsEventReceiver : SPFeatureReceiver
    {
        #region Events

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPWebApplication parent = (SPWebApplication) properties.Feature.Parent;

            AddCustomAction(parent, properties, "ReadFromPropertyBagAction.nwa");
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWebApplication parent = (SPWebApplication) properties.Feature.Parent;

            RemoveCustomAction(parent, properties,
                "CFSP.CustomActions.ReadFromPropertyBag.ReadFromPropertyBagAdapter",
                Assembly.GetExecutingAssembly().FullName);

        }
        #endregion

        #region Methods

        /// <summary>
        /// Adds a nintex custom action to SharePoint
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="properties"></param>
        /// <param name="pathToNWAFile"></param>
        protected void AddCustomAction(SPWebApplication parent, SPFeatureReceiverProperties properties,
            string pathToNWAFile)
        {

            // First step is register the action to the Nintex Workflow database
            XmlDocument nwaXml = GetNWADefinition(properties, pathToNWAFile);

            ActivityReference newActivityReference = ActivityReference.ReadFromNWA(nwaXml);

            ActivityReference action = ActivityReferenceCollection.FindByAdapter(newActivityReference.AdapterType,
                newActivityReference.AdapterAssembly);

            if (action != null)
            {
                // update the details if the adapter already exists
                ActivityReferenceCollection.UpdateActivity(action.ActivityId, newActivityReference.Name,
                    newActivityReference.Description, newActivityReference.Category,
                    newActivityReference.ActivityAssembly, newActivityReference.ActivityType,
                    newActivityReference.AdapterAssembly, newActivityReference.AdapterType,
                    newActivityReference.HandlerUrl, newActivityReference.ConfigPage,
                    newActivityReference.RenderBehaviour, newActivityReference.Icon, newActivityReference.ToolboxIcon,
                    newActivityReference.WarningIcon, newActivityReference.QuickAccess,
                    newActivityReference.ListTypeFilter);
            }
            else
            {
                ActivityReferenceCollection.AddActivity(newActivityReference.Name, newActivityReference.Description,
                    newActivityReference.Category, newActivityReference.ActivityAssembly,
                    newActivityReference.ActivityType, newActivityReference.AdapterAssembly,
                    newActivityReference.AdapterType, newActivityReference.HandlerUrl, newActivityReference.ConfigPage,
                    newActivityReference.RenderBehaviour, newActivityReference.Icon, newActivityReference.ToolboxIcon,
                    newActivityReference.WarningIcon, newActivityReference.QuickAccess,
                    newActivityReference.ListTypeFilter);
                action = ActivityReferenceCollection.FindByAdapter(newActivityReference.AdapterType,
                    newActivityReference.AdapterAssembly);
            }

            // Second step is to modify the web.config file to allow use of the activity in declarative workflows
            string activityTypeName = string.Empty;
            string activityNamespace = string.Empty;
            Utility.ExtractNamespaceAndClassName(action.ActivityType, out activityTypeName, out activityNamespace);
            AuthorisedTypes.InstallAuthorizedWorkflowTypes(parent, action.ActivityAssembly, activityNamespace,
                activityTypeName);

            // Third step is to activate the action for the farm
            ActivityActivationReference reference = new ActivityActivationReference(action.ActivityId, Guid.Empty,
                Guid.Empty);
            reference.AddOrUpdateActivationReference();
        }


        /// <summary>
        /// Removes a nintex custom action from SharePoint
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="properties"></param>
        /// <param name="adapterType"></param>
        /// <param name="adapterAssembly"></param>
        protected void RemoveCustomAction(SPWebApplication parent, SPFeatureReceiverProperties properties,
            string adapterType, string adapterAssembly)
        {
            ActivityReference action = ActivityReferenceCollection.FindByAdapter(adapterType, adapterAssembly);
            if (action != null)
            {
                // Remove the action definition from the workflow configuration database if the Feature is not activated elsewhere
                if (!IsFeatureActivatedInAnyWebApp(parent, properties.Definition.Id))
                    ActivityReferenceCollection.RemoveAction(action.ActivityId);

                string activityTypeName = string.Empty;
                string activityNamespace = string.Empty;
                Utility.ExtractNamespaceAndClassName(action.ActivityType, out activityTypeName, out activityNamespace);

                // Remove the web.config entry
                Collection<SPWebConfigModification> modifications = parent.WebConfigModifications;
                foreach (SPWebConfigModification modification in modifications)
                {
                    if (modification.Owner == AuthorisedTypes.OWNER_TOKEN)
                        // OWNER_TOKEN is the owner for any web config modification added by Nintex Workflow
                    {
                        if (IsAuthorizedTypeMatch(modification.Value, action.ActivityAssembly, activityTypeName,
                            activityNamespace))
                        {
                            modifications.Remove(modification);
                            parent.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                            break;
                        }
                    }
                }

            }
        }

        private bool IsAuthorizedTypeMatch(string modification, string activityAssembly, string activityType,
            string activityNamespace)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(modification);
            if (doc.FirstChild.Name == "authorizedType")
            {
                return (doc.SelectSingleNode("//@TypeName").Value == activityType
                        && doc.SelectSingleNode("//@Namespace").Value == activityNamespace
                        && doc.SelectSingleNode("//@Assembly").Value == activityAssembly);

            }

            return false;
        }

        private bool IsFeatureActivatedInAnyWebApp(SPWebApplication thisWebApplication, Guid thisFeatureId)
        {
            SPWebService webService = SPWebService.ContentService;
            if (webService == null)
                throw new ApplicationException("Cannot access ContentService");

            SPWebApplicationCollection webApps = webService.WebApplications;
            foreach (SPWebApplication webApp in webApps)
            {
                if (webApp != thisWebApplication)
                    if (webApp.Features[thisFeatureId] != null)
                        return true;
            }

            return false;
        }

        private XmlDocument GetNWADefinition(SPFeatureReceiverProperties properties, string pathToNWAFile)
        {
            using (Stream stream = properties.Definition.GetFile(pathToNWAFile))
            {
                XmlDocument nwaXml = new XmlDocument();
                nwaXml.Load(stream);
                return nwaXml;
            }
        }

        #endregion
    }
}

Comments

Popular posts from this blog

PowerShell For create Sub site in office 365

#Add references to SharePoint client assemblies and authenticate to Office 365 site Add-Type -Path "\Software\SharePoint 2013 Client Browser v1.7\Microsoft.SharePoint.Client.dll" Add-Type -Path "\Software\SharePoint 2013 Client Browser v1.7\Microsoft.SharePoint.Client.Runtime.dll" $Username = Read-Host -Prompt "Please enter your username" $Password = Read-Host -Prompt "Please enter your password" -AsSecureString $Site = "https://XXXXXXX.sharepoint.com/sites/Test2/" $Context = New-Object Microsoft.SharePoint.Client.ClientContext($Site) $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username,$Password) $Context.Credentials = $Creds $csvLocation = "C:\Users\PS_SiteCollectionsToCreate.csv" $csv = Import-Csv $csvLocation #List Custom Templates $Templates = $Context.Site.GetWebTemplates("1033","0") $Context.Load($Templates) $Context.ExecuteQuery() $Templates | Whe...

Create bulk Sub site Using power shell script using custom SharePoint template

#Add references to SharePoint client assemblies and authenticate to Office 365 site Add-Type -Path "\Software\SharePoint 2013 Client Browser v1.7\Microsoft.SharePoint.Client.dll" Add-Type -Path "\Software\SharePoint 2013 Client Browser v1.7\Microsoft.SharePoint.Client.Runtime.dll" $Username = Read-Host -Prompt "Please enter your username" $Password = Read-Host -Prompt "Please enter your password" -AsSecureString $Site = "https://xxxx.sharepoint.com/sites/sPOTest2/" $Context = New-Object Microsoft.SharePoint.Client.ClientContext($Site) $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username,$Password) $Context.Credentials = $Creds $csvLocation = "C:\Users\AA82211\Desktop\PS_SiteCollectionsToCreate.csv" $csv = Import-Csv $csvLocation #List Custom Templates $Templates = $Context.Site.GetWebTemplates("1033","0") $Context.Load($Templates) $Context.ExecuteQuery() $...

Business-critical processes with SharePoint and SQL

SharePoint 2010 provides the ability to connect to backend business systems, surface business data in SharePoint and make it accessible by, and useful to, employees across the organization. Almost every company of significant size uses ERP and CRM solutions to run core business processes. Over time, companies have developed detailed practices around using such systems to support vertical disciplines within the organization (e.g. product planning, financial performance management, supply-chain management, etc.),  yet challenges remain with regard to driving visibility and collaboration, based on business data, across different disciplines and teams. These challenges stem from the fact that only a fraction of employees are licensed and trained to use those backend systems, and from the high cost and complexity of integrating such systems across different functions and teams. With SharePoint and SQL, once the relevant business data is surfaced in an enterprise-wide...