
A Biblioteca Twilio Helper para ASP.NET (Twilio.aspnet) ajuda a integrar o Twilio SDK oficial para C# e .NET nos seus aplicativos ASP.NET. A biblioteca suporta asp.net MVC na estrutura .net e asp.net Core.
Esta biblioteca ajuda você a responder aos webhooks, adiciona o cliente Twilio ao contêiner de injeção de dependência e valida a solicitação HTTP originada do Twilio.
Requer .NET 6.0 ou posterior.
Execute o seguinte comando para instalar o pacote usando a .NET CLI:
dotnet add package Twilio.AspNet.CoreComo alternativa, no console do gerenciador de pacotes ou desenvolvedor PowerShell, execute o seguinte comando para instalar a versão mais recente:
Install-Package Twilio.AspNet.CoreComo alternativa, use o Nuget Package Manager para o Visual Studio ou a Janela Nuget para o JetBrains Rider, procure o Twilio.aspnet.core e instale o pacote.
Requer .NET 4.6.2 ou posterior.
No console de gerenciador de pacotes ou desenvolvedor PowerShell, execute o seguinte comando para instalar a versão mais recente:
Install-Package Twilio.AspNet.MvcComo alternativa, use o Nuget Package Manager para o Visual Studio ou a Janela Nuget para o JetBrains Rider, busque o Twilio.asp.mvc e instale o pacote.
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 ) ;
}
} Este controlador lidará com o sms webhook. Os detalhes do SMS recebido estarão vinculados ao parâmetro SmsRequest request . Ao herdar do TwilioController , você obtém acesso ao método TwiML que pode usar para responder com o 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 ) ;
}
} Este controlador lidará com o webhook de voz. Os detalhes da chamada de voz que recebem estarão vinculados ao parâmetro VoiceRequest request . Ao herdar do TwilioController , você obtém acesso ao método TwiML que pode usar para responder com o TWIML.
TwiML em vez de herdar do TwilioController Se você não puder herdar da classe TwilioController , poderá usar os métodos de extensão 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 ) ;
}
} Esta amostra é a mesma da amostra anterior do SMS Webhook, mas, em vez de herdar do TwilioController , o SmsController herda do Controller fornecido pelo MVC do ASP.NET e usa this.TwiML para usar o método de extensão TwiML .
Twilio.aspnet.core também tem suporte para APIs mínimas.
Esta amostra mostra como você pode manipular um sms webhook usando o http get and post.
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 ( ) ; Nos controladores MVC tradicionais, o objeto SmsRequest , VoiceRequest e outro objeto de solicitação digitado seria vinculado, mas as APIs mínimas não suportam a mesma ligação do modelo.
Em vez disso, você pode vincular parâmetros individuais para solicitações HTTP GET usando o atributo FromQuery . Quando você não especifica o atributo FROUNDY, várias fontes serão consideradas para se vincular além dos parâmetros da sequência de consultas. Para solicitações de postagem HTTP, você pode pegar o formulário e recuperar parâmetros individuais por índice de string.
Para responder com twiml, use os Results.Extensions.TwiML .
O Twilio.aspnet vem com várias classes para ajudá -lo a vincular os dados de webhooks a objetos .NET digitados fortemente. Aqui está a lista de aulas:
SmsRequest : mantém dados para solicitações de webhook SMS recebidasSmsStatusCallbackRequest : mantém dados para rastrear o status de entrega de um Twilio SMS ou MMS de saídaStatusCallbackRequest : mantém dados para rastrear o status de uma chamada de voz de Twilio de saídaVoiceRequest : mantém dados para chamadas de voz recebidasNota Somente controladores MVC e páginas de barbear suportam a ligação do modelo a objetos .NET digitados. Em APIs mínimas e outros cenários, você terá que escrever código para extrair os parâmetros.
A amostra a seguir mostra como aceitar SMS de entrada, responder e acompanhar o status da resposta do 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 ) ;
}
} Conforme mostrado na amostra acima, você pode adicionar um SmsRequest como parâmetro e o MVC ligará o objeto para você. O código então responde com um SMS com o parâmetro status e method . Quando o status do SMS mudar, o Twilio enviará uma solicitação de postagem HTTP para a ação StatusCallback . Você pode adicionar um SmsStatusCallbackRequest como um parâmetro, e o MVC ligará o objeto para você.
No núcleo do ASP.NET, você pode adicionar o cliente da API Twilio Rest aos serviços do ASP.NET Core usando o método .AddTwilioClient , como este:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddTwilioClient ( ) Agora você pode solicitar ITwilioRestClient e TwilioRestClient via injeção de dependência.
Você pode configurar o cliente Twilio usando a seguinte configuração:
{
"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
}
}
}Algumas anotações:
Twilio:Client:AuthToken recorre ao Twilio:AuthToken . Você só precisa configurar um deles.Twilio:Client:CredentialType possui os seguintes valores válidos: Unspecified , AuthToken ou ApiKey .Twilio:Client:CredentialType é opcional e os padrões Unspecified . Se Unspecified , se você configurou uma chave da API ou um token de autenticação será detectado.Se você não deseja configurar o cliente Twilio usando a configuração do .NET, pode fazê -lo manualmente:
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 ;
} ) ;Aviso não coda seu token de autenticação ou segredo da API em código e não os verifique no controle de origem. Recomendamos usar o gerente de segredos para desenvolvimento local. Como alternativa, você pode usar variáveis de ambiente, um serviço de cofre ou outras técnicas mais seguras.
Por padrão, quando você chama .AddTwilioClient , uma fábrica de clientes HTTP está configurada que é usada para fornecer um HttpClient ao cliente Twilio Rest. Se você deseja personalizar este cliente HTTP, pode fazê -lo substituindo a fábrica do cliente HTTP "Twilio", depois de invocar .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
} ) ;Os webhooks exigem que seu terminal esteja disponível ao público, mas isso também apresenta o risco de que os maus atores possam encontrar seu URL da webhook e tentar abusá -lo.
Felizmente, você pode verificar se uma solicitação HTTP se originou do Twilio. A biblioteca Twilio.AspNet fornece um atributo que validará a solicitação para você no MVC. A implementação difere entre a biblioteca Twilio.AspNet.Core e Twilio.AspNet.Mvc .
Adicione o método .AddTwilioRequestValidation na inicialização:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddTwilioRequestValidation ( ) ;Em seguida, configure a validação da solicitação:
{
"Twilio" : {
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"RequestValidation" : {
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"AllowLocal" : false ,
"BaseUrlOverride" : " https://??????.ngrok.io "
}
}
}Algumas anotações sobre a configuração:
Twilio:RequestValidation:AuthToken recorre ao Twilio:AuthToken . Você só precisa configurar um deles.AllowLocal pulará a validação quando a solicitação HTTP se originou do localhost.BaseUrlOverride , caso seu aplicativo esteja por trás de um proxy reverso ou um túnel como o NGROK. O caminho da solicitação atual será anexado ao BaseUrlOverride para validação de solicitação.Informações em vez de configurar o
BaseUrlOverride, você pode usar o middleware de cabeçalhos encaminhados para definir o esquema correto, porta, host etc. na solicitação HTTP atual.
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 ( ) ; Como resultado, você não precisa configurar BaseUrlOverride sempre que reiniciar o NGROK ou alterar URLs de proxy reverso. Siga as orientações da Microsoft para configurar o middleware do cabeçalho encaminhado com segurança.
Você também pode configurar manualmente a validação da solicitação:
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" ;
} ) ;Aviso não coda seu token de autenticação no código e não os verifique no controle de origem. Recomendamos usar o gerente de segredos para desenvolvimento local. Como alternativa, você pode usar variáveis de ambiente, um serviço de cofre ou outras técnicas mais seguras.
Depois que a validação da solicitação for configurada, você pode usar o atributo [ValidateRequest] no MVC. Você pode aplicar o atributo globalmente, a áreas de MVC, controladores e ações. Aqui está um exemplo em que o atributo é aplicado à ação 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 ) ;
}
} O .NET 7 apresenta o conceito de filtros de endpoint que você pode aplicar a qualquer endpoint do ASP.NET Core. A biblioteca ajudante do ASP.NET Core adicionou um filtro de terminal para validar solicitações de Twilio chamado ValidateTwilioRequestFilter .
Você pode adicionar este filtro a qualquer grupo de extremidades ou grupo de extremidade usando o método 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" , ( ) => .. . ) ;Como alternativa, você pode adicionar o final do ponto de extremidade:
app . MapPost ( "/sms" , ( ) => .. . )
. AddEndpointFilter < ValidateTwilioRequestFilter > ( ) ; Quando você não pode usar o filtro [ValidateRequest] ou ValidateTwilioRequestFilter , você pode usar o ValidateTwilioRequestMiddleware . Você pode adicionar adicionar o ValidateTwilioRequestFilter como este:
app . UseTwilioRequestValidation ( ) ;
// or the equivalent: app.UseMiddleware<ValidateTwilioRequestMiddleware>(); Este middleware executará a validação para todas as solicitações. Se você não deseja aplicar a validação a todas as solicitações, pode usar app.UseWhen() para executar o middleware condicionalmente.
Aqui está um exemplo de como validar solicitações que começam com Path /Twilio-Media , a ponto de proteger arquivos de mídia que apenas o proxy do Twilio deve poder acessar:
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 ( ) ; No seu web.config, você pode configurar a validação de solicitação, como mostrado abaixo:
<? 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 >Você também pode configurar a validação de solicitação usando as configurações do aplicativo:
<? 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 > Se você configurar a validação de solicitação usando os dois lados, a configuração do aplicativo substituirá o elemento de configuração twilio/requestValidation .
Algumas anotações sobre a configuração:
allowLocal pulará a validação quando a solicitação HTTP se originou do localhost.baseUrlOverride , caso você esteja na frente de um proxy reverso ou um túnel como o NGROK. O caminho da solicitação atual será anexado ao baseUrlOverride para validação de solicitação.Aviso não coda seu token de autenticação no código e não os verifique no controle de origem. Use o
UserSecretsConfigBuilderpara desenvolvimento local ou um dos outros construtores de configuração. Como alternativa, você deve criptografar as seções de configuração que contêm segredos como o token de autenticação.
Agora que a validação da solicitação foi configurada, use o atributo [ValidateRequest] . Você pode aplicar o atributo globalmente, a áreas de MVC, controladores e ações. Aqui está um exemplo em que o atributo é aplicado à ação 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 ) ;
}
} O atributo [ValidateRequest] funciona apenas para MVC. Se você precisar validar solicitações fora do MVC, poderá usar a classe RequestValidationHelper fornecida pelo Twilio.AspNet . Como alternativa, a classe RequestValidator do Twilio SDK também pode ajudá -lo com isso.
Aqui está um exemplo mínimo de API que valida a solicitação recebida 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 adiciona o TwilioRequestValidationOptions , que normalmente é usado para o atributo [ValidateRequest] , mas nesta amostra é usada para recuperar a configuração de validação da solicitação. Em seguida, dentro do terminal /sms , o método IsValidTwilioRequest é usado para validar a solicitação. IsValidTwilioRequest recupera as opções de validação de solicitação da DI e executa a mesma lógica que [ValidateRequest] faria para as solicitações do MVC. Se a solicitação não for válida, o código de status HTTP 403 será retornado; caso contrário, alguns TWIML serão devolvidos ao Twilio.