Skip to content

Commit a312ebc

Browse files
committed
Introduced a service class to encapsulate HubSpot API requests.
1 parent 9eede5d commit a312ebc

File tree

12 files changed

+267
-163
lines changed

12 files changed

+267
-163
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Umbraco.Forms.Extensions.Crm.Hubspot.Models.Responses;
4+
using Umbraco.Forms.Extensions.Crm.Hubspot.Services;
5+
using Umbraco.Web.Editors;
6+
using Umbraco.Web.Mvc;
7+
8+
namespace Umbraco.Forms.Extensions.Crm.Hubspot.Controllers
9+
{
10+
[PluginController("FormsExtensions")]
11+
public class HubspotController : UmbracoAuthorizedJsonController
12+
{
13+
private readonly IContactService _contactService;
14+
15+
public HubspotController(IContactService contactService)
16+
{
17+
_contactService = contactService;
18+
}
19+
20+
/// <summary>
21+
/// ~/Umbraco/[YourAreaName]/[YourControllerName]
22+
/// ~/Umbraco/FormsExtensions/Hubspot/GetAllProperties
23+
/// </summary>
24+
/// <returns></returns>
25+
public async Task<IEnumerable<Property>> GetAllProperties() => await _contactService.GetContactProperties();
26+
}
27+
}

src/Umbraco.Forms.Extensions.Crm.Hubspot/HubspotComponent.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
using System.Web.Mvc;
55
using System.Web.Routing;
66
using Umbraco.Core.Composing;
7+
using Umbraco.Forms.Extensions.Crm.Hubspot.Controllers;
78
using Umbraco.Web;
89
using Umbraco.Web.JavaScript;
910

1011
namespace Umbraco.Forms.Extensions.Crm.Hubspot
1112
{
12-
public class HubspotComposer : ComponentComposer<HubspotComponent>, IUserComposer { }
13-
1413
public class HubspotComponent : IComponent
1514
{
1615
public void Initialize()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Umbraco.Core;
2+
using Umbraco.Core.Composing;
3+
using Umbraco.Forms.Extensions.Crm.Hubspot.Services;
4+
5+
namespace Umbraco.Forms.Extensions.Crm.Hubspot
6+
{
7+
public class HubspotComposer : IUserComposer
8+
{
9+
public void Compose(Composition composition)
10+
{
11+
composition.Register<IContactService, HubspotContactService>(Lifetime.Singleton);
12+
13+
composition.Components().Append<HubspotComponent>();
14+
}
15+
}
16+
}

src/Umbraco.Forms.Extensions.Crm.Hubspot/HubspotController.cs

Lines changed: 0 additions & 73 deletions
This file was deleted.
Lines changed: 21 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
using Newtonsoft.Json;
2-
using Newtonsoft.Json.Linq;
32
using System;
43
using System.Collections.Generic;
5-
using System.Net.Http;
6-
using System.Text;
7-
using Umbraco.Core.Composing;
84
using Umbraco.Core.Logging;
95
using Umbraco.Forms.Core;
106
using Umbraco.Forms.Core.Attributes;
117
using Umbraco.Forms.Core.Enums;
128
using Umbraco.Forms.Core.Persistence.Dtos;
9+
using Umbraco.Forms.Extensions.Crm.Hubspot.Models;
10+
using Umbraco.Forms.Extensions.Crm.Hubspot.Services;
1311

1412
namespace Umbraco.Forms.Extensions.Crm.Hubspot
1513
{
1614
public class HubspotWorkflow : WorkflowType
1715
{
18-
static readonly HttpClient client = new HttpClient();
16+
private readonly ILogger _logger;
17+
private readonly IContactService _contactService;
1918

20-
private readonly IFacadeConfiguration _configuration;
21-
22-
public HubspotWorkflow(IFacadeConfiguration configuration)
19+
public HubspotWorkflow(ILogger logger, IContactService contactService)
2320
{
24-
_configuration = configuration;
21+
_logger = logger;
22+
_contactService = contactService;
2523

2624
Id = new Guid("c47ef1ef-22b1-4b9d-acf6-f57cb8961550");
2725
Name = "Save Contact to Hubspot";
@@ -35,68 +33,29 @@ public HubspotWorkflow(IFacadeConfiguration configuration)
3533

3634
public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
3735
{
38-
// Check Hubspot key is not empty
39-
var apiKey = _configuration.GetSetting("HubSpotApiKey");
40-
if (string.IsNullOrWhiteSpace(apiKey))
41-
{
42-
// Missing an API Key
43-
// TODO: Can I bubble up a specific message as to why
44-
Current.Logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: No API key has been configurated for the 'Save Contact to HubSpot' the form {FormName} ({FormId})", Workflow.Name, e.Form.Name, e.Form.Id);
45-
return WorkflowExecutionStatus.NotConfigured;
46-
}
47-
4836
var fieldMappingsRawJson = FieldMappings;
4937
var fieldMappings = JsonConvert.DeserializeObject<List<MappedProperty>>(fieldMappingsRawJson);
50-
if(fieldMappings.Count == 0)
38+
if (fieldMappings.Count == 0)
5139
{
52-
Current.Logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: Missing Hubspot field mappings for workflow for the form {FormName} ({FormId})", Workflow.Name, e.Form.Name, e.Form.Id);
40+
_logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: Missing Hubspot field mappings for workflow for the form {FormName} ({FormId})", Workflow.Name, e.Form.Name, e.Form.Id);
5341
return WorkflowExecutionStatus.NotConfigured;
54-
}
55-
56-
// Map data from the workflow setting Hubspot fields
57-
// From the form field values submitted for this form submission
58-
var postData = new PropertiesPost();
59-
60-
foreach (var mapping in fieldMappings)
61-
{
62-
var fieldId = mapping.FormField;
63-
var recordField = record.GetRecordField(new Guid(fieldId));
64-
if (recordField != null)
65-
{
66-
// TODO:
67-
// What about different field types in forms & Hubspot that are not simple text ones ?
68-
postData.Properties.Add(mapping.HubspotField, recordField.ValuesAsString(false));
69-
}
70-
else
71-
{
72-
// There field mapping value could not be found.
73-
// Write a warning in the log
74-
Current.Logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: The field mapping with Id, {FieldMappingId}, did not match any record fields. This is probably caused by the record field being marked as sensitive and the workflow has been set not to include sensitive data", Workflow.Name, mapping.FormField);
75-
}
7642
}
7743

78-
// Serialise dynamic JObject to a string for StringContent to POST to URL
79-
var objAsJson = JsonConvert.SerializeObject(postData);
80-
var content = new StringContent(objAsJson, Encoding.UTF8, "application/json");
81-
82-
// POST data to hubspot
83-
// https://api.hubapi.com/crm/v3/objects/contacts?hapikey=YOUR_HUBSPOT_API_KEY
84-
var url = $"https://api.hubapi.com/crm/v3/objects/contacts?hapikey={apiKey}";
85-
var postResponse = client.PostAsync(url, content).GetAwaiter().GetResult();
86-
87-
// Depending on POST status fail or mark workflow as completed
88-
if (postResponse.IsSuccessStatusCode == false)
44+
var commandResult = _contactService.PostContact(record, fieldMappings).GetAwaiter().GetResult();
45+
switch (commandResult)
8946
{
90-
// LOG THE ERROR
91-
Current.Logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: Error submitting data to Hubspot for the form {FormName} ({FormId})", Workflow.Name, e.Form.Name, e.Form.Id);
92-
return WorkflowExecutionStatus.Failed;
47+
case CommandResult.NotConfigured:
48+
_logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: Could not complete contact request for {FormName} ({FormId}) as the workflow is not correctly configured.", Workflow.Name, e.Form.Name, e.Form.Id);
49+
return WorkflowExecutionStatus.NotConfigured;
50+
case CommandResult.Failed:
51+
_logger.Warn<HubspotWorkflow>("Workflow {WorkflowName}: Failed for {FormName} ({FormId}).", Workflow.Name, e.Form.Name, e.Form.Id);
52+
return WorkflowExecutionStatus.Failed;
53+
case CommandResult.Success:
54+
return WorkflowExecutionStatus.Completed;
55+
default:
56+
throw new ArgumentOutOfRangeException(nameof(commandResult));
9357
}
9458

95-
// TODO:
96-
// Is it worth logging the success that it got created in HubSpot with its ID etc in response
97-
// Can get full response with: postResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult();
98-
99-
return WorkflowExecutionStatus.Completed;
10059
}
10160

10261
public override List<Exception> ValidateSettings()
@@ -105,30 +64,4 @@ public override List<Exception> ValidateSettings()
10564
return errors;
10665
}
10766
}
108-
109-
internal class PropertiesPost
110-
{
111-
public PropertiesPost()
112-
{
113-
// Ensure we an init an empty object to add straight away
114-
Properties = new JObject();
115-
}
116-
117-
[JsonProperty(PropertyName = "properties")]
118-
public JObject Properties { get; set; }
119-
}
120-
121-
internal class MappedProperty
122-
{
123-
[JsonProperty(PropertyName = "formField")]
124-
public string FormField { get; set; }
125-
126-
[JsonProperty(PropertyName = "hubspotField")]
127-
public string HubspotField { get; set; }
128-
}
129-
130-
internal class ErrorResponse
131-
{
132-
public string message { get; set; }
133-
}
13467
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Umbraco.Forms.Extensions.Crm.Hubspot.Models
4+
{
5+
public class MappedProperty
6+
{
7+
[JsonProperty(PropertyName = "formField")]
8+
public string FormField { get; set; }
9+
10+
[JsonProperty(PropertyName = "hubspotField")]
11+
public string HubspotField { get; set; }
12+
}
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Newtonsoft.Json;
2+
using Newtonsoft.Json.Linq;
3+
4+
namespace Umbraco.Forms.Extensions.Crm.Hubspot
5+
{
6+
internal class PropertiesRequest
7+
{
8+
[JsonProperty(PropertyName = "properties")]
9+
public JObject Properties { get; set; } = new JObject();
10+
}
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Umbraco.Forms.Extensions.Crm.Hubspot.Models.Responses
4+
{
5+
public class ErrorResponse
6+
{
7+
[JsonProperty(PropertyName = "message")]
8+
public string Message { get; set; }
9+
}
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Newtonsoft.Json;
2+
using System.Collections.Generic;
3+
4+
namespace Umbraco.Forms.Extensions.Crm.Hubspot.Models.Responses
5+
{
6+
public class PropertiesResponse
7+
{
8+
[JsonProperty(PropertyName = "results")]
9+
public List<Property> Results { get; set; }
10+
}
11+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Umbraco.Forms.Extensions.Crm.Hubspot.Models.Responses
4+
{
5+
public class Property
6+
{
7+
[JsonProperty(PropertyName = "name")]
8+
public string Name { get; set; }
9+
10+
[JsonProperty(PropertyName = "label")]
11+
public string Label { get; set; }
12+
13+
[JsonProperty(PropertyName = "description")]
14+
public string Description { get; set; }
15+
}
16+
}

0 commit comments

Comments
 (0)