
Библиотека Twilio Helper для ASP.NET (twilio.aspnet) помогает интегрировать официальную Twilio SDK для C# и .net в ваши приложения ASP.NET. Библиотека поддерживает ASP.NET MVC на .NET Framework и ASP.NET CORE.
Эта библиотека помогает вам реагировать на Webhooks, добавляет клиента Twilio в контейнер для инъекции зависимостей и подтверждает HTTP -запрос, который происходит от Twilio.
Требуется .NET 6.0 или более поздней версии.
Запустите следующую команду, чтобы установить пакет, используя CLI .NET:
dotnet add package Twilio.AspNet.CoreВ качестве альтернативы, из консоли диспетчера пакетов или разработчика PowerShell запустите следующую команду для установки последней версии:
Install-Package Twilio.AspNet.CoreВ качестве альтернативы, используйте диспетчер пакетов Nuget для Visual Studio или окно Nuget для Rider Rider, а затем найдите twilio.aspnet.core и установите пакет.
Требуется .NET 4.6.2 или более поздней версии.
В консоли менеджера пакетов или разработчика PowerShell запустите следующую команду, чтобы установить последнюю версию:
Install-Package Twilio.AspNet.MvcВ качестве альтернативы, используйте диспетчер пакетов Nuget для Visual Studio или окно Nuget для Ridebrains Rider, затем найдите twilio.aspnet.mvc и установите пакет.
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 ) ;
}
} Этот контроллер будет обрабатывать SMS -WebHook. Детали входящих SMS будут связаны с параметрам SmsRequest request . Унаследовав от TwilioController , вы получаете доступ к методу TwiML , который вы можете использовать для ответа с помощью 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 ) ;
}
} Этот контроллер будет обрабатывать Voice Webhook. Подробная информация о входящем голосовом вызове будет связана с параметром VoiceRequest request . Унаследовав от TwilioController , вы получаете доступ к методу TwiML , который вы можете использовать для ответа с помощью Twiml.
TwiML вместо наследства от TwilioController Если вы не можете унаследовать от класса TwilioController , вы можете использовать методы расширения 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 ) ;
}
} Этот образец такой же, как и предыдущий образец SMS Webhook, но вместо того, чтобы наследовать от TwilioController , SmsController наследует от Controller ASP.NET MVC и использует this.TwiML для использования метода расширения TwiML .
Twilio.aspnet.core также поддерживает минимальные API.
Этот образец показывает, как вы можете передать SMS -веб -крючок, используя 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 ( ) ; В традиционных контроллерах MVC SmsRequest , VoiceRequest и другой типированный объект запроса будут связаны, но минимальные API не поддерживают ту же привязку модели.
Вместо этого вы можете связать отдельные параметры для HTTP -запросов с помощью атрибута FromQuery . Когда вы не указываете атрибут FromQuery, считать несколько источников привязываться в дополнение к параметрам строки запроса. Для запросов HTTP Post вы можете получить форму, а затем получить отдельные параметры по строковому индексу.
Чтобы ответить Twiml, используйте метод Results.Extensions.TwiML .
Twilio.aspnet поставляется с несколькими классами, которые помогут вам связать данные из Webhooks с сильно напечатанными объектами .NET. Вот список классов:
SmsRequest : хранит данные для входящих запросов на SMS WebhookSmsStatusCallbackRequest : хранит данные для отслеживания состояния доставки исходящих SMS или MMS TwilioStatusCallbackRequest : хранит данные для отслеживания состояния исходящего голосового вызова TwilioVoiceRequest : хранит данные для входящих голосовых вызововПримечание только контроллеры MVC и страницы бритвы поддерживают привязку модели с типированными объектами .NET. В минимальных API и других сценариях вам придется написать код для извлечения параметров самостоятельно.
Следующий образец показывает, как принять входящие SMS, ответить и отслеживать статус ответа 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 ) ;
}
} Как показано в примере выше, вы можете добавить SmsRequest в качестве параметра, и MVC будет связывать объект для вас. Затем код отвечает с помощью SMS с параметром status и method . Когда статус SMS изменится, Twilio отправит запрос HTTP POST в действие StatusCallback . Вы можете добавить SmsStatusCallbackRequest в качестве параметра, и MVC будет связывать объект для вас.
В Core ASP.NET вы можете добавить клиент API Twilio REST в сервисы ASP.NET Core, используя метод .AddTwilioClient , например:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddTwilioClient ( ) Теперь вы можете запросить ITwilioRestClient и TwilioRestClient с помощью инъекции зависимостей.
Вы можете настроить клиент Twilio, используя следующую конфигурацию:
{
"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
}
}
}Пара заметок:
Twilio:Client:AuthToken отступает на Twilio:AuthToken . Вам нужно только настроить один из них.Twilio:Client:CredentialType имеет следующие допустимые значения: Unspecified , AuthToken или ApiKey .Twilio:Client:CredentialType не является обязательным, и по умолчанию Unspecified . Если будет обнаружено, если вы Unspecified , будут ли вы настроить ключ API или токен Auth.Если вы не хотите настроить клиент Twilio с помощью конфигурации .NET, вы можете сделать это вручную:
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 ;
} ) ;ПРЕДУПРЕЖДЕНИЕ Не жестко кодируйте ваш токен Auth или секрет ключей API в код и не проверяйте их в управлении источником. Мы рекомендуем использовать менеджер Secrets для местного развития. В качестве альтернативы, вы можете использовать переменные среды, службу хранилища или другие более безопасные методы.
По умолчанию при вызове .AddTwilioClient настраивается HTTP -фабрика, которая используется для предоставления HttpClient для клиента Twilio REST. Если вы хотите настроить этого HTTP -клиента, вы можете сделать это, переопределив фабрику «Twilio» HTTP, после вызова .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
} ) ;Webhooks требуют, чтобы ваша конечная точка была общедоступной, но это также представляет риск, что плохие актеры могут найти ваш URL -адрес веб -хука и попытаться злоупотреблять им.
К счастью, вы можете проверить, что HTTP -запрос возник из Twilio. Библиотека Twilio.AspNet предоставляет атрибут, который подтвердит запрос для вас в MVC. Реализация отличается между Twilio.AspNet.Core и библиотекой Twilio.AspNet.Mvc .
Добавьте метод .AddTwilioRequestValidation при запуске:
using Twilio . AspNet . Core ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddTwilioRequestValidation ( ) ;Затем настройте проверку запроса:
{
"Twilio" : {
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"RequestValidation" : {
"AuthToken" : " [YOUR_AUTH_TOKEN] " ,
"AllowLocal" : false ,
"BaseUrlOverride" : " https://??????.ngrok.io "
}
}
}Пара заметок о конфигурации:
Twilio:RequestValidation:AuthToken отступает на Twilio:AuthToken . Вам нужно только настроить один из них.AllowLocal пропустит проверку, когда HTTP -запрос возник из Localhost.BaseUrlOverride на случай, если ваше приложение стоит за обратным прокси или туннелем, таким как NGROK. Путь текущего запроса будет добавлен в BaseUrlOverride для проверки запроса.Информация Вместо настройки
BaseUrlOverride, вы можете использовать промежуточное программное обеспечение перенаправленных заголовков, чтобы установить правильную схему, порт, хост и т. Д. На текущем HTTP -запросе.
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 ( ) ; В результате вам не нужно настраивать BaseUrlOverride всякий раз, когда вы перезагружаете NGROK, или менять обратные прокси -URL -адреса. Следуйте руководству Microsoft для надежной настройки промежуточного программного обеспечения для направленного заголовка.
Вы также можете вручную настроить проверку запроса:
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" ;
} ) ;ПРЕДУПРЕЖДЕНИЕ НЕ СРЕДИНГОВАЯ ПРИКЛЮЧАТЕЛЬНОСТЬ ТОКЕНА AUTH в код и не проверяйте их в управлении источником. Мы рекомендуем использовать менеджер Secrets для местного развития. В качестве альтернативы, вы можете использовать переменные среды, службу хранилища или другие более безопасные методы.
После того, как проверка запроса была настроена, вы можете использовать атрибут [ValidateRequest] в MVC. Вы можете применить атрибут по всему миру к областям MVC, контроллерам и действиям. Вот пример, в котором атрибут применяется к 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 представляет концепцию фильтров конечных точек, которую вы можете применить к любой конечной точке ASP.NET Core. Библиотека Helper для ядра ASP.NET добавила фильтр конечной точки для проверки запросов Twilio с именем ValidateTwilioRequestFilter .
Вы можете добавить этот фильтр в любую конечную точку или группу конечных точек, используя метод 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" , ( ) => .. . ) ;В качестве альтернативы, вы можете добавить фильтр конечной точки самостоятельно:
app . MapPost ( "/sms" , ( ) => .. . )
. AddEndpointFilter < ValidateTwilioRequestFilter > ( ) ; Когда вы не можете использовать фильтр [ValidateRequest] или ValidateTwilioRequestFilter , вы можете вместо этого использовать ValidateTwilioRequestMiddleware . Вы можете добавить добавить ValidateTwilioRequestFilter , как это:
app . UseTwilioRequestValidation ( ) ;
// or the equivalent: app.UseMiddleware<ValidateTwilioRequestMiddleware>(); Это промежуточное программное обеспечение выполнит проверку для всех запросов. Если вы не хотите применять валидацию ко всем запросам, вы можете использовать app.UseWhen() для условного запуска промежуточного программного обеспечения.
Вот пример того, как проверить запросы, которые начинаются с Path /Twilio-Media , для защиты медиа-файлов, к которым должен быть доступ только прокси Twilio:
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 ( ) ; В вашем web.config вы можете настроить проверку запроса, как показано ниже:
<? 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 >Вы также можете настроить проверку запросов, используя настройки приложения:
<? 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 > Если вы настраиваете проверку запросов с помощью обоих способов, настройка приложения будет перезаписать элемент конфигурации twilio/requestValidation .
Пара заметок о конфигурации:
allowLocal пропустит проверку, когда HTTP -запрос возник из Localhost.baseUrlOverride на случай, если вы находитесь перед обратным прокси или туннелем, таким как Ngrok. Путь текущего запроса будет добавлен в baseUrlOverride для проверки запроса.ПРЕДУПРЕЖДЕНИЕ НЕ СРЕДИНГОВАЯ ПРИКЛЮЧАТЕЛЬНОСТЬ ТОКЕНА AUTH в код и не проверяйте их в управлении источником. Используйте
UserSecretsConfigBuilderдля локальной разработки или одного из других строителей конфигурации. В качестве альтернативы, вы должны шифровать разделы конфигурации, содержащие секреты, такие как токен Auth.
Теперь эта проверка запроса была настроена, используйте атрибут [ValidateRequest] . Вы можете применить атрибут по всему миру к областям MVC, контроллерам и действиям. Вот пример, в котором атрибут применяется к 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 ) ;
}
} Атрибут [ValidateRequest] работает только для MVC. Если вам нужно проверить запросы за пределами MVC, вы можете использовать класс RequestValidationHelper предоставленного Twilio.AspNet . В качестве альтернативы, класс RequestValidator из Twilio SDK также может помочь вам в этом.
Вот минимальный пример API, который подтверждает входящий запрос, возникший из 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 добавляет TwilioRequestValidationOptions , который обычно используется для атрибута [ValidateRequest] , но в этом примере он используется для самостоятельного извлечения конфигурации проверки запроса. Затем внутри конечной точки /SMS метод IsValidTwilioRequest используется для проверки запроса. IsValidTwilioRequest извлекает параметры проверки запроса из DI и выполняет ту же логику, что и [ValidateRequest] для запросов MVC. Если запрос недопустим, код 403 HTTP возвращается, в противном случае, некоторые Twiml возвращаются в Twilio.