Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3015,6 +3015,4 @@ The newest version of the `twilio-csharp` helper library!

This version brings a host of changes to update and modernize the `twilio-csharp` helper library. It is auto-generated to produce a more consistent and correct product.

- [Migration Guide](https://www.twilio.com/docs/libraries/csharp/migrating-your-csharp-dot-net-application-twilio-sdk-4x-5x)
- [Full API Documentation](https://twilio.github.io/twilio-csharp/)
- [General Documentation](https://www.twilio.com/docs/libraries/csharp)
5 changes: 0 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,6 @@ you're working on.
For large fixes, please build and test the documentation before submitting the
PR to be sure you haven't accidentally introduced layout or formatting issues.

If you want to help improve the docs at
[https://www.twilio.com/docs/libraries/csharp][docs-link], please contact
[help@twilio.com](mailto:help@twilio.com).

## <a name="submit"></a> Submission Guidelines

### Submitting an Issue
Expand Down Expand Up @@ -171,6 +167,5 @@ you are working:
* All features or bug fixes **must be tested** by one or more tests.
* All classes and methods **must be documented**.

[docs-link]: https://www.twilio.com/docs/libraries/csharp
[issue-link]: https://github.com/twilio/twilio-csharp/issues/new
[github]: https://github.com/twilio/twilio-csharp
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ More documentation for this library can be found [here][libdocs].

### Migrate from earlier versions

See the migration guide [here][migrating]. Also, if you were using the `Twilio.Mvc` package, that has been replaced by the [Twilio.AspNet.Mvc][aspnet] package which is compatible with this version of the library.
See the migration guide [here](./UPGRADE.md). Also, if you were using the `Twilio.Mvc` package, that has been replaced by the [Twilio.AspNet.Mvc][aspnet] package which is compatible with this version of the library.

### TLS 1.2 Requirements

New accounts and subaccounts are now required to use TLS 1.2 when accessing the REST API. ["Upgrade Required" errors](https://www.twilio.com/docs/api/errors/20426) indicate that TLS 1.0/1.1 is being used. With .NET, you can enable TLS 1.2 using this setting:

```csharp
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
```
Expand All @@ -38,17 +39,22 @@ The best and easiest way to add the Twilio libraries to your .NET project is to

From within Visual Studio, you can use the NuGet GUI to search for and install the Twilio NuGet package. Or, as a shortcut, simply type the following command into the Package Manager Console:

Install-Package Twilio
```shell
Install-Package Twilio
```

### With .NET Core Command Line Tools

If you are building with the .NET Core command line tools, then you can run the following command from within your project directory:

dotnet add package Twilio
```shell
dotnet add package Twilio
```

## Sample usage

The examples below show how to have your application initiate and outbound phone call and send an SMS message using the Twilio .NET helper library:

```csharp
TwilioClient.Init("ACCOUNT_SID", "AUTH_TOKEN");

Expand Down Expand Up @@ -79,6 +85,7 @@ TwilioClient.SetEdge("sydney");
This will result in the `hostname` transforming from `api.twilio.com` to `api.sydney.au1.twilio.com`.

## Enable debug logging

There are two ways to enable debug logging in the default HTTP client. You can create an environment variable called `TWILIO_LOG_LEVEL` and set it to `debug` or you can set the LogLevel variable on the client as debug:

```csharp
Expand Down Expand Up @@ -131,30 +138,32 @@ Console.WriteLine(response);

## Use a custom HTTP Client

To use a custom HTTP client with this helper library, please see the [Twilio documentation](https://www.twilio.com/docs/libraries/csharp-dotnet/custom-http-clients-dot-net-framework).
To use a custom HTTP client with this helper library, please see the [advanced example of how to do so](./advanced-examples/custom-http-client.md).

## Docker Image

The `Dockerfile` present in this repository and its respective `twilio/twilio-csharp` Docker image are used by Twilio for testing purposes.

You could use the docker image for building and running tests:

```bash
docker build -t twiliobuild .
```

Bash:

```bash
docker run -it --rm -v $(pwd):/twilio twiliobuild
make test
```

Powershell:

```pwsh
docker run -it --rm -v ${PWD}:/twilio twiliobuild
make test
```


## Get support

If you need help installing or using the library, please check the [Twilio Support Help Center](https://support.twilio.com) first, and [file a support ticket](https://twilio.com/help/contact) if you don't find an answer to your question.
Expand All @@ -165,5 +174,4 @@ If you've instead found a bug in the library or would like new features added, g
[apidocs]: https://www.twilio.com/docs/api
[twiml]: https://www.twilio.com/docs/api/twiml
[libdocs]: https://www.twilio.com/docs/libraries/reference/twilio-csharp/
[migrating]: https://www.twilio.com/docs/libraries/csharp-dotnet/usage-guide
[aspnet]: https://github.com/twilio/twilio-aspnet
2 changes: 0 additions & 2 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ _`MAJOR` version bumps will have upgrade notes posted here._

Behind the scenes Csharp Helper is now auto-generated via OpenAPI with this release. This enables us to rapidly add new features and enhance consistency across versions and languages.

To learn more about the Csharp Helper Library, check out [our docs](https://www.twilio.com/docs/libraries/csharp-dotnet).

[2017-11-XX] 5.8.x to 5.9.x
---------------------------

Expand Down
187 changes: 187 additions & 0 deletions advanced-examples/custom-http-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# Custom HTTP Clients for the Twilio C# Helper Library with .NET Framework

If you are working with the Twilio C# / .NET Helper Library, and you need to be able to modify the HTTP requests that the library makes to the Twilio servers, you’re in the right place. The most common need to alter the HTTP request is to connect and authenticate with an enterprise’s proxy server. We’ll provide sample code that you can drop right into your app to handle this use case.

## Connect and authenticate with a proxy server

To connect and provide credentials to a proxy server that may be between your app and Twilio, you need a way to modify the HTTP requests that the Twilio helper library makes on your behalf to invoke the Twilio REST API.

On .NET 4.5.1 and above, the Twilio helper library uses the `HttpClient` class (in the `System.Net.Http` `namespace`) under the hood to make the HTTP requests. Knowing this, the following two facts should help us arrive at the solution:

- Connecting to a proxy server with `HttpClient` is a [solved problem](https://gist.github.com/bryanbarnard/8102915).
- The Twilio Helper Library allows you to provide your own `HttpClient` for making API requests.

So the question becomes how do we apply this to a typical Twilio REST API example?

```csharp
TwilioClient.Init(accountSid, authToken);

var message = MessageResource.Create(
to: new PhoneNumber("+15558675309"),
from: new PhoneNumber("+15017250604"),
body: "Hello from C#");
```

Where does a `TwilioRestClient` get created and used? Out of the box, the helper library is creating a default `TwilioRestClient` for you, using the Twilio credentials you pass to the `Init` method. However, there’s nothing stopping you from creating your own and using that.

Once you have your own `TwilioRestClient`, you can pass it to any Twilio REST API resource action you want. Here’s an example of sending an SMS message with a custom client:

```csharp
using System;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

namespace CustomClientDotNet4x
{
class Program
{
static void Main(string[] args)
{
var twilioRestClient = ProxiedTwilioClientCreator.GetClient();

// Now that we have our custom built TwilioRestClient,
// we can pass it to any REST API resource action.
var message = MessageResource.Create(
to: new PhoneNumber("+15017122661"),
from: new PhoneNumber("+15017122661"),
body: "Hey there!",
// Here's where you inject the custom client
client: twilioRestClient
);

Console.WriteLine($"Message SID: {message.Sid}");
}
}
}
```

## Create your custom TwilioRestClient

When you take a closer look at the constructor for `TwilioRestClient`, you see that the `httpClient` parameter is actually of type `Twilio.Http.HttpClient` and not the `System.Net.HttpClient` we were expecting. `Twilio.Http.HttpClient` is actually an abstraction that allows plugging in any implementation of an HTTP client you want (or even creating a mocking layer for unit testing).

However, within the helper library, there is an implementation of `Twilio.Http.HttpClient` called SystemNetHttpClient. This class wraps the `System.Net.HttpClient` and provides it to the Twilio helper library to make the necessary HTTP requests.

## Call Twilio through the proxy server

Now that we understand how all the components fit together, we can create our own `TwilioRestClient` that can connect through a proxy server. To make this reusable, here’s a class that you can use to create this `TwilioRestClient` whenever you need one.

```csharp
using System;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Text;
using Twilio.Clients;

namespace CustomClientDotNet4x
{
public static class ProxiedTwilioClientCreator
{
private static HttpClient _httpClient;

private static void CreateHttpClient()
{
var proxyUrl = ConfigurationManager.AppSettings["ProxyServerUrl"];
var handler = new HttpClientHandler()
{
Proxy = new WebProxy(proxyUrl),
UseProxy = true
};

_httpClient = new HttpClient(handler);
var byteArray = Encoding.Unicode.GetBytes(
ConfigurationManager.AppSettings["ProxyUsername"]
+ ":"
+ ConfigurationManager.AppSettings["ProxyPassword"]
);

_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(byteArray)
);
}

public static TwilioRestClient GetClient()
{
var accountSid = ConfigurationManager.AppSettings["TwilioAccountSid"];
var authToken = ConfigurationManager.AppSettings["TwilioAuthToken"];

if (_httpClient == null)
{
// It's best* to create a single HttpClient and reuse it
// * See: https://goo.gl/FShAAe
CreateHttpClient();
}

var twilioRestClient = new TwilioRestClient(
accountSid,
authToken,
httpClient: new Twilio.Http.SystemNetHttpClient(_httpClient)
);

return twilioRestClient;
}
}
}
```

Notice the use of `ConfigurationManager.AppSettings` to retrieve various configuration settings:

- Your Twilio Account Sid and Auth Token ([found here, in the Twilio console](https://console.twilio.con))
- Your proxy server URL (including the server name or address and port number)
- Your username and password for the proxy server

These settings can be placed in your Web.config or App.config (for a console app) like so:

```xml
<appSettings>
<!-- Find your Twilio Account Sid and Token at twilio.com/console -->
<add key="TwilioAccountSid" value="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
<add key="TwilioAuthToken" value="your_auth_token" />

<!-- Replace the following with your proxy server's settings -->
<add key="ProxyServerUrl" value="http://127.0.0.1:8888"/>
<add key="ProxyUsername" value="your_username"/>
<add key="ProxyPassword" value="your_password"/>
</appSettings>
```

Here’s a console program that sends a text message and shows how it all can work together.

```csharp
using System;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

namespace CustomClientDotNet4x
{
class Program
{
static void Main(string[] args)
{
var twilioRestClient = ProxiedTwilioClientCreator.GetClient();

// Now that we have our custom built TwilioRestClient,
// we can pass it to any REST API resource action.
var message = MessageResource.Create(
to: new PhoneNumber("+15017122661"),
from: new PhoneNumber("+15017122661"),
body: "Hey there!",
// Here's where you inject the custom client
client: twilioRestClient
);

Console.WriteLine($"Message SID: {message.Sid}");
}
}
}
```

## What else can this technique be used for?

Now that you know how to inject your own System.Net.HttpClient into the Twilio API request pipeline, you could use this technique to add custom HTTP headers to the requests (perhaps as required by an upstream proxy server).

You could also implement your own Twilio.Http.HttpClient to mock the Twilio API responses so your unit and integration tests can run quickly without the need to make a connection to Twilio. In fact, there’s [already an example online](https://github.com/dprothero/twilio-mock-example) showing how to do exactly that.

We can’t wait to see what you build!