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

Build and Deploy a custom theme in SharePoint 2019: Using C# and Site features

Custom Theme and Branding are common to use cases and all kinds of business users like to have the personalized team and collaboration sites. today I am posting C# code that will help to build custom features for SharePoint 2019 site.   If need any assistance, I would be happy to help: kamal_pandey@outlook.com  ----------------------------- Code to build  custom features---------- using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; namespace SharePointBranding.Code {     public class BrandingManager     {         public SPWeb Web { get; set; }         public BrandingManager(SPWeb web)         {             Web = web;         }         public void SetMasterPage(stri...

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...