Skip to contentSkip to navigationSkip to topbar
On this page

Send and Receive Media Messages with WhatsApp in C#/ASP.NET


(warning)

Warning

Twilio is launching a new Console. Some screenshots on this page may show the Legacy Console and therefore may no longer be accurate. We are working to update all screenshots to reflect the new Console experience. Learn more about the new Console(link takes you to an external page).

In this tutorial, we'll set up a C#/ASP.NET application that uses the WhatsApp Channel to:

  • Send media messages
  • Reply to incoming messages with media

The code samples in this tutorial use Twilio's C# helper library(link takes you to an external page) and ASP.NET MVC 5.


Send outbound media messages through WhatsApp

send-outbound-media-messages-through-whatsapp page anchor

Just like when sending an MMS, sending an outbound WhatsApp message uses Twilio's Message resource. This section walks you through the setting up and sending media in a WhatsApp message. Media can consist of images, audio files, and PDF documents.

Sign up for (or log in to) your Twilio Account and activate the Sandbox

sign-up-for-or-log-in-to-your-twilio-account-and-activate-the-sandbox page anchor

Before you can send a WhatsApp message from your web language, you'll need to sign up for a Twilio account(link takes you to an external page) or sign into your existing account and activate the Twilio Sandbox for WhatsApp(link takes you to an external page). The Sandbox allows you to prototype with WhatsApp immediately using a shared phone number without waiting for your Twilio number to be approved by WhatsApp.

To get started, select a number from the available sandbox numbers to activate your sandbox.

WA_Sandbox.

Be sure to take note of the phone number you choose in the Sandbox. You will need this later when we're ready to send some messages.

Gather your Twilio account information

gather-your-twilio-account-information page anchor

Before you can send any messages, you'll need to gather your Twilio account credentials. You can find these in the Twilio Console(link takes you to an external page).

  • Account SID - Used to identify yourself in API requests
  • Auth Token - Used to authenticate REST API requests
Account Credentials.

For all of our code snippets and Python examples, you need to authenticate with the Account SID and Auth Token.

(error)

Danger

This tutorial uses hard-coded credentials at the top of the code; you should follow best practices regarding credential protection in production.

Send a media WhatsApp message via the REST API

send-a-media-whatsapp-message-via-the-rest-api page anchor

To send an outgoing media message via WhatsApp from your Twilio account you'll need to make an HTTP POST to Twilio's Message resource.

Sending a media message through WhatsApp is similar to sending a text-based message over WhatsApp with one important addition: the media_url parameter. The media_url parameter in this code tells Twilio where to retrieve the media that we want to include in the WhatsApp message. (You can prevent unauthorized access to your media(link takes you to an external page) by turning on HTTP Basic Auth for media URLs in the Twilio Console(link takes you to an external page).)

(warning)

Warning

If you have joined your Sandbox > 24 hours ago, you will need to send a fresh inbound message to your WhatsApp number in order to then send yourself a media message. WhatsApp currently does not support media in "template" messages that take place outside of a 24-hour "session".

Twilio's C# helper library helps you to create a new instance of the Message resource. When you do this, you'll specify the to, from, and mediaUrl parameters of your message.

If you don't already have the C# helper library installed you can install it using NuGet:

Install-Package Twilio -ProjectName MyProject

Now, create a file named program.cs and include the following code:

Send a media message with WhatsAppLink to code sample: Send a media message with WhatsApp
1
// Install the C# / .NET helper library from twilio.com/docs/csharp/install
2
3
using System;
4
using Twilio;
5
using Twilio.Rest.Api.V2010.Account;
6
using System.Threading.Tasks;
7
using System.Collections.Generic;
8
9
class Program {
10
public static async Task Main(string[] args) {
11
// Find your Account SID and Auth Token at twilio.com/console
12
// and set the environment variables. See http://twil.io/secure
13
string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");
14
string authToken = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN");
15
16
TwilioClient.Init(accountSid, authToken);
17
18
var message = await MessageResource.CreateAsync(
19
mediaUrl: new List<Uri> { new Uri(
20
"https://images.unsplash.com/photo-1545093149-618ce3bcf49d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=668&q=80") },
21
from: new Twilio.Types.PhoneNumber("whatsapp:+14155238886"),
22
to: new Twilio.Types.PhoneNumber("whatsapp:+15017122661"));
23
24
Console.WriteLine(message.Sid);
25
}
26
}

Output

1
{
2
"account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
3
"api_version": "2010-04-01",
4
"body": "Hello! 👍",
5
"date_created": "Thu, 24 Aug 2023 05:01:45 +0000",
6
"date_sent": "Thu, 24 Aug 2023 05:01:45 +0000",
7
"date_updated": "Thu, 24 Aug 2023 05:01:45 +0000",
8
"direction": "outbound-api",
9
"error_code": null,
10
"error_message": null,
11
"from": "whatsapp:+14155238886",
12
"num_media": "0",
13
"num_segments": "1",
14
"price": null,
15
"price_unit": null,
16
"messaging_service_sid": "MGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
17
"sid": "SMaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
18
"status": "queued",
19
"subresource_uris": {
20
"media": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages/SMaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Media.json"
21
},
22
"tags": {
23
"campaign_name": "Spring Sale 2022",
24
"message_type": "cart_abandoned"
25
},
26
"to": "whatsapp:+15017122661",
27
"uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages/SMaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"
28
}

Replace the placeholder values for accountSid and authToken with your unique values. You can find these in your Twilio console(link takes you to an external page).

(error)

Danger

Please note: it's okay to hard-code your credentials when getting started, but you should use environment variables to keep them secret before deploying to production. Check out how to keep your Twilio credentials secure.

The to number should be the phone number for the destination WhatsApp account in the E.164 format. If you are using the WhatsApp Sandbox, you can only send messages to numbers that have joined the Sandbox.

You'll tell Twilio which phone number to use to send this message by replacing the from number with the whatsapp: channel identifier followed by the Sandbox number in E.164 format.

Save the file, compile it and then run the executable:

1
csc program.cs
2
program

In a few moments, you should receive a WhatsApp message with an image!

Please note that WhatsApp does not support including a text body in the same message as a video, audio file, document, contact (vCard), or location. If you pass the Body parameter on a message with one of these media types, the body will be ignored and not delivered to the device.

Understanding Twilio's Response

understanding-twilios-response page anchor

When you send an outbound WhatsApp media message, Twilio sends data about the message in its response to your request. The JSON response contains the unique SID and URI for your media resource:

"subresource_uris": {"media": "/2010-04 01/Accounts/ACxxxxxxxx/Messages/SMxxxxxxxxxxxxx/Media.json"}

When the Twilio REST API creates your new Message resource, it saves the image found at the specified mediaUrl as a Media resource. Once created, you can access this resource at any time via the API.

You can print this value from your C# code to see where the image is stored. The following line to the end of your program.cs file prints out your newly provisioned Media URI:

Debug.WriteLine(message.SubresourceUris["media"]);

Respond with media in WhatsApp

respond-with-media-in-whatsapp page anchor

To reply using media to incoming WhatsApp messages, you'll need to provide Twilio with a webhook URL that points to a server that runs code to inspect and save the media files.

(warning)

Warning

WhatsApp media content is currently only supported in Session Messages. If the WhatsApp session with a user expires, you must wait for an inbound message to create a new session before you can send them a media message.

Webhooks are user-defined HTTP(link takes you to an external page) callbacks. They are usually triggered by some event, such as receiving an SMS message or an incoming phone call. When that event occurs, Twilio makes an HTTP request (usually a POST or a GET(link takes you to an external page)) to the URL configured for the webhook.

To handle a webhook, you only need to build a small web application that can accept the HTTP requests. Almost all server-side programming languages offer some framework for you to do this. In this tutorial, we'll be setting up our web application with ASP.NET(link takes you to an external page).

Webhook functionality is the same for every Twilio application. First, a webhook makes an HTTP request to a URI that you provide to Twilio. When it receives this request, your application performs pre-defined logic. This could be something like database read/writes or calling another API. Finally, your application sends a TwiML response to Twilio in which it specifies the instructions for Twilio to follow.

TwiML is the Twilio Markup Language, which is just to say that it's an XML(link takes you to an external page) document with special tags defined by Twilio to help you build your messaging and voice applications.

TwiML is easier shown than explained:

1
<?xml version="1.0" encoding="UTF-8"?>
2
<Response>
3
<Message>Thanks for the message!</Message>
4
</Response>

Every TwiML document has the <Response> element, which can contain one or more verbs. Verbs are actions you'd like Twilio to take, such as <Say> a greeting to a caller, or send an SMS <Message> in reply to an incoming message. For a full reference on everything you can do with TwiML, refer to our TwiML API Reference.

To send back a media in your WhatsApp reply, you need to include the media TwiML element with the URL to the media file. One media attachment is supported per message, with a size limit of 5MB.

Generate TwiML in your application

generate-twiml-in-your-application page anchor

To reply to an incoming WhatsApp message, you can either write raw TwiML or use a helper library. When you use the helper library, you don't have to worry about generating the raw XML yourself.

Reply with media to incoming WhatsApp messages

reply-with-media-to-incoming-whatsapp-messages page anchor
1
using Newtonsoft.Json;
2
using System.Diagnostics;
3
using System.Linq;
4
using System.Web.Mvc;
5
using Twilio.AspNet.Mvc;
6
using Twilio.TwiML;
7
using HttpPostAttribute = System.Web.Mvc.HttpPostAttribute;
8
using static System.Linq.Enumerable;
9
using Microsoft.Win32;
10
using System.Net;
11
using System;
12
using System.IO;
13
using Twilio.TwiML.Messaging;
14
15
namespace WhatsappMediaTutorial.Controllers
16
{
17
public class WhatsAppMediaController : TwilioController
18
{
19
public static Uri GOOD_BOY_URL = new Uri("https://images.unsplash.com/photo-1518717758536-85ae29035b6d?ixlib=" +
20
"rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80");
21
22
public virtual SystemWebClient webClient()
23
{
24
return new SystemWebClient();
25
}
26
27
[HttpPostAttribute]
28
public TwiMLResult Create(FormCollection formCollection)
29
{
30
var numMedia = int.Parse(formCollection["NumMedia"]);
31
32
var response = new MessagingResponse();
33
34
if (numMedia > 0)
35
{
36
var message = new Message();
37
message.Body("Thanks for the image! Here's one for you!");
38
message.Media(GOOD_BOY_URL);
39
response.Append(message);
40
} else
41
{
42
response.Message("Send us an image!");
43
}
44
45
return TwiML(response);
46
}
47
48
private string AppDataDirectory
49
{
50
get {
51
var dataDirectory = Path.Combine(
52
Environment.CurrentDirectory,
53
@"..\..\..\WhatsAppMediaTutorial\App_Data\"
54
);
55
return Path.GetFullPath(dataDirectory);
56
}
57
}
58
59
public static string GetDefaultExtension(string mimeType)
60
{
61
var key = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type\" + mimeType, false);
62
var value = key != null ? key.GetValue("Extension", null) : null;
63
var result = value != null ? value.ToString() : string.Empty;
64
65
return result;
66
}
67
68
private void LogParamsAsJson() => Debug.WriteLine(JsonConvert.SerializeObject(
69
Request.Params.AllKeys.ToDictionary(r => r, r => Request.Params[r]),
70
Formatting.Indented
71
).ToString());
72
}
73
}

You have the code - now you need a URL you can give to Twilio.

Twilio can only access public servers on the Internet. That means you need to take your web application and publish it to a web or cloud hosting provider (of which there are many(link takes you to an external page)), you can host it on your own server, or you can use a service such as ngrok(link takes you to an external page) to expose your local development machine to the internet. (We only recommend the latter for development and testing purposes and not for production deployments.)

To send media in response to an incoming WhatsApp message, add an image URL. If necessary, restart your server, then send a message to your WhatsApp number again. You should receive a WhatsApp message that includes an image. Check out the API Reference for more details.

Configure your webhook URL

configure-your-webhook-url page anchor

Now that you have a URL for your web application's TwiML reply generating routine, you can configure your Twilio phone number to call your webhook URL whenever a new WhatsApp message comes in for you.

You can set the webhook URL for incoming messages to your server in the Sandbox(link takes you to an external page).

Make sure you choose HTTP POST or HTTP GET to correspond to what your web application is expecting. Usually, the default of POST is fine.

(warning)

Protect your webhooks

Twilio supports HTTP Basic and Digest Authentication. Authentication allows you to password protect your TwiML URLs on your web server so that only you and Twilio can access them.

Learn more here, and check out our guide to securing your ASP.NET application by validating incoming Twilio requests.

And that's all there is to it; receiving and responding is exactly the same as you would do in any SMS app with our Messaging API. Cool, right?


Examine media on incoming WhatsApp messages

examine-media-on-incoming-whatsapp-messages page anchor

Viewing, saving, or manipulating the media on incoming WhatsApp messages also involves configuring a Webhook URL. The URL points to a server generating TwiML instructions including the media you want to send.

Get incoming message details

get-incoming-message-details page anchor

When Twilio calls your webhook, it sends a number of parameters about the message you just received. Most of these, such as the To phone number, the From phone number, and the Body of the message are available as properties of the request parameter to our action method.

Twilio sends form variables named MediaUrlX, where X is a zero-based index. WhatsApp messages will only contain one media file per incoming message, so you can access the file at MediaUrl0 on the incoming request from Twilio to your webhook URL.

Determine Content-Type of media

determine-content-type-of-media page anchor

Attachments to WhatsApp messages can be of many different file types, including JPG, MP3, and PDF. (See more about the supported file types in the FAQs(link takes you to an external page).) Twilio handles the determination of the file type for you and you can get the standard mime type(link takes you to an external page) from the MediaContentTypeX parameter. If you are expecting photos and images, then you will likely see a lot of attachments with the mime type image/jpeg.


All the code, in a complete working project, is available on GitHub. To dig deeper, head over to the Messaging API Reference and learn more about the Twilio webhook request and the REST API Media resource. Also, you should be aware of the pricing(link takes you to an external page) for storage of all the media files that you keep on Twilio's servers.

We'd love to hear what you build with this!

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.