This content originally appeared on Twilio Blog and was authored by Niels Swimberghe
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 7, we're expanding the library's capabilities and improving existing features.
Wondering what was previously introduced? You can read about v6 and prior releases here.
What's new in Twilio.AspNet v7.0.0
V7.0.0 is a major release of the Twilio.AspNet library because it contains breaking changes.
Here's an overview of the changes:
🎉 NEW FEATURES
- You can now use the
ValidateTwilioRequestFilter
to validate that HTTP requests originate from Twilio. This adds validation to endpoints including Minimal APIs. - You can also use the new
ValidateTwilioRequestMiddleware
to validate Twilio requests for when you can't use the[ValidateRequest]
attribute or theValidateTwilioRequestFilter
. - There are new overloads for the
TwiMLResult
constructor and for theTwiML
methods that let you specify how to format the TwiML in the HTTP response body. This lets you remove whitespace to minimize the payload size. - The
VoiceResponse
andMessagingResponse
class has a new extension methodToTwiMLResult()
that will create aTwiMLResult
for you.
🙌 ENHANCEMENTS
- The
SmsRequest
andVoiceRequest
class has been updated with parameters that were missing. Twilio.AspNet.Core
andTwilio.AspNet.Mvc
now depend on version 6 of the Twilio C# helper library.
⚠️ BREAKING CHANGES
- You can no longer pass in a
string
orXDocument
into theTwiMLResult
constructor. You can find guidance on how to update your code in this GitHub Gist. - The public properties on
TwiMLResult
have been removed. - The
HttpRequest.IsLocal()
extension method has been removed. - The
HttpStatusCodeResult
class has been removed in favor ofStatusCodeResult
provided by ASP.NET Core MVC andHttpStatusCodeResult
by ASP.NET MVC on .NET Framework. - The
Twilio.AspNet.Core.MinimalApi
namespace has been removed. Types from the namespace have moved to theTwilio.AspNet.Core
namespace. - The
RequestValidationHelper
class is now static. You'll need to change your code to not instantiate this class and call its methods in a static manner instead.
Validate Twilio requests in endpoints and minimal APIs
To integrate with Twilio webhooks, your webhook handlers have to be publicly accessible on the internet. That means everyone else can access your webhook handlers – including malicious actors. This is why you have to validate that the incoming HTTP request originates from Twilio.
The helper library for ASP.NET has multiple ways to perform this validation. First of all, you need to configure Twilio request validation by calling .AddTwilioRequestValidation()
during startup:
using Twilio.AspNet.Core;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTwilioRequestValidation();
Then you need to use .NET configuration to configure the request validation. Here's the JSON representation of the configuration:
{
"Twilio": {
"RequestValidation": {
"AuthToken": "[YOUR_AUTH_TOKEN]",
"AllowLocal": true,
"BaseUrlOverride": "https://??????.ngrok.io"
}
}
}
While the example above shows the JSON representation of the configuration, you can use any configuration provider plugged into your application. The AuthToken
in particular should not be stored in your appsettings.json file. Instead, use user-secrets, a vault service, or environment variables instead.
Now that request validation is configured, you can apply the [ValidateRequest]
attribute to your controllers and actions in ASP.NET Core MVC. However, until now, there was no way to validate requests outside of MVC. In v7 there are two new ways to validate requests outside of MVC, using the ValidateTwilioRequestFilter
for endpoints and Minimal APIs, and using the ValidateTwilioRequestMiddleware
which is discussed in more detail later.
ValidateTwilioRequestFilter
relies on the new endpoint filters introduced in ASP.NET Core 7, which means this feature is only available when you install the library into an ASP.NET Core 7 project.
Here's how you can add request validation using the new ValidateTwilioRequestFilter
:
using Twilio.AspNet.Core;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTwilioRequestValidation();
var app = builder.Build();
app.MapPost("/sms", () => ...)
.ValidateTwilioRequest();
app.Run();
Before the /sms endpoint is executed, the ValidateTwilioRequestFilter
will validate that the HTTP requests originate from Twilio.
ValidateTwilioRequest()
is a convenience extension method and is the equivalent of the following code:
app.MapPost("/sms", () => ...)
.AddEndpointFilter<ValidateTwilioRequestFilter>();
ASP.NET Core 7 also introduced endpoint groups, which you can also apply the request validation to:
var twilioGroup = app.MapGroup("/twilio");
twilioGroup.ValidateTwilioRequest();
{
twilioGroup.MapPost("/sms", () => ...);
twilioGroup.MapPost("/voice", () => ...);
}
Now HTTP POST requests going to /twilio/sms and /twilio/voice will first be validated by the ValidateTwilioRequestFilter
.
You can specify an empty path when creating an endpoint group. This can be helpful if you want to apply request validation to all endpoints in a group, but you don't want to prefix the paths of your endpoints.
Validate Twilio requests using middleware
If you can't use the [ValidateRequest]
attribute or the new ValidateTwilioRequestFilter
, you can now plug the ValidateTwilioRequestMiddleware
into your request pipeline. Keep in mind that the middleware will run for all HTTP requests unless you conditionally apply the middleware using MapWhen
or UseWhen
.
The ValidateTwilioRequestMiddleware
is particularly useful for serving static media files that only Twilio should have access to, because middleware is the only way to hook into the HTTP requests for static files. Here's how you would serve static files with Twilio request validation:
using System.Net;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using Twilio.AspNet.Core;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTwilioRequestValidation();
var app = builder.Build();
app.UseWhen(
context => context.Request.Path.StartsWithSegments("/twilio-media", StringComparison.OrdinalIgnoreCase),
app => app.UseTwilioRequestValidation()
);
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "TwilioMedia")),
RequestPath = "/twilio-media"
});
app.Run();
The ValidateTwilioRequestMiddleware
is added by the app.UseTwilioRequestValidation()
extension method. However, this middleware only runs when the path of the incoming HTTP request starts with /twilio-media because it is conditionally added using app.UseWhen
.
The media files are stored in a subfolder called TwilioMedia and served at the path /twilio-media. When those media files are requested, the ValidateTwilioRequestMiddleware
validates the HTTP request before returning the file. However, other HTTP requests are unaffected.
Remove whitespace from your TwiML response
There are now overloads for the TwiML
methods and the TwiMLResult
constructor that let you specify the formatting of the TwiML using the System.Xml.Linq.SaveOptions
enum. By specifying SaveOptions.DisableFormatting
, there will be no formatting for the TwiML written to the HTTP response body. This will remove the whitespace and indentation from the resulting XML.
Here's an example of this using Minimal APIs:
using System.Xml.Linq;
using Twilio.AspNet.Core;
using Twilio.TwiML;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/message", () =>
{
var response = new MessagingResponse();
response.Message("Ahoy!");
return Results.Extensions.TwiML(response, SaveOptions.DisableFormatting);
});
app.Run();
The response body would normally look like this:
<?xml version="1.0" encoding="utf-8"?>
<Response>
<Message>Ahoy!</Message>
</Response>
However, with formatting removed, the response body looks like this:
<?xml version="1.0" encoding="utf-8"?><Response><Message>Ahoy!</Message></Response>
The ToTwiMLResult() extension method
The ToTwiMLResult()
method extends the MessagingResponse
and VoiceResponse
classes, so you can more fluently create a TwiMLResult
.
Here's how you'd create a TwiMLResult
in Minimal API without ToTwiMLResult()
:
app.MapPost("/message", () =>
{
var response = new MessagingResponse()
.Message("Ahoy!");
return Results.Extensions.TwiML(response);
});
This is the same code using the ToTwiMLResult
extension method:
app.MapPost("/message", () => new MessagingResponse()
.Message("Ahoy!")
.ToTwiMLResult()
);
The ToTwiMLResult()
also works in ASP.NET Core MVC.
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, and a Microsoft MVP in Developer Technologies. Get in touch with Niels on Twitter @RealSwimburger and follow Niels’ personal blog on .NET, Azure, and web development at swimburger.net.
This content originally appeared on Twilio Blog and was authored by Niels Swimberghe
Niels Swimberghe | Sciencx (2022-11-18T17:18:30+00:00) What’s new in the Twilio helper library for ASP.NET (v7.0.0 – November 2022). Retrieved from https://www.scien.cx/2022/11/18/whats-new-in-the-twilio-helper-library-for-asp-net-v7-0-0-november-2022/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.