Subscribe users to a Mailchimp newsletter from .NET/C# π§π΅
You have spent a lot of time building your high-quality newsletter and now you want people to sign up. Including the usual <script>
element, provided by Mailchimp, on your website is easy. But what if you want to ask people to subscribe as part of signing up as a user on your .NET website? In this post, I'll show you how to manage Mailchimp subscriptions from C#.
For the example code in this post, I'll use an ASP.NET Core website. This could be anything .NET really but asking a user to subscribe to your newsletter as part of signing up for a new user covers a common scenario.
If you want to code along, remember to enable Individual User Accounts when creating the ASP.NET Core application. This will include a /register
path in your application where we can include the newsletter signup:
ASP.NET Core comes with a range of scaffolded files when enabling security through the wizard. By default, these files are not available for you to modify. To do that, right-click the project and select Add | New Scaffolded Item:
Next, select Identity:
And finally, select Account\Register Β and the Entity Framework context generated for your project:
You now have a registering page razor page located in Areas\Identity\Pages\Account\Register.cshtml
. Before we start modifying that file, let's initialize the classes needed to talk with Mailchimp. I'll use the excellent package MailChimp.Net.V3
by Brandon Seydel for this post. Install it using NuGet:
dotnet add package MailChimp.Net.V3
I'll use dependency injection for the manager class available in the Mailchimp package. Add the following code to the ConfigureServices
method in the Startup.cs
file:
var mailchimpManager = new MailChimpManager("API_KEY");
services.AddSingleton<IMailChimpManager>(mailchimpManager);
You want to replace API_KEY
with your own API key available from Mailchimp here: https://us1.admin.mailchimp.com/account/api/
.
Injecting the IMailChimpManager
can be done using a simple constructor injection in the Register.cshtml.cs
file:
private readonly IMailChimpManager _mailchimpManager;
public RegisterModel(
/* ... */
IMailChimpManager mailchimpManager)
{
/* ... */
_mailchimpManager = mailchimpManager;
}
We want to accept an additional boolean when signing up the user, indicating if the user wants to sign up for the newsletter or not. In the same file, add a new boolean to the InputModel
class:
public bool NewsletterSubscribe { get; set; }
And finally, in the OnPostAsync
method, include the following code just before redirecting the user:
if (Input.NewsletterSubscribe)
{
var member = new MailChimp.Net.Models.Member
{
EmailAddress = Input.Email,
StatusIfNew = MailChimp.Net.Models.Status.Subscribed,
};
await _mailchimpManager.Members.AddOrUpdateAsync("AUDIENCE_ID", member);
}
This code will subscribe the user's email to the specified audience. You will need to replace AUDIENCE_ID
with the Audience ID available through Mailchimp:
In case you are using double signup, where the user needs to approve the membership through email, you need to the StatusIfNew
to Pending
:
StatusIfNew = MailChimp.Net.Models.Status.Pending
The only missing step now is to extend the UI. Insert the following code just after the confirm password field in Register.cshtml
:
<div class="form-group">
<label asp-for="Input.NewsletterSubscribe"></label>
<input asp-for="Input.NewsletterSubscribe" class="form-control" />
</div>
This will show a huge ugly checkbox data-bound to the NewsletterSubscribe
boolean property that we created on the InputModel
class:
That's it. When the user clicks this checkbox and clicks Register, the POST action automatically signs up the user for your email list at Mailchimp.
Error handling
In my experience, thinking about error handling when integrating with the Mailchimp API is an important aspect. The API fails from time to time with both timeouts and other types of exceptions. Depending on which logging framework you use, logging errors is straight-forward using a try-catch:
try
{
await _mailchimpManager.Members.AddOrUpdateAsync("AUDIENCE_ID", member);
return true;
}
catch (Exception e)
{
logger.LogError(e, "Error during add or update member");
return false;
}
In this example, I'm returning a boolean indicating if the member is added or not. You'd normally not implement control flow using try-catch, but I'm afraid there's no other way to check if the Mailchimp API will accept the request or not, besides making it and observing if it fails.
Retry
As already mentioned, there's a range of exceptions that can happen when communicating with the Mailchimp API. One of them is a timeout, which may be fixed by waiting a few seconds and trying again. To implement retry you can install Polly
:
dotnet add package Polly
Then wrap the call to AddOrUpdateAsync
in a retry policy and tell Polly to only retry on timeouts:
await Policy
.Handle<SocketException>()
.WaitAndRetryAsync(3, i => new TimeSpan(0, 0, 0, i * 1))
.ExecuteAsync(async () =>
{
await _mailchimpManager.Members.AddOrUpdateAsync("AUDIENCE_ID", member);
});
This code will call the AddOrUpdateAsync
method and retry it three times in case a SocketException
is thrown.