What's new in the Twilio helper library for ASP.NET (v6.0.0 - August 2022)
Time to read: 7 minutes
The Twilio helper library for ASP.NET (Twilio.AspNet) is a community-driven open-source project to make integrating Twilio with ASP.NET easier, for both ASP.NET Core and ASP.NET MVC on .NET Framework. The library helps you achieve common use cases and with the release of version 6, we're expanding the library's capabilities and improving existing features.
What's new in Twilio.AspNet v6.0.0
V6.0.0 is a major release of the Twilio.AspNet library because it contains breaking changes. Starting from this release, version numbers do not match the version of the Twilio .NET SDK.
Here's an overview of the changes:
🎉 NEW FEATURES
- You can now add the
TwilioRestClient
to ASP.NET Core's dependency injection (DI) container, using the.AddTwilioClient
method. This Twilio client will use anHttpClient
provided by the HTTP client factory. You can find more information about this new feature later in the article.
🙌 ENHANCEMENTS
- Big breaking change to the
[ValidateRequest]
attribute. The attribute no longer accepts parameters or properties. Instead, you have to configure the request validation elsewhere. In ASP.NET Core, you can configure request validation using .NET Configuration or using code. In ASP.NET MVC on .NET Framework, you can configure request validation in the Web.config file using thetwilio/requestValidation
configuration element, or using app settings. You can find more information about this enhancement later in the article. - We migrated the build process from AppVeyor to GitHub Actions. You can now see how we build, test, package, and push the release to nuget.org using the workflows under the Actions tab in GitHub
- The README.md file has been updated to document the new features and improvements.
Before v6.0.0, there was another small release, v5.77.0 which included the following changes:
- Twilio.AspNet.Core and Twilio.AspNet.Common now use .NET Standard 2.0 and dropped older .NET Standard versions.
- Twilio.AspNet.Mvc now targets .NET 4.6.2.
- The Microsoft.AspNetCore.Mvc.Core dependency has been updated to a more recent version. For newer versions of .NET, a framework dependency is used instead. This updated dependency also updated the transitive dependency on Microsoft.AspNetCore.Http. This was done because the old version of Microsoft.AspNetCore.Http contained a vulnerability (CVE-2020-1045).
- Twilio.AspNet.Core and Twilio.AspNet.Mvc now depend on version 5.77.0 of the Twilio package.
Add Twilio API client to the dependency injection container
Background on TwilioClient and TwilioRestClient
The Twilio .NET SDK provides a static TwilioClient
class to authenticate:
Once initialized, you can interact with the API resource classes, for example, here's how you can send an SMS using the MessageResource
class.
This is the quick and easy approach you will find in most of our documentation, however, there's another way. Instead of using the static TwilioClient
class, you can create a TwilioRestClient
and pass it in as a parameter when interacting with the API resource classes.
Here's what that would look like for the same SMS example:
You may be wondering, why would you want to use the TwilioRestClient
instead of the static TwilioClient
?
- You cannot have multiple instances or any instances of a static class. So if your application needs to authenticate with multiple Twilio accounts, like in a multi-tenant app, you cannot do that with the static
TwilioClient
, but you can support this scenario using theTwilioRestClient
. - .NET developers generally don't like using static classes because it makes their code less maintainable and harder to test. By using the
TwilioRestClient
class and theITwilioRestClient
interface, you can use the inversion of control (IoC) principle and more easily mock the clients which makes it easier to test.
New: Add TwilioRestClient as a service
Now that you know how to use the TwilioRestClient
and why you'd want to, let's take a look at the new feature that is introduced in v6.0.0.
You can now add the TwilioRestClient
to ASP.NET Core's services using the .AddTwilioClient
method:
Once the client is added, you can request ITwilioRestClient
and TwilioRestClient
via dependency injection. For example, here's how you can receive the client via the constructor of a controller, and then send the same SMS as before:
Before you can run this code, you need to configure the Twilio client, which is done through standard .NET configuration. Here's what the configuration would look like in JSON:
A couple of notes:
- You can configure
Twilio:AuthToken
whichTwilio:Client:AuthToken
will fall back to. Twilio:Client:CredentialType
has the following valid values:Unspecified
,AuthToken
, orApiKey
.- When using
AuthToken
, you only need to configure theAccountSid
and theAuthToken
. - When using
ApiKey
, you only need to configure theApiKeySid
and theApiKeySecret
.
- When using
Twilio:Client:CredentialType
is optional and defaults toUnspecified
.- If
Unspecified
, whether you configured an API Key or an Auth Token will be detected. - If
Unspecified
and the API Key and Auth Token are both configured, the API Key will be used as it is the preferred way to authenticate.
- If
If you do not wish to configure the Twilio client using configuration, you can do so through code:
Improved HTTP client
TwilioClient
and TwilioRestClient
use the HttpClient
class to send HTTP requests to the Twilio APIs.
Unless you pass in your own HTTP client to the TwilioRestClient
constructor, it will create a new HttpClient
for every instance. Since the TwilioClient
holds on to a singleton of TwilioRestClient
, TwilioClient
will use a single HttpClient
until you restart your application which can lead to DNS stalenes. On the other hand, if you create a new TwilioRestClient
for every API call, a new HttpClient
will also be created for every API call which could lead to socket exhaustion.
By using TwilioRestClient
instead of the static TwilioClient
, you already avoid the DNS staleness issues, but you could still run out of network sockets. To avoid this issue and improve performance, .AddTwilioClient
uses the HTTP client factory APIs to retrieve an HttpClient
and supplies it to the TwilioRestClient
constructor.
In short, using the TwilioRestClient
configured by .AddTwilioClient
is more reliable and performant.
HttpClient
objects created by the HTTP client factory are also configured to log HTTP requests. You can control the log level via configuration using the following log categories: System.Net.Http.HttpClient.Twilio.LogicalHandler
and System.Net.Http.HttpClient.Twilio.ClientHandler
.
Here's how you set the log level to Information
using appsettings.json:
If for some reason you do need to change the way the HttpClient
is supplied to TwilioRestClient
, you can pass in a callback method to .AddTwilioClient
. You need this if you want to use a forward proxy.
Here's an example that creates a new HttpClient
for every instance of TwilioRestClient
that is requested using DI:
The above code is for the sake of demonstration and could lead to port exhaustion issues again. When you supply your own HttpClient
, we still recommend you follow the best practices by using the HTTP client factory APIs.
Validate HTTP requests coming from Twilio
Your web application has to be publicly available for Twilio to send webhook requests to it. However, this means that anyone can send HTTP requests to your application which could be exploited. Luckily, you can secure your webhooks by validating the X-Twilio-Signature
HTTP header.
To make request validation easier and more closely integrated with MVC, Twilio.AspNet provides the [ValidateRequest]
attribute. Before v6.0.0, you could apply the attribute in places like controllers and actions like this:
Now any requests made to the SmsController.Index
action would first be validated by the ValidateRequest
attribute and if the request did not originate from Twilio, an HTTP 403 Forbidden status code would be responded with.
This worked great, but you had to configure the request validation in code, which introduced some challenges:
- Hard-coding the auth token into code meant that this sensitive secret would be embedded in the DLL-files and also tracked in source control systems, both of which increased the chance of leaking the auth token.
- Depending on where you're deploying your application (dev/staging/production environments), your configuration would be hard-coded and could not be changed. Each environment may require a different configuration, but there's no easy way to do that.
To resolve these issues, we had to remove the constructor parameters and properties from the ValidateRequest
attribute and use external configuration to configure request validation.
Going forward from v6.0.0, use the ValidateRequest
attribute without any parameters.
Next, you'll need to configure request validation, but this is done differently depending on whether you're using ASP.NET Core or ASP.NET MVC on .NET Framework.
On ASP.NET Core, add .AddTwilioRequestValidation()
to your startup.
Then use .NET configuration to configure the request validation. Here's the JSON representation of the configuration:
A couple of notes about the configuration:
- You can configure
Twilio:AuthToken
whichTwilio:RequestValidation:AuthToken
will fall back to. AllowLocal
will skip validation when the HTTP request originated from localhost.- Use
BaseUrlOverride
in case your app is behind a reverse proxy or a tunnel like ngrok. The path of the current request will be appended to theBaseUrlOverride
for request validation.
You can also configure request validation using code:
That's it! Now you can use external configuration like JSON files, environment variables, user-secrets, etc. to configure request validation. This makes your application easier to deploy to other environments.
For ASP.NET MVC on .NET Framework, you can configure request validation using the Web.config file using the twilio/requestValidation
configuration element:
Alternatively, you can configure request validation using app settings:
Now that request validation is configured, you can apply the ValidateRequest
attribute to your MVC apps globally, regions, controllers, and actions to protect your endpoints.
Go use the shiny new bits
You can take advantage of these new features and enhancements now by installing the latest version of the Twilio helper library for ASP.NET. You can find the installation instructions in the readme of the Twilio.AspNet GitHub repository. If you like this library, consider giving it a star on the GitHub repo. Also you are welcome to submit an issue if you run into problems.
We can't wait to see what you'll build with Twilio.AspNet. Let us know on social media and don't forget to mention @TwilioDevs and @RealSwimburger on Twitter or LinkedIn.
Niels Swimberghe is a Belgian American software engineer and technical content creator at Twilio. Get in touch with Niels on Twitter @RealSwimburger and follow Niels’ personal blog on .NET, Azure, and web development at swimburger.net.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.