Category Archives: Sales Force

Async integration with SalesForce Leads web service

The SalesForce Leads web service is used mainly to register new leads from other applications, for example a trial page where a user registers for a trial and a Lead in SalesForce is created to be followed by commercial teams.

The integration itself is very simple and straightforward, this post is about doing it in an async way, and also presents a solution for integrations with several different Models.

The web service is called through a normal HttpWebRequest object, but it’s setup is done in 3 stages:

  • The creation of the HttpWebRequest with the initial configuration.
  • Writing the RequestStream from a string – This is the service’s parameters that will be sent in the HTTP POST.
  • Submiting the request.

The RequestStream writing and the request submission are written as async ready methods (they can be awaited on) but the HttpWebRequest creation isn’t as this is of very fast execution.

Calling the service through the HttpWebRequest in an async manner

The integration is written in a static class. The entry point is the static method SubmitRequest, it takes as a parameter an object that is basically a Model object that will have it’s metadata parsed for Param attributes to get the SalesForce common parameters.

public static async Task SubmitRequest(object info)
{
    var request = CreateSalesForceRequest();
    var message = GetSalesForceParams(info) + "&" + GetSalesForceStaticParams();

    await request.WriteRequestStream(message);

    try
    {
        await request.SubmitSalesForce();
    }
    catch (Exception)
    {
        // This doesn't seem to do anything as the servlet allways returns HTTP 200.OK.
        // Use the debug email param and debug param on the servlet Parameter list instead.
        Trace.TraceError("Error registering lead in salesforce. Encoded message string was: {0}", message);
    }
}

Besides the GetSalesForceParams, we can see the 3 stages described earlier in the following methods:

private static HttpWebRequest CreateSalesForceRequest()
{
    var request = (HttpWebRequest)WebRequest.Create(ConfigurationManager.AppSettings["SalesforceWebToLeadUrl"]);
    request.Timeout = 60000;
    request.ContentType = "application/x-www-form-urlencoded";
    request.Method = WebRequestMethods.Http.Post;
    request.KeepAlive = true;
    request.ProtocolVersion = HttpVersion.Version11;
    request.UserAgent = "";

    return request;
}

This creates the HttpWebRequest properly configured to call the Leads web service. The specific web service URL is being retrieve from the configuration file.

private static Task WriteRequestStream(this WebRequest request, string message)
{
    return Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)
        .ContinueWith(t =>
                            {
                                var stream = t.Result;
                                var data = Encoding.ASCII.GetBytes(message);
                                Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, data, 0, data.Length,
                                                        null, TaskCreationOptions.AttachedToParent)
                                    .ContinueWith(x => stream.Close());
                            });
}

This is the first of the async ready methods. It is written as an extension to the WebRequest object. It returns a Task so that it can be awaited and uses the useful FromAsync method in the TPL that wraps a pair of begin and end methods.

private static Task SubmitSalesForce(this WebRequest request)
{
    return Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)
        .ContinueWith(t =>
                            {
                                var response = t.Result;
                                if (response != null)
                                    response.Close();
                            });
}

The last stage of the request submission is the actual SubmitSalesForce method. It is written as an extension to the WebRequest object.

Formatting the service’s parameters

The request string is composed by 2 different blocks. The first one will compose the static parameters with the Leads group, your company OID in SalesForce and additional things that you might want to setup. These are saved in a static Dictionary

private static readonly Dictionary<string, string> StaticParams = new Dictionary<string, string>
                                                                        {
                                                                            {"oid", "MYOID"},
                                                                            {"lead_source", "Web Trial"},
                                                                            {"debug", "1"},
                                                                            {
                                                                                "debugEmail",
                                                                                "me@mycompany.com"
                                                                            }
                                                                        };

And then transformed by the simple method

private static string GetSalesForceStaticParams()
{
    return string.Join("&", StaticParams.Select(p => p.Key + "=" + HttpUtility.UrlEncode(p.Value)));
}

The tricky part comes from the non-static parameters. In my scenario I have several projects using this integration with SalesForce, and these projects use different types of Models and Model architectures. To cope with these differences I used an attribute decoration pattern, much like ADO.NET does validation, so that Models could be decorated specifying certain properties as SalesForce parameters. An extra degree of complexity is added because I have to support EntityFramework Database first modelling, so property decoration is done through the MetadataType attribute instead of having metadata at the properties themselves, an example of an extension of an EntityFramework Database first model object is given below:

[MetadataType(typeof(LandingPageUserMetadata))]
public partial class LandingPageUser
{
}

public class LandingPageUserMetadata
{
    [Required]
    [Display(Name = "First Name")]
    [SalesForceParam(Type = SalesForceParamType.FirstName)]
    public string FirstName { get; set; }

    [Required]
    [Display(Name = "Last Name")]
    [SalesForceParam(Type = SalesForceParamType.LastName)]
    public string LastName { get; set; }

    [Required]
    [Display(Name = "Email account")]
    [EmailValidation(ErrorMessage = "This has to be a valid email address.")]
    [SalesForceParam(Type = SalesForceParamType.Email)]
    public string EmailAddress { get; set; }
}

To support this type of decoration, additional code needs to be written to check for the MetadataType attribute and then parse it’s configured Type. Then the mapping between the actual metadata and the properties needs to be in place so that the values are retrieved from the Model object and not the object used to define the metadata.

The code that takes an object and parses it’s metadata or metadatatype attribute and returns a request message string is:

public static string GetSalesForceParams(object info)
{
    var sfProperties = info.GetType()
        .GetProperties()
        .Where(p => p.GetCustomAttributes(typeof(SalesForceParamAttribute), true).Any())
        .ToArray();

    if (!sfProperties.Any())
    {
        var metadataTypes = info.GetType()
            .GetCustomAttributes(typeof(MetadataTypeAttribute), true)
            .OfType<MetadataTypeAttribute>()
            .ToArray();

        var metadata = metadataTypes.FirstOrDefault();

        if (metadata != null)
        {
            sfProperties = metadata.MetadataClassType
                .GetProperties()
                .Where(p => p.GetCustomAttributes(typeof(SalesForceParamAttribute), true).Any())
                .ToArray();
        }
    }

    var sfParams =
        sfProperties
            .Where(p => info.GetType().GetProperty(p.Name).GetValue(info) != null)
            .Select(
                p =>
                ((SalesForceParamAttribute)p.GetCustomAttributes(typeof(SalesForceParamAttribute), false).First()).SalesForceParam +
                "=" +
                HttpUtility.UrlEncode(info.GetType().GetProperty(p.Name).GetValue(info).ToString()));

    return string.Join("&", sfParams);
}

The attribute definition is simple and straightforward:

namespace IW.Web.Common.SalesForce
{
    using System;

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
    public class SalesForceParamAttribute : Attribute
    {
        public SalesForceParamType Type { get; set; }

        public string SalesForceParam
        {
            get
            {
                switch (Type)
                {
                    case SalesForceParamType.FirstName:
                        return "first_name";
                    case SalesForceParamType.LastName:
                        return "last_name";
                    case SalesForceParamType.Email:
                        return "email";
                    case SalesForceParamType.Company:
                        return "company";
                    case SalesForceParamType.Phone:
                        return "phone";
                    default:
                        return string.Empty;
                }
            }
        }
    }

    public enum SalesForceParamType
    {
        FirstName,
        LastName,
        Email,
        Company,
        Phone
    }
}

Calling the Async methods from an ASP.NET MVC 4 controller

Whenever you’re calling async methods, that are awaiting method calls, you need to make sure that the controller awaits on them, so that they can be executed to the end within the lifetime scope of the controller, without destroying the thread running the controller.

ASP.NET MVC 2 introduced AsyncController, but then the way we had to use to write async methods was too quirky. With the async framework that was changed and now writing an AsyncController is very clean:

public class HomeController : AsyncController
{
    public ActionResult Index()
    {
        return View(new LandingPageUser());
    }

    [HttpPost]
    public async Task<ActionResult> Index(LandingPageUser model)
    {
        // Check if the model is valid and try to Save it to the Database
        if (ModelState.IsValid && model.Save(ModelState))
        {
            // DO YOUR WORK
            // (...)

            // Integrate with SalesForce and send in the request
            if (Boolean.Parse(ConfigurationManager.AppSettings["EnableSalesforceRegistrations"]))
                await SalesForceExtensions.SubmitRequest(model);

            return View("Success");
        }

        return View(model);
    }
}