
ASP.NET(twilio.aspnet)的Twilio Helper库,可帮助您将官方的Twilio SDK集成到C#和.NET中,并将其集成到您的ASP.NET应用程序中。该库支持.NET框架和ASP.NET Core上的ASP.NET MVC。
该库可帮助您响应Webhooks,将Twilio客户端添加到依赖项注入容器中,并验证HTTP请求来自Twilio。
需要.NET 6.0或更高版本。
运行以下命令使用.NET CLI:
dotnet add package Twilio.AspNet.Core另外,从软件包管理器控制台或开发人员PowerShell中运行以下命令来安装最新版本:
Install-Package Twilio.AspNet.Core或者,将Nuget软件包管理器用于Visual Studio或Jetbrains Rider的Nuget窗口,然后搜索Twilio.aspnet.core并安装软件包。
需要.NET 4.6.2或更高版本。
从包装管理器控制台或开发人员PowerShell中运行以下命令以安装最新版本:
Install-Package Twilio.AspNet.Mvc或者,使用Nuget软件包管理器作为Visual Studio或Jetbrains Rider的Nuget窗口,然后搜索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 ) ;
}
}该控制器将处理语音webook。传入语音呼叫的详细信息将绑定到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样本相同,但是SmsController从ASP.NET MVC提供的Controller继承,而不是从TwilioController继承,而是使用this.TwiML使用TwiML扩展方法。
Twilio.aspnet.Core还支持最小API。
该示例向您展示了如何使用HTTP GET并发布SMS Webhook。
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不支持相同的模型绑定。
相反,您可以使用FromQuery属性绑定HTTP获取请求的单个参数。当您不指定FROFQUERY属性时,除了查询字符串参数外,还将考虑多个源可以绑定。对于HTTP POST请求,您可以获取表单,然后通过字符串索引检索单个参数。
要使用twiml响应,请使用Results.Extensions.TwiML方法。
Twilio.aspnet配备多个类,可帮助您将Webhooks的数据绑定到强烈键入的.NET对象。这是类列表:
SmsRequest :保留用于传入SMS Webhook请求的数据SmsStatusCallbackRequest :保留用于跟踪出站Twilio SMS或MMS的交付状态的数据StatusCallbackRequest :保留用于跟踪出站Twilio语音通话状态的数据VoiceRequest :保留传入语音通话的数据注意仅MVC控制器和Razor页面支持模型绑定到键入的.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将为您绑定对象。然后,代码以带有status和method参数的SMS响应。当SMS的状态更改时,Twilio将向StatusCallback操作发送HTTP POST请求。您可以将SmsStatusCallbackRequest添加为参数,MVC将为您绑定对象。
在ASP.NET Core中,您可以使用.AddTwilioClient方法将Twilio Rest API客户端添加到ASP.NET Core的服务中:
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密钥还是验证令牌。如果您不希望使用.NET配置配置Twilio客户端,则可以手动进行操作:
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 ;
} ) ;警告不要将您的身份令牌或API密钥秘密用硬编码为代码,也不要将其检查为源控件。我们建议使用秘密经理进行本地发展。另外,您可以使用环境变量,保管库服务或其他更安全的技术。
默认情况下,当您调用.AddTwilioClient时,将配置HTTP客户端工厂,用于为Twilio Rest客户端提供HttpClient 。如果您想自定义此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要求您的端点公开可用,但这也引入了不良演员可以找到您的Webhook 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将跳过验证。BaseUrlOverride 。当前请求的路径将附加到BaseUrlOverride以进行请求验证。您可以在当前的HTTP请求上使用转发的标头中间件来设置正确的方案,端口,主机等,而不是配置
BaseUrlOverride。
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 ( ) ;结果,每当重新启动NGrok或更改反向代理URL时,您都不必配置BaseUrlOverride 。遵循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" ;
} ) ;警告不要将您的身份令牌编码为代码,也不要将其检查为源控件。我们建议使用秘密经理进行本地发展。另外,您可以使用环境变量,保管库服务或其他更安全的技术。
一旦配置了请求验证,您就可以在MVC中使用[ValidateRequest]属性。您可以将属性应用于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核心端点。用于ASP.NET核心的辅助库添加了一个端点过滤器,以验证称为ValidateTwilioRequestFilter的Twilio请求。
您可以使用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()有条件地运行中间件。
这是如何验证以路径/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将跳过验证。baseUrlOverride 。当前请求的路径将附加到baseUrlOverride以进行请求验证。警告不要将您的身份令牌编码为代码,也不要将其检查为源控件。使用
UserSecretsConfigBuilder使用sconfigbuilder进行本地开发或其他配置构建器之一。另外,您应该加密包含诸如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之外的请求,则可以使用Twilio.AspNet提供的RequestValidationHelper类。另外,Twilio SDK的RequestValidator类也可以为您提供帮助。
这是一个最小的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请求所做的相同逻辑。如果请求不有效,则返回HTTP状态代码403,否则,将返回twiml返回Twilio。