
La bibliothèque Twilio Helper pour ASP.NET (Twilio.Aspnet) vous aide à intégrer le SDK Twilio officiel pour C # et .NET dans vos applications ASP.NET. La bibliothèque prend en charge ASP.NET MVC sur .NET Framework et ASP.NET Core.
Cette bibliothèque vous aide à répondre aux webhooks, ajoute le client Twilio au conteneur d'injection de dépendance et valider la demande HTTP provient de Twilio.
Nécessite .NET 6.0 ou version ultérieure.
Exécutez la commande suivante pour installer le package à l'aide de la CLI .NET:
dotnet add package Twilio.AspNet.CoreAlternativement, à partir de la console du gestionnaire de packages ou du développeur PowerShell, exécutez la commande suivante pour installer la dernière version:
Install-Package Twilio.AspNet.CoreAlternativement, utilisez le NUGET Package Manager pour Visual Studio ou la fenêtre NuGet pour JetBrains Rider, puis recherchez Twilio.Aspnet.Core et installez le package.
Nécessite .NET 4.6.2 ou version ultérieure.
Depuis la console de Package Manager ou le développeur PowerShell, exécutez la commande suivante pour installer la dernière version:
Install-Package Twilio.AspNet.MvcAlternativement, utilisez le NUGET Package Manager pour Visual Studio ou la fenêtre NuGet pour JetBrains Rider, puis recherchez Twilio.Aspnet.mvc et installez le package.
using Twilio . AspNet . Common ;
using Twilio . AspNet . Core ; // or .Mvc for .NET Framework
using Twilio . TwiML ;
public class SmsController : TwilioController
{
// GET: Sms
public TwiMLResult Index ( SmsRequest request )
{
var response = new MessagingResponse ( ) ;
response . Message ( $ "Ahoy { request . From } !" ) ;
return TwiML ( response ) ;
}
} Ce contrôleur gérera le SMS WebHook. Les détails des SMS entrants seront liés au paramètre SmsRequest request . En héritant du TwilioController , vous avez accès à la méthode TwiML que vous pouvez utiliser pour répondre avec Twiml.
using Twilio . AspNet . Common ;
using Twilio . AspNet . Core ; // or .Mvc for .NET Framework
using Twilio . TwiML ;
public class VoiceController : TwilioController
{
// GET: Voice
public TwiMLResult Index ( VoiceRequest request )
{
var response = new VoiceResponse ( ) ;
response . Say ( $ "Ahoy! Are you from { request . FromCity } ?" ) ;
return TwiML ( response ) ;
}
} Ce contrôleur s'occupera de la voix Webhook. Les détails de l'appel vocal entrant seront liés au paramètre VoiceRequest request . En héritant du TwilioController , vous avez accès à la méthode TwiML que vous pouvez utiliser pour répondre avec Twiml.
TwiML au lieu de hériter de TwilioController Si vous ne pouvez pas hériter de la classe TwilioController , vous pouvez utiliser les méthodes d'extension TwiML .
using Microsoft . AspNetCore . Mvc ; // or System.Web.Mvc for .NET Framework
using Twilio . AspNet . Common ;
using Twilio . AspNet . Core ; // or .Mvc for .NET Framework
using Twilio . TwiML ;
public class SmsController : Controller
{
// GET: Sms
public TwiMLResult Index ( SmsRequest request )
{
var response = new MessagingResponse ( ) ;
response . Message ( $ "Ahoy { request . From } !" ) ;
return this . TwiML ( response ) ;
}
} Cet échantillon est le même que l'échantillon SMS WebHook précédent, mais au lieu de hériter de TwilioController , le SmsController hérite du Controller fourni par ASP.NET MVC, et utilise this.TwiML pour utiliser la méthode d'extension TwiML .
Twilio.aspnet.core soutient également les API minimales.
Cet échantillon vous montre comment vous pouvez gérer un webhook SMS à l'aide de HTTP Get and Publier.
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 ( ) ; Dans les contrôleurs MVC traditionnels, l'objet SmsRequest , VoiceRequest et d'autres objets de demande dactylographiques serait lié, mais les API minimes ne prennent pas en charge la même liaison du modèle.
Au lieu de cela, vous pouvez lier les paramètres individuels pour les demandes de GET HTTP à l'aide de l'attribut FromQuery . Lorsque vous ne spécifiez pas l'attribut FromQuery, plusieurs sources seront considérées comme se liant à partir des paramètres de chaîne de requête. Pour les demandes de publication HTTP, vous pouvez saisir le formulaire, puis récupérer les paramètres individuels par index de chaîne.
Pour répondre avec TwIML, utilisez la méthode Results.Extensions.TwiML .
Twilio.aspnet est livré avec plusieurs classes pour vous aider à lier les données de WebHooks à des objets .NET fortement typés. Voici la liste des classes:
SmsRequest : Contient des données pour les demandes de webhook entrantesSmsStatusCallbackRequest : Contient des données pour suivre l'état de livraison d'un Twilio SMS ou MMS sortantStatusCallbackRequest : Contient des données pour suivre le statut d'un appel vocal Twilio sortantVoiceRequest : tient des données pour les appels vocaux entrantsRemarque uniquement les contrôleurs MVC et les pages de rasoir prennent en charge la liaison du modèle aux objets .NET typés. Dans les API minimales et autres scénarios, vous devrez écrire du code pour extraire les paramètres vous-même.
L'échantillon suivant montre comment accepter les SMS entrants, répondre et suivre l'état de la réponse SMS.
using Twilio . AspNet . Common ;
using Twilio . AspNet . Core ; // or .Mvc for .NET Framework
using Twilio . TwiML ;
public class SmsController : TwilioController
{
private readonly ILogger < SmsController > logger ;
public SmsController ( ILogger < SmsController > logger )
{
this . logger = logger ;
}
public TwiMLResult Index ( SmsRequest request )
{
var messagingResponse = new MessagingResponse ( ) ;
messagingResponse . Message (
body : $ "Ahoy { request . From } !" ,
action : new Uri ( "/Sms/StatusCallback" ) ,
method : Twilio . Http . HttpMethod . Post
) ;
return TwiML ( messagingResponse ) ;
}
public void StatusCallback ( SmsStatusCallbackRequest request )
{
logger . LogInformation ( "SMS Status: {Status}" , request . MessageStatus ) ;
}
} Comme indiqué dans l'échantillon ci-dessus, vous pouvez ajouter un SmsRequest en tant que paramètre, et MVC vous liera l'objet. Le code répond ensuite par un SMS avec le paramètre status et method . Lorsque l'état du SMS modifie, Twilio enverra une demande de message HTTP à StatusCallback . Vous pouvez ajouter un paramètre SmsStatusCallbackRequest , et MVC vous liera l'objet.
Dans ASP.NET Core, vous pouvez ajouter le client API Twilio REST aux services d'Asp.net Core en utilisant la méthode .AddTwilioClient , comme celle-ci:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddTwilioClient ( ) Vous pouvez maintenant demander ITwilioRestClient et TwilioRestClient via une injection de dépendance.
Vous pouvez configurer le client Twilio à l'aide de la configuration suivante:
{
"Twilio" : {
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"Client" : {
"AccountSid" : " [YOUR_ACCOUNT_SID] " ,
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"ApiKeySid" : " [YOUR_API_KEY_SID] " ,
"ApiKeySecret" : " [YOUR_API_KEY_SECRET] " ,
"CredentialType" : " [Unspecified|AuthToken|ApiKey] " ,
"Region" : null ,
"Edge" : null ,
"LogLevel" : null
}
}
}Quelques notes:
Twilio:Client:AuthToken retombe sur Twilio:AuthToken . Il vous suffit de configurer l'un d'eux.Twilio:Client:CredentialType a les valeurs valides suivantes: Unspecified , AuthToken ou ApiKey .Twilio:Client:CredentialType est facultatif et par défaut Unspecified . S'il Unspecified , que vous ayez configuré une touche API ou un jeton AUTH sera détecté.Si vous ne souhaitez pas configurer le client Twilio en utilisant la configuration .NET, vous pouvez le faire manuellement:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddTwilioClient ( ( serviceProvider , options ) =>
{
options . AccountSid = "[YOUR_ACCOUNT_SID]" ;
options . AuthToken = "[YOUR_AUTH_TOKEN]" ;
options . ApiKeySid = "[YOUR_API_KEY_SID]" ;
options . ApiKeySecret = "[YOUR_API_KEY_SECRET]" ;
options . Edge = null ;
options . Region = null ;
options . LogLevel = null ;
options . CredentialType = CredentialType . Unspecified ;
} ) ;AVERTISSEMENT NE CODEZ PAS DE CODE DU TOKET AUTH VOTRE SECRET DE VOTRE CLÉS EN CODE EN COMPRIMATEUR ET NE PAS les vérifier dans le contrôle de la source. Nous vous recommandons d'utiliser le Secrets Manager pour le développement local. Alternativement, vous pouvez utiliser des variables d'environnement, un service de coffre-fort ou d'autres techniques plus sécurisées.
Par défaut, lorsque vous appelez .AddTwilioClient , une usine client HTTP est configurée qui est utilisée pour fournir un HttpClient au client Twilio REST. Si vous souhaitez personnaliser ce client HTTP, vous pouvez le faire en remplaçant l'usine de client HTTP "Twilio", après avoir invoqué .AddTwilioClient :
builder . Services . AddTwilioClient ( ) ;
builder . Services . AddHttpClient ( "Twilio" )
. ConfigureHttpClient ( client =>
{
client . BaseAddress = new Uri ( "YOUR_PROXY_ADDRESS" ) ;
} )
. ConfigurePrimaryHttpMessageHandler ( ( ) => new HttpClientHandler
{
// same options as the Twilio C# SDK
AllowAutoRedirect = false
} ) ;Les webhooks exigent que votre point final soit accessible au public, mais cela introduit également le risque que les mauvais acteurs puissent trouver votre URL de webhook et essayer de l'abuser.
Heureusement, vous pouvez vérifier qu'une demande HTTP est originaire de Twilio. La bibliothèque Twilio.AspNet fournit un attribut qui validera la demande pour vous dans MVC. L'implémentation diffère entre la bibliothèque Twilio.AspNet.Core et Twilio.AspNet.Mvc .
Ajoutez la méthode .AddTwilioRequestValidation au démarrage:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddTwilioRequestValidation ( ) ;Configurez ensuite la validation de la demande:
{
"Twilio" : {
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"RequestValidation" : {
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"AllowLocal" : false ,
"BaseUrlOverride" : " https://??????.ngrok.io "
}
}
}Quelques notes sur la configuration:
Twilio:RequestValidation:AuthToken retombe sur Twilio:AuthToken . Il vous suffit de configurer l'un d'eux.AllowLocal sautera la validation lorsque la demande HTTP est originaire de LocalHost.BaseUrlOverride au cas où votre application serait derrière un proxy inversé ou un tunnel comme Ngrok. Le chemin d'accès de la demande actuelle sera annexé à la validation de la BaseUrlOverride de la demande.Informations Au lieu de configurer la
BaseUrlOverride, vous pouvez utiliser les en-têtes transférés au middleware pour définir le schéma, le port, l'hôte, etc. corrects sur la demande HTTP actuelle.
using Microsoft . AspNetCore . HttpOverrides ;
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddTwilioRequestValidation ( ) ;
builder . Services . Configure < ForwardedHeadersOptions > ( options => options . ForwardedHeaders = ForwardedHeaders . All ) ;
// more service configuration
var app = builder . Build ( ) ;
app . UseForwardedHeaders ( ) ;
// more request pipeline configuration
app . Run ( ) ; En conséquence, vous n'avez pas à configurer BaseUrlOverride chaque fois que vous redémarrez Ngrok ou modifiez les URL proxy inverses. Suivez les conseils de Microsoft pour configurer en toute sécurité le middleware en-tête transmis.
Vous pouvez également configurer manuellement la validation de la demande:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services
. AddTwilioRequestValidation ( ( serviceProvider , options ) =>
{
options . AuthToken = "[YOUR_AUTH_TOKEN]" ;
options . AllowLocal = false ;
options . BaseUrlOverride = "https://??????.ngrok.io" ;
} ) ;AVERTISSEMENT NE CODEZ PAS VOTRE TOKEN AUTH en code et ne les vérifiez pas dans le contrôle de la source. Nous vous recommandons d'utiliser le Secrets Manager pour le développement local. Alternativement, vous pouvez utiliser des variables d'environnement, un service de coffre-fort ou d'autres techniques plus sécurisées.
Une fois la validation de la demande configurée, vous pouvez utiliser l'attribut [ValidateRequest] dans MVC. Vous pouvez appliquer l'attribut à l'échelle mondiale, aux zones MVC, aux contrôleurs et aux actions. Voici un exemple où l'attribut est appliqué à l'action Index :
using Twilio . AspNet . Common ;
using Twilio . AspNet . Core ;
using Twilio . TwiML ;
public class SmsController : TwilioController
{
[ ValidateRequest ]
public TwiMLResult Index ( SmsRequest request )
{
var response = new MessagingResponse ( ) ;
response . Message ( "Ahoy!" ) ;
return TwiML ( response ) ;
}
} .NET 7 présente le concept de filtres de point de terminaison que vous pouvez appliquer à n'importe quel point de terminaison ASP.NET Core. La bibliothèque d'assistance pour ASP.NET Core a ajouté un filtre de point de terminaison pour valider les demandes Twilio appelées ValidateTwilioRequestFilter .
Vous pouvez ajouter ce filtre à n'importe quel groupe de points de terminaison ou point de terminaison en utilisant la méthode ValidateTwilioRequest :
// add filter to endpoint
app . MapPost ( "/sms" , ( ) => .. . )
. ValidateTwilioRequest ( ) ;
// add filter to endpoint group
var twilioGroup = app . MapGroup ( "/twilio" ) ;
twilioGroup . ValidateTwilioRequest ( ) ;
twilioGroup . MapPost ( "/sms" , ( ) => .. . ) ;
twilioGroup . MapPost ( "/voice" , ( ) => .. . ) ;Alternativement, vous pouvez ajouter vous-même le filtre de point final:
app . MapPost ( "/sms" , ( ) => .. . )
. AddEndpointFilter < ValidateTwilioRequestFilter > ( ) ; Lorsque vous ne pouvez pas utiliser le filtre [ValidateRequest] ou ValidateTwilioRequestFilter , vous pouvez utiliser ValidateTwilioRequestMiddleware . Vous pouvez ajouter d'ajouter le ValidateTwilioRequestFilter comme ceci:
app . UseTwilioRequestValidation ( ) ;
// or the equivalent: app.UseMiddleware<ValidateTwilioRequestMiddleware>(); Ce middleware effectuera la validation de toutes les demandes. Si vous ne souhaitez pas appliquer la validation à toutes les demandes, vous pouvez utiliser app.UseWhen() pour exécuter le middleware conditionnellement.
Voici un exemple de la façon de valider les demandes qui commencent par Path / Twilio-Media , afin de protéger les fichiers multimédias que seul le proxy Twilio devrait pouvoir accéder:
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 ( ) ; Dans votre web.config, vous pouvez configurer la validation de la demande comme indiqué ci-dessous:
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< configuration >
< configSections >
< sectionGroup name = " twilio " type = " Twilio.AspNet.Mvc.TwilioSectionGroup,Twilio.AspNet.Mvc " >
< section name = " requestValidation " type = " Twilio.AspNet.Mvc.RequestValidationConfigurationSection,Twilio.AspNet.Mvc " />
</ sectionGroup >
</ configSections >
< twilio >
< requestValidation
authToken = " [YOUR_AUTH_TOKEN] "
baseUrlOverride = " https://??????.ngrok.io "
allowLocal = " false "
/>
</ twilio >
</ configuration >Vous pouvez également configurer la validation de la demande à l'aide des paramètres de l'application:
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< configuration >
< appSettings >
< add key = " twilio:requestValidation:authToken " value = " [YOUR_AUTH_TOKEN] " />
< add key = " twilio:requestValidation:baseUrlOverride " value = " https://??????.ngrok.io " />
< add key = " twilio:requestValidation:allowLocal " value = " false " />
</ appSettings >
</ configuration > Si vous configurez la validation de la demande à l'aide des deux voies, le paramètre de l'application écrasera l'élément de configuration twilio/requestValidation .
Quelques notes sur la configuration:
allowLocal sautera la validation lorsque la demande HTTP est originaire de LocalHost.baseUrlOverride au cas où vous êtes devant un proxy inversé ou un tunnel comme Ngrok. Le chemin d'accès de la demande actuelle sera annexé à la validation de la baseUrlOverride de la demande.AVERTISSEMENT NE CODEZ PAS VOTRE TOKEN AUTH en code et ne les vérifiez pas dans le contrôle de la source. Utilisez le
UserSecretsConfigBuilderpour le développement local ou l'un des autres constructeurs de configuration. Alternativement, vous devez crypter les sections de configuration contenant des secrets comme le jeton AUTH.
Maintenant que la validation de la demande a été configurée, utilisez l'attribut [ValidateRequest] . Vous pouvez appliquer l'attribut à l'échelle mondiale, aux zones MVC, aux contrôleurs et aux actions. Voici un exemple où l'attribut est appliqué à l'action Index :
using Twilio . AspNet . Common ;
using Twilio . AspNet . Mvc ;
using Twilio . TwiML ;
public class SmsController : TwilioController
{
[ ValidateRequest ]
public TwiMLResult Index ( SmsRequest request )
{
var response = new MessagingResponse ( ) ;
response . Message ( "Ahoy!" ) ;
return TwiML ( response ) ;
}
} L'attribut [ValidateRequest] fonctionne uniquement pour MVC. Si vous avez besoin de valider les demandes en dehors de MVC, vous pouvez utiliser la classe de RequestValidationHelper fournie par Twilio.AspNet . Alternativement, la classe RequestValidator du SDK Twilio peut également vous aider.
Voici un exemple API minimal qui valide la demande entrante provenant de Twilio:
using System . Net ;
using Microsoft . Extensions . Options ;
using Twilio . AspNet . Core ;
using Twilio . AspNet . Core . MinimalApi ;
using Twilio . TwiML ;
var builder = WebApplication . CreateBuilder ( args ) ;
// adds TwilioRequestValidationOptions
builder . Services . AddTwilioRequestValidation ( ) ;
var app = builder . Build ( ) ;
app . MapPost ( "/sms" , ( HttpContext httpContext ) =>
{
if ( IsValidTwilioRequest ( httpContext ) == false )
return Results . StatusCode ( ( int ) HttpStatusCode . Forbidden ) ;
var messagingResponse = new MessagingResponse ( ) ;
messagingResponse . Message ( "Ahoy!" ) ;
return Results . Extensions . TwiML ( messagingResponse ) ;
} ) ;
app . Run ( ) ;
bool IsValidTwilioRequest ( HttpContext httpContext )
{
var options = httpContext . RequestServices
. GetService < IOptions < TwilioRequestValidationOptions > > ( )
? . Value ?? throw new Exception ( "TwilioRequestValidationOptions missing." ) ;
string ? urlOverride = null ;
if ( options . BaseUrlOverride is not null )
{
var request = httpContext . Request ;
urlOverride = $ " { options . BaseUrlOverride . TrimEnd ( '/' ) } { request . Path } { request . QueryString } " ;
}
return RequestValidationHelper . IsValidRequest ( httpContext , options . AuthToken , urlOverride , options . AllowLocal ) ;
} AddTwilioRequestValidation ajoute les TwilioRequestValidationOptions , qui est normalement utilisée pour l'attribut [ValidateRequest] , mais dans cet échantillon, il est utilisé pour récupérer la configuration de la validation de la demande vous-même. Ensuite, à l'intérieur du point de terminaison / SMS , la méthode IsValidTwilioRequest est utilisée pour valider la demande. IsValidTwilioRequest récupère les options de validation de la demande de DI et effectue la même logique que [ValidateRequest] ferait pour les demandes MVC. Si la demande n'est pas valide, le code d'état HTTP 403 est renvoyé, sinon, un Twiml est renvoyé à Twilio.