Back to Blog
Integration Guides

How to Send SMS with Twilio and .NET: Step-by-Step Tutorial

Integrate the Twilio .NET NuGet package into any .NET application with proper async patterns, configuration binding, and error handling.

DA
Danial A
Senior Twilio Consultant, Telphi Consulting
June 22, 2026
7 min read
Twilio
Integration
SDK
Mobile
How to Send SMS with Twilio and .NET: Step-by-Step Tutorial

Twilio SMS and .NET integrate through the official Twilio NuGet package that works across the entire .NET ecosystem including ASP.NET Core, .NET Worker Services, Azure Functions, console applications, and class libraries, providing MessageResource.CreateAsync for non-blocking SMS dispatch that fits .NET's async/await model and integrates with Microsoft.Extensions.DependencyInjection for clean service registration. This integration is used by .NET development teams building applications on .NET 6, 7, 8, or later that need SMS for OTP verification, system alerts, appointment reminders, or transactional notifications, and who want a single NuGet package that works consistently across all .NET project types without framework-specific adapters. The Twilio NuGet package is installed with dotnet add package Twilio, credentials are bound from .NET configuration to a typed options class, and TwilioClient.Init is called once during application startup before any MessageResource.CreateAsync calls.

What You Need Before You Start

Add the Twilio NuGet package to your .NET project by running dotnet add package Twilio. Collect your Twilio Account SID, Auth Token, and a provisioned SMS-capable phone number. For .NET console applications, create a TwilioSettings section in appsettings.json with AccountSid, AuthToken, and FromNumber keys. For Azure Functions, add these values to local.settings.json under Values for local development. Set production values using environment variables named TwilioSettings__AccountSid, TwilioSettings__AuthToken, and TwilioSettings__FromNumber, which the .NET configuration system maps to the nested TwilioSettings section using double underscore as the hierarchy separator. Create a TwilioSettings record or class with string properties for each credential to receive the bound values via IOptions<TwilioSettings>.

Step-by-Step Integration Guide

Create a TwilioSmsService class that accepts IOptions<TwilioSettings> and ILogger<TwilioSmsService> via constructor injection. In the constructor, read the settings from options.Value, validate that AccountSid and AuthToken are not null or empty by throwing an InvalidOperationException with a descriptive message if so, and call TwilioClient.Init(settings.AccountSid, settings.AuthToken). Define a SendSmsAsync method that accepts string toPhone and string body plus an optional CancellationToken, calls var message = await MessageResource.CreateAsync(to: new Twilio.Types.PhoneNumber(toPhone), from: new Twilio.Types.PhoneNumber(_fromNumber), body: body) wrapped in try/catch catching Twilio.Exceptions.ApiException, logs the exception Code and Message via the logger, and throws a TwilioSmsException extending Exception. In your Program.cs for console or ASP.NET Core, register the service with builder.Services.Configure<TwilioSettings>(builder.Configuration.GetSection('TwilioSettings')) and builder.Services.AddSingleton<TwilioSmsService>(), then inject TwilioSmsService wherever SMS dispatch is needed.

Common Issues and How to Fix Them

TwilioClient.Init throws InvalidOperationException on the first MessageResource.CreateAsync call when called from a constructor of a singleton service that was resolved before TwilioClient.Init executed, because .NET DI resolves services lazily and a competing service may have called MessageResource.CreateAsync before Init ran. Call TwilioClient.Init as early as possible in Program.cs after reading credentials from configuration rather than inside a service constructor, or use a thread-safe singleton initialization check in the service. MessageResource.CreateAsync deadlocks in legacy ASP.NET Framework applications that use .Result or .Wait() on the returned Task because the synchronization context blocks waiting for a result that can never complete on the same thread. In .NET Framework applications with a synchronization context, use ConfigureAwait(false) on all awaited Twilio calls or use Task.Run(() => MessageResource.CreateAsync(...)).Result only in a fire-and-forget context, and prefer upgrading to .NET 6 or later where the default synchronization context does not cause these deadlocks. The appsettings.json TwilioSettings section binds but the AccountSid property is null when the JSON property name casing in the file does not match the C# property name casing and the IOptions binding uses case-sensitive matching in some environments. Use the exact same casing in both the appsettings.json key and the C# class property, or add a JsonPropertyName attribute to the property to explicitly specify the JSON key name.

How to Get More from This Integration

Build a .NET Worker Service for background SMS processing by creating a BackgroundService subclass that maintains a Channel<SmsJob> as an in-memory queue, exposes a QueueSms method that writes to the channel, processes jobs in ExecuteAsync by reading from the channel and calling TwilioSmsService.SendSmsAsync with a linked CancellationToken from stoppingToken, and registers it with builder.Services.AddHostedService, enabling fire-and-forget SMS dispatch from any ASP.NET Core controller without blocking HTTP threads. Add Polly retry policies using the Microsoft.Extensions.Http.Polly NuGet package by defining a retry policy and wrapping the SendSmsAsync body to provide automatic exponential backoff retry for transient Twilio API failures. Implement a .NET minimal API SMS endpoint for lightweight applications by adding app.MapPost('/api/sms', async (SmsRequest req, TwilioSmsService sms) => { var sid = await sms.SendSmsAsync(req.To, req.Body); return Results.Ok(new { sid }); }) in Program.cs after building the WebApplication, requiring no controller class and keeping the SMS endpoint as a single expression.

Conclusion

.NET and Twilio together provide a production-ready SMS integration using NuGet package management, typed configuration binding, and async/await patterns that work consistently across all modern .NET application types. Contact Telphi Consulting to implement and configure Twilio SMS in your .NET application.

Share this article:
0 views

Ready to Transform Your Business Communications?

Get a free consultation with our VoIP experts and discover how we can help you save costs, improve efficiency, and scale your business.

Comments (0)

Join the discussion and share your thoughts (AI-moderated for quality)

Protected by AI moderation

Be the first to comment

No comments yet. Share your thoughts below.