Custom actions, triggers, and UI fields

Create custom actions & triggers 

You can register your own triggers and actions. They should be registered in custom Sitefinity modules as shown in the sample below. For more information, see Custom modules

To register a trigger, you need to implement IServiceHookTriggerProvider interface. You also need to create a new trigger class that inherits from ServiceHookTriggerSettingsBase

When defining trigger settings, you need to add this data in constructor: 

  • key - unique key for trigger 
  • triggerTitle - title that be displayed in UI. 
  • eventType - event that you want to track 
  • module - name of the module 


Also, you can add additional event filter in IsMatch function.  

Registering actions


To register custom actions, you must implement IServiceHookActionProvider interface. In addition, you need to create new action setting class inherited from IServiceHookActionSettings

When defining action setting you need to: 

  • Define unique Key
  • Define action Title that is displayed in UI. 
  • Define ParametersType property 

You can also define properties, which can be used in the UI when executing actions. For more information, see Widget designers

When you want to encrypt field to hide sensitive data, you can use Sitefinity.Configuration.SecretData attribute 

Finally, you must implement ExecuteActionAsync method as shown in the sample below. 

Custom service hook sample 

This sample code creates a contact in HubSpot when a user logs in to Sitefinity.  

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using SitefinityWebApp;
using Progress.Sitefinity.Renderer.Designers.Attributes;
using Telerik.Sitefinity;
using Telerik.Sitefinity.Abstractions;
using Telerik.Sitefinity.Configuration;
using Telerik.Sitefinity.Data.Linq.Dynamic;
using Telerik.Sitefinity.HubSpotConnector.Configuration;
using Telerik.Sitefinity.Security;
using Telerik.Sitefinity.Security.Model;
using Telerik.Sitefinity.ServiceHooks;
using Telerik.Sitefinity.ServiceHooks.TriggerSettings;
using Telerik.Sitefinity.Services;
[assembly: SitefinityModule(HubSpotConnectivityModule.ModuleName, typeof(HubSpotConnectivityModule), "HubSpot connectivity", "", StartupType.OnApplicationStart)]
namespace SitefinityWebApp
{
public class HubSpotConnectivityModule : ModuleBase, IServiceHookTriggerProvider, IServiceHookActionProvider
{
public override Guid LandingPageId
{
get { return Guid.Empty; }
}
public override void Initialize(ModuleSettings settings)
{
base.Initialize(settings);
App.WorkWith().Module(Name)
.Initialize();
}
public override void Install(SiteInitializer initializer)
{
}
public override void Upgrade(SiteInitializer initializer, Version upgradeFrom)
{
}
protected override ConfigSection GetModuleConfig()
{
return null;
}
public override Type[] Managers
{
get { return null; }
}
IDictionary<string, IServiceHookTriggerSettings> IServiceHookTriggerProvider.GetServiceHookTriggersSettings()
{
var triggerSettings = new Dictionary<string, IServiceHookTriggerSettings>();
var type = typeof(User);
var loginCompletedTriggerTitle = "User is logged in";
var loginCompletedKey = $"{type.FullName}:LoggedIn".ToLowerInvariant();
var loginCompletedTriggerSettings = new HubSpotConnectivityTriggerSettings(loginCompletedKey, loginCompletedTriggerTitle, typeof(Telerik.Sitefinity.Web.Events.ILoginCompletedEvent), this.Name);
triggerSettings.Add(loginCompletedKey, loginCompletedTriggerSettings);
return triggerSettings;
}
IDictionary<string, IServiceHookActionSettings> IServiceHookActionProvider.GetServiceHookActionsSettings()
{
var actionSettings = new Dictionary<string, IServiceHookActionSettings>();
actionSettings.Add("HubSpotContactCreation", new HubSpotContactCreationActionSettings());
return actionSettings;
}
internal const string ModuleName = "HubSpotConnectivity";
}
public class HubSpotConnectivityTriggerSettings : ServiceHookTriggerSettingsBase
{
public HubSpotConnectivityTriggerSettings(string key, string triggerTitle, Type eventType, string module) : base(key, triggerTitle, eventType, module)
{
}
}
public enum RoleType
{
NonAdminstrators,
Administrators,
All
}
public class HubSpotContactCreationActionParameters
{
[DisplayName("Role type")]
[DefaultValue(RoleType.NonAdminstrators)]
[Choice("[{\"Title\":\"Non adminstrators\",\"Name\":\"NonAdminstrators\",\"Value\":\"NonAdminstrators\",\"Icon\":null},{\"Title\":\"Administrators\",\"Name\":\"Administrators\",\"Value\":\"Administrators\",\"Icon\":null},{\"Title\":\"All\",\"Name\":\"All\",\"Value\":\"All\",\"Icon\":null}]", NotResponsive = true)]
public RoleType RoleType { get; set; }
[DisplayName("Api Key")]
[DefaultValue("")]
public string ApiKey { get; set; }
}
public class HubSpotContactCreationActionSettings : IServiceHookActionSettings
{
/// <inheritdoc />
public virtual string Title
{
get
{
return ActionTitle;
}
}
/// <inheritdoc />
public virtual string Key
{
get
{
return Name;
}
}
/// <inheritdoc />
public virtual Type ParametersType
{
get
{
return typeof(HubSpotContactCreationActionParameters);
}
}
/// <inheritdoc />
public virtual async Task ExecuteActionAsync(ITriggerData triggerData, object parameters)
{
if (triggerData == null)
throw new ArgumentNullException(nameof(triggerData));
if (parameters == null)
throw new ArgumentNullException(nameof(parameters));
if (triggerData.OriginalEvent != null && triggerData.OriginalEvent.UserId != null)
{
var userId = Guid.Parse(triggerData.OriginalEvent.UserId.ToString());
if (userId != Guid.Empty)
{
var actionParameters = parameters as HubSpotContactCreationActionParameters;
if (actionParameters != null)
{
var apiKey = this.GetApiKey(actionParameters.ApiKey);
if (!string.IsNullOrEmpty(apiKey))
{
var url = $"https://api.hubapi.com/crm/v3/objects/contacts?hapikey={apiKey}";
UserManager userManager = UserManager.GetManager();
User user = userManager.GetUser(userId);
if (user != null)
{
UserProfileManager profileManager = UserProfileManager.GetManager();
var profile = profileManager.GetUserProfile<SitefinityProfile>(user);
var requestContent = new StringContent(
"{{\"properties\":{{\"company\":\"{0}\",\"email\":\"{1}\",\"firstname\":\"{2}\",\"lastname\":\"{3}\",\"phone\":\"{4}\",\"website\":\"{5}\"}}}}"
.Arrange("mycompany", user.Email, profile.FirstName, profile.LastName, "1113334444222", "www.mycompanysite.com"),
Encoding.UTF8,
"application/json");
if (this.CanSendRequest(actionParameters.RoleType, userId))
{
var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Content = requestContent;
// If a hubspot contact does not exist, sending will create new
// If it exists, in HubSpot, in the api key logs for request response, you will see "Contact already exists" message.
using (HttpClient httpClient = new HttpClient())
{
HttpResponseMessage httpResponseMessage = null;
try
{
httpResponseMessage = await httpClient.SendAsync(request);
httpResponseMessage.EnsureSuccessStatusCode();
}
catch (HttpRequestException exc)
{
if (httpResponseMessage != null && httpResponseMessage.StatusCode != System.Net.HttpStatusCode.Conflict)
{
throw exc;
}
}
}
}
}
}
}
}
}
}
private string GetApiKey(string paramaterApiKey)
{
var apiKey = paramaterApiKey;
if (string.IsNullOrEmpty(apiKey))
{
var configManager = ConfigManager.GetManager();
var hubSpotConnectorConfig = configManager.GetSection<HubSpotConnectorConfig>();
apiKey = hubSpotConnectorConfig.HubSpotApiKey;
}
return apiKey;
}
private bool CanSendRequest(RoleType roleType, Guid userId)
{
IList<Role> roles = RoleManager.FindRolesForUser(userId);
var canSendRequest = true;
switch (roleType)
{
case RoleType.NonAdminstrators:
canSendRequest = roles.Any(role => !SecurityManager.IsAdministrativeRole(role.Id));
break;
case RoleType.Administrators:
canSendRequest = roles.Any(role => SecurityManager.IsAdministrativeRole(role.Id));
break;
case RoleType.All:
default:
break;
}
return canSendRequest;
}
private const string Name = "HubSpotContactCreation";
private const string ActionTitle = "HubSpot Contact Creation";
}
}

Customize UI fields 

You can customize Servicehook UI with custom JavaScript implementation. 
You can customize Admin App fields by overriding them.
For more information about custom fields, see the corresponding GitHub repository

EXAMPLE: Using the extensions, you can replace Title field by providing this data to FieldData object: 

fieldName: "Title",

fieldType: FieldTypes.shortText,

typeName: "widget-servicehooks"

Want to learn more?

Increase your Sitefinity skills by signing up for our free trainings. Get Sitefinity-certified at Progress Education Community to boost your credentials.

Get started with Integration Hub | Sitefinity Cloud | Sitefinity SaaS

This free lesson teaches administrators, marketers, and other business professionals how to use the Integration hub service to create automated workflows between Sitefinity and other business systems.

Web Security for Sitefinity Administrators

This free lesson teaches administrators the basics about protecting yor Sitefinity instance and its sites from external threats. Configure HTTPS, SSL, allow lists for trusted sites, and cookie security, among others.

Foundations of Sitefinity ASP.NET Core Development

The free on-demand video course teaches developers how to use Sitefinity .NET Core and leverage its decoupled architecture and new way of coding against the platform.

Was this article helpful?