Migrating Your C# / .NET Application from Twilio SDK 4.x to 5.x

Deprecation notice: New functionality will only be added to the new library (C# 5.x). The old library (C# 4.x) is deprecated and Twilio will no longer provide bug fixes. Support might ask you to upgrade before debugging issues. The old library will remain available indefinitely on GitHub.

The open source Twilio C#/.NET SDK has undergone significant changes from version 4.x to 5.x - we'll break down the major changes here to make migrating to the new version as painless as possible. If you're integrating Twilio in your C#/.NET app for the first time, you can skip straight to the install page.

.NET Version Compatibility

The Twilio C# SDK supports .NET applications written in C#, VB.Net, and F# that utilize the .NET Framework version 3.5 or higher or any .NET runtime supporting .NET Standard v1.4.

Client Initialization

Initializing the client for future REST API calls is now a static method. There is no need to create a client object.

// Find your Account Sid and Auth Token at twilio.com/user/account
var accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var authToken = "your_auth_token";
TwilioClient.Init(accountSid, authToken);

This only needs to be done once. All subsequent calls to the Twilio API will be authenticated using the credentials passed to the Init method.

Custom Client

The helper library methods that make REST API requests each have an optional client parameter. By default, the library will use the default TwilioRestClient object that gets created when you call TwilioClient.Init. If you need to manipulate the HTTP requests in any way as they are made (for example, for using a proxy server), you can write your own class that implements ITwilioRestClient and pass an instance of that class to the helper library method calls. For the majority of use cases, this will not be necessary.

Resource Classes

The older version of the library contained a single client class that had hundreds of methods to perform various tasks (sending messages, retrieving call logs, etc.). Now, each resource in the Twilio REST API has a corresponding C# class. Want to work with SMS messages? You need the MessageResource class. Phone calls? Check out CallResource.

Each resource class has a set of static methods you can call to Create, Fetch, Read (list), Update, and Delete the resources. Where a method isn’t supported by Twilio for a given resource, it is omitted from the class.

Create

Many resources can be created. Do do so, call the Create static method on the class. For example, here’s how to create (send) a new SMS message:

var message = MessageResource.Create(
    to: new PhoneNumber("+15558675309"),
    from: new PhoneNumber("+15017250604"),
    body: "I am one with C# and C# is with me."
);
Console.WriteLine(message.DateCreated);

This will create a Message resource on Twilio (which sends the message) and you will have access to all the properties of the resource in the return variable message.

Fetch

Use Fetch when you know the unique identifier of a specific resource and you want to retrieve all of its properties. For example, you could retrieve information about your Twilio account:

var account = AccountResource.Fetch("ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
Console.WriteLine(account.DateCreated);

Read

Read methods fetch a list of resources. Often, the Read method will provide additional filtering parameters to narrow down the list of results you get back. Here’s how you might get a list of calls that were made to a specific number:

var calls = CallResource.Read(to: new PhoneNumber("+15558675309"));
foreach (var call in calls)
{
    Console.WriteLine(call.StartTime);
}

Paging

In prior versions of the helper library, you had to worry about paging. You would retrieve one page of results and then continue requesting pages until you’d retrieved all of the resources you needed. Now, paging is handled automatically. In the example above -- and any time you use Read -- you can simply iterate through the results that come back and any requests for additional pages of results will be made for you.

var thirtyDaysAgo = DateTime.UtcNow.AddDays(-30);
var messages = MessageResource.Read(dateSentAfter: thirtyDaysAgo);
// Iterating automatically requests additional pages 
// from the Twilio REST API
foreach (var message in messages)
{
    Console.WriteLine(message.Body);
}

If you wish to enforce a limit on the number of records returned, include a limit parameter. For example, here’s how to limit the number of records to 50:

var messages = MessageResource.Read(dateSentAfter: thirtyDaysAgo, limit: 50);

Update

Update methods allow you to modify a specific resource.  To use an Update method you’ll need to know the resource’s unique identifie.. Here’s an example that redacts a previously sent or received SMS message by setting the Body to an empty string:

MessageResource.Update("MM5ef8732a3c49700934481addd5ce1659", "");

Delete

Delete methods remove the resource from Twilio’s servers. Like Fetch and Update methods, it takes the unique identifier of the resource to be deleted. For example, you may want to delete a recording of a call:

RecordingResource.Delete("RE557ce644e5ab84fa21cc21112e22c485");

Passing Arguments

There are two ways each of the above methods can be called on a resource class. The first you’ve seen. You pass positional and/or named arguments to the methods. Optional arguments will have a default value of null. Take this example of the method signature for MessageResource.Create:

public static MessageResource Create(
        PhoneNumber to, 
        string accountSid = null, 
        PhoneNumber from = null, 
        string messagingServiceSid = null, 
        string body = null, 
        List<System.Uri> mediaUrl = null, 
        System.Uri statusCallback = null, 
        string applicationSid = null, 
        Decimal? maxPrice = null, 
        bool? provideFeedback = null, 
        ITwilioRestClient client = null)

Even though there are a large number of arguments to the Create function, many are optional, so you can only pass in the arguments you need using named arguments:

var message = MessageResource.Create(
    to: new PhoneNumber("+15558675309"),
    from: new PhoneNumber("+15017250604"),
    body: "I am one with C# and C# is with me."
);

However, each of a resource’s Create, Update, Read and Delete methods  can also be called using an Options class. Here’s the version of MessageResource.Create that takes a single CreateMessageOptions class.

Rather than specifying many individual arguments, you instead create a CreateMessageOptions class, set your message values using its properties and pass it to the Create method. If you were fetching, the class would be FetchMessageOptions. If you were deleting a recording, then it would be DeleteRecordingOptions. Sense a pattern forming?

When using an Options class, the constructor will contain each of the required properties for the resource you are using and action you wish to perform. For example, when creating an SMS, you must provide a “to” phone number, so that is an argument to the CreateMessageOptions constructor. Any remaining properties can be set on the Options object you create:

var options = new CreateMessageOptions(new PhoneNumber("+15558675309"));
options.From = new PhoneNumber("+15017250604");
options.Body = "I am one with C# and C# is with me.";

var message = MessageResource.Create(options);

Asynchronous Methods

If you’re using .NET Framework 4.5.1+ or .NET Core 1.0+, then you can use asynchronous versions of the Create, Fetch, Read, Update, and Delete resource methods. Predictably, these methods are named CreateAsync, FetchAsync, ReadAsync, UpdateAsync, and DeleteAsync. Here’s an example that creates a new call using CreateAsync:

public async Task<CallResource> PhoneHomeAsync()
{
    var call = await CallResource.CreateAsync(
        to: new PhoneNumber("+15558675309"),
        from: new PhoneNumber("+15017250604"),
        url: new Uri("http://demo.twilio.com/docs/voice.xml")
    );
    return call;
}

TwiML

The Twilio C# SDK now includes helper classes to generate TwiML. You may have previously generated the XML manually or perhaps used the separate Twilio.TwiML library. Using the library to generate the TwiML is a good way to make sure you’re generating well-formed TwiML and a smart editor like Visual Studio or VS Code can tell you what verbs, nouns, and attributes are available when constructing your response.

There are two classes you can use to generate TwiML: Twilio.TwiML.VoiceResponse and Twilio.TwiML.MessagingResponse. You would use the former when handling a voice call and the latter when responding to a text message.

VoiceResponse

To build TwiML to handle a phone call, just create an instance of the VoiceResponse class and then call methods on the new object that correspond to the various TwiML verbs. For example, here’s code that plays a greeting in a specific language: 

Loading Code Samples...
Language
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        response.Say("Chapeau!", voice: "alice", language: "fr-FR");

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say voice="alice" language="fr-FR">Chapeau!</Say>
</Response>
Using a specific language as an attribute in a Say verb

And an example with nested verbs:

Loading Code Samples...
Language
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(input: "speech", action: new Uri("/completed"));
        gather.Say("Welcome to Twilio, please tell us why you're calling");
        response.Append(gather);

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/simple_gather.xml -->
<Response>
    <Gather input="speech" action="/completed">
           <Say>Welcome to Twilio, please tell us why you're calling</Say>
        </Gather>
</Response>
Gather with Speech

MessagingResponse

Generating TwiML for SMS responses is done in much the same way, but with the MessagingResponse class. Having different classes makes it easy for you to know what methods are supported in the two different contexts.

Here’s an example that replies with a simple message:

Loading Code Samples...
Language
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using System;


class Example
{
    static void Main()
    {
        var response = new MessagingResponse();
        response.Message("Store Location: 123 Easy St.");

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        Store Location: 123 Easy St.
    </Message>
</Response>
Simple sending of SMS

And an example sending a message with Media attached:

Loading Code Samples...
Language
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using Twilio.TwiML.Messaging;
using System;


class Example
{
    static void Main()
    {
        var response = new MessagingResponse();
        var message = new Message();
        message.Body("Store Location: 123 Easy St.");
        message.Media(new Uri("https://demo.twilio.com/owl.png"));
        response.Append(message);

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        <Body>Store Location: 123 Easy St.</Body>
        <Media>https://demo.twilio.com/owl.png</Media>
    </Message>
</Response>
Sending of an Message with Media (MMS)

Debugging API Requests

To assist with debugging, the library allows you to access the underlying request and response objects. This capability is built into the default HTTP client that ships with the library.

For example, you can retrieve the status code of the last response like so:

// Download the twilio-csharp library from twilio.com/docs/libraries/csharp
using System;
using System.Net;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;
using System.Collections.Generic;

class Example
{
   static void Main(string[] args)
   {
        // Find your Account Sid and Auth Token at twilio.com/console
        const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "your_auth_token";
        TwilioClient.Init(accountSid, authToken);

        var to = new PhoneNumber("+14158675309");
        var message = MessageResource.Create(
            to,
            from: new PhoneNumber("+14258675310"),
            body: "Ahoy!");

        // Retrieve the status code of the last response from the HTTP client
        var statusCode = TwilioClient.GetRestClient().HttpClient
            .LastResponse.StatusCode;

        Console.WriteLine(statusCode);
   }
}

Security Tokens for Client SDK’s

The Twilio client-side SDK’s for JavaScript, iOS, and Android require authentication or capability tokens to be generated by your server-side code. Token generation for all client SDK’s is built into the helper library. There’s no need to pull in additional NuGet packages (e.g. Twilio.Auth or Twilio.Client). The following tutorials have been updated for the new helper library and show how to generate these tokens:

ASP.NET MVC Helpers

You may have previously used the Twilio.Mvc library in your ASP.NET MVC projects. When you migrate to v5.x of this library, you will need to remove the reference to the Twilio.Mvc package and replace it with the new Twilio.AspNet.Mvc package.

Where to Find Help

All of the Quickstarts, Tutorials, and API Reference documentation will have example code in both the older 4.x library and the new 5.x library. There are hundreds of samples just waiting for you to copy and paste.

The Twilio C# helper library is open source software. Please visit us on GitHub to view the source, open issues, or submit pull requests.
Finally, we are always ready to help. Just contact us directly for support.

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        response.Say("Chapeau!", voice: "alice", language: "fr-FR");

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say voice="alice" language="fr-FR">Chapeau!</Say>
</Response>
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(input: "speech", action: new Uri("/completed"));
        gather.Say("Welcome to Twilio, please tell us why you're calling");
        response.Append(gather);

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/simple_gather.xml -->
<Response>
    <Gather input="speech" action="/completed">
           <Say>Welcome to Twilio, please tell us why you're calling</Say>
        </Gather>
</Response>
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using System;


class Example
{
    static void Main()
    {
        var response = new MessagingResponse();
        response.Message("Store Location: 123 Easy St.");

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        Store Location: 123 Easy St.
    </Message>
</Response>
SDK Version:
  • 5.x
Format:
  • TwiML
using Twilio.TwiML;
using Twilio.TwiML.Messaging;
using System;


class Example
{
    static void Main()
    {
        var response = new MessagingResponse();
        var message = new Message();
        message.Body("Store Location: 123 Easy St.");
        message.Media(new Uri("https://demo.twilio.com/owl.png"));
        response.Append(message);

        Console.WriteLine(response.ToString());;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Message>
        <Body>Store Location: 123 Easy St.</Body>
        <Media>https://demo.twilio.com/owl.png</Media>
    </Message>
</Response>