What's new in the Twilio helper library for ASP.NET (v5.73.0 - April 2022)
Niels Swimberghe - - .NET
Follow me on Twitter, buy me a coffee
This blog post was written for Twilio and originally published at the Twilio blog.
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 with very common use cases like:
- Responding to Twilio webhook requests with TwiML objects from the official Twilio SDK for C# and .NET.
- Binding data from Twilio webhook requests to strongly typed .NET objects.
- Validating webhook requests originate from Twilio and rejecting them if not.
As .NET and ASP.NET is evolving, the Twilio.AspNet contributors are enhancing the library to take advantage of the newest capabilities and best practices. So what's new?
What's old in Twilio.AspNet #
Actually, before I share the shiny new additions, let me share what is already part of the library. After all, this is the first blog post to share news about the library.
Handle Twilio webhook requests with ASP.NET #
In previous versions of Twilio.AspNet, you could create a controller to respond to Twilio webhooks like this:
using Twilio.AspNet.Common; using Twilio.AspNet.Core; // or .Mvc for .NET Framework using Twilio.TwiML; public class SmsController : TwilioController { public TwiMLResult Index(SmsRequest request) { var response = new MessagingResponse(); response.Message($"Ahoy {request.From}!"); return TwiML(response); } }
If you're using the routing convention that comes out-of-the-box with MVC, this action can be reached via the path /Sms/Index or /Sms (Index is the default). When you configure the URL with this path as your Twilio messaging webhook, the Index
action will start receiving the messages sent to your Twilio Phone Number. When a webhook request comes in:
- The HTTP request data will be bound to the
SmsRequest
parameter. This way you can conveniently inspect the data using a strongly typed .NET object. The SmsRequest class is provided by the Twilio.AspNet library. - The code will then create a new
MessagingResponse
which is a TwiML class from the official Twilio SDK for C# and .NET.response.Message
will create TwiML instructions to respond with a message that looks like "Ahoy +11234567890!". - The
TwiML
method accepts theTwiML
object and creates aTwiMLResult
which will write the TwiML to the HTTP response. ThisTwiML
method is inherited from the TwilioController class provided by the Twilio.AspNet library.
As a result, when someone texts your Twilio Phone Number, Twilio will send a text message back saying "Ahoy +11234567890!".
Similarly, you can also respond to voice calls as shown in this sample:
using Twilio.AspNet.Common; using Twilio.AspNet.Core; // or .Mvc for .NET Framework using Twilio.TwiML; public class VoiceController : TwilioController { public TwiMLResult Index(VoiceRequest request) { var response = new VoiceResponse(); response.Say($"Ahoy! Are you from {request.FromCity}?"); return TwiML(response); } }
After configuring the voice webhook, when the phone number receives a phone call, Twilio will send an HTTP request to the Index
action. The data from the HTTP request will be bound to the VoiceRequest
parameter. This data is then used to construct TwiML instructions. For example, when I call the phone number, it would transcribe the message to audio and say "Ahoy! Are you from BELTSVILLE?".
Secure your Twilio webhook #
Webhooks by its very nature have to be publicly accessible to the internet, otherwise Twilio can't send HTTP requests to them. As a result, everyone else can also send HTTP requests to your webhook. To make sure HTTP requests originate from Twilio and not some bad actor, you can add the ValidateRequest
attribute to your controllers or actions. This attribute will verify the signature of the HTTP request to ensure the request originated from Twilio.
What's new in Twilio.AspNet #
In recent months, a couple of new versions of the Twilio.AspNet library have been released with the latest being version 5.73.0. Here's an overview of the changes:
- 🎉 NEW FEATURES
You can find more information about these new features later in the article.
- 🙌 ENHANCEMENTS
- The project files and build scripts have been updated. (PR #52)
- The .NET Framework based project files have been updated to use the new SDK-style project files. Now you can use the same .NET CLI commands to build and test the .NET Framework projects as you can with the .NET (Core) projects. As a result, it's easier to build, test, and pack the projects for this library.
- With the increased consistency, the build scripts have also been updated and no longer rely on the nuget and xunit executables that were previously embedded in the repository.
- The README.md file has been updated to refresh outdated information and include more samples on how to use the library. (PR #48, PR #50)
- A new CHANGELOG.md file has been created so users can quickly learn about enhancements, bug fixes, and breaking changes whenever a new version is released. (PR #52)
- The metadata of the NuGet packages has been updated to refresh outdated information. This metadata is shown in places like NuGet.org, the NuGet Package Manager for Visual Studio, and the NuGet window for JetBrains Rider (PR #52)
- 🪳 BUG FIXES
- A bug was fixed where Swagger would complain about the
TwiML
methods when inheriting from theTwilioController
. (PR #43)
TwiML for Minimal API #
ASP.NET Core 6 introduced a new way to write web APIs that sparks joy, and now Twilio.AspNet.Core has support to return TwiML
in Minimal APIs just like you could before with controllers.
Here's an example with C#:
using Microsoft.AspNetCore.Mvc; using Twilio.AspNet.Core.MinimalApi; using Twilio.TwiML; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/sms", ([FromQuery] string from) => { var response = new MessagingResponse(); response.Message($"Ahoy {from}!"); return Results.Extensions.TwiML(response); }); app.MapPost("/sms", async (HttpRequest request) => { var form = await request.ReadFormAsync(); var from = form["from"]; response.Message($"Ahoy {from}!"); return Results.Extensions.TwiML(response); }); app.Run();
When Twilio sends an HTTP POST or GET request to your /sms webhook, it will be handled by one of the two endpoints defined above. Both endpoints do exactly the same as the prior MVC controller example.
Unfortunately, Minimal APIs do not support the same data binding from HTTP request data to parameters that MVC does. For HTTP GET requests, you have to bind individual query string parameters using the [FromQuery]
attributes to .NET parameters with simple data types like strings, integers, floats, doubles, etc.
For HTTP POST requests, you have to accept the HttpRequest
as a parameter and manually retrieve the desired parameters from the Form
property.
Lastly, the TwiMLResponse
is passed to the Results.Extensions.TwiML
method which will create a TwiMLResult
that will take care of writing the TwiML
to the HTTP response body. The Results.Extensions.TwiML
is an extension method that you can import by using the Twilio.AspNet.Core.MinimalApi
namespace.
For voice calls, you can use a VoiceResponse
instead of a MessagingResponse
, everything else works the same.
TwiML extension methods for controllers #
As shown in the first sample in this article, you can let your controller inherit from TwilioController
which gives you access to the TwiML
methods. These TwiML
methods create a TwiMLResult
object which takes care of writing the TwiML to the HTTP response body. However, if your controller already inherits from another base class, you can't also inherit from TwilioController
. It's one or the other. That's why Twilio.AspNet (.Core and .Mvc) now has the same methods as extension methods. You can now use this.TwiML
to return TwiML
objects in controllers. Here's the same MVC example using the TwiML
extension methods instead of the methods from the TwilioController
.
using Twilio.AspNet.Common; using Twilio.AspNet.Core; // or .Mvc for .NET Framework using Twilio.TwiML; public class SmsController : Controller { public TwiMLResult Index(SmsRequest request) { var response = new MessagingResponse(); response.Message($"Ahoy {request.From}!"); return this.TwiML(response); } }
You can also use a VoiceResponse
instead of a MessagingResponse
to return TwiML for Voice webhooks.
Go use the shiny new bits #
You can take advantage of these new features and enhancements 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 us a star on the GitHub repo and 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 @TwilioDevs and @RealSwimburger on Twitter or LinkedIn.