How To Build a Group SMS Application with ASP.NET MVC

Since launching Twilio SMS we’ve been impressed by the creative ways developers are integrating text messaging into their applications.

Jonathan Kressaty betwext Twilio SMSOne popular use case we’ve been seeing is group messaging, such as the Betwext application built by Jonathan Kressaty which won our SMS developer contest back in February. Betwext is a simple group text messaging service. When you use Betwext, you only have to send your message once and everyone on your active list will receive your message along with any replies by others on the list. It’s almost like adding a “reply-all” button to your texting, and it was super-useful at South by Southwest this year.

Build Your Own Group Messaging App

With Twilio’s REST API it’s easy to send text messages to any number of recipients. We’ve put together an example demonstrating how to build a simple group messaging application.  The example uses ASP.NET MVC and C# but the concepts can be easily applied to any other framework. Below we’ll discuss how to process incoming messages, handle subscribe and unsubscribe requests, and most importantly, forward messages from group members to the rest of the group.

In our group SMS app, members can join the group by texting START to your group phone number. After joining the group, any messages sent to the group number will be forwarded to all of the other members. To leave room for the sender’s number in the forwarded message, messages are limited to 140 characters in length. To leave the group, send STOP.

Group SMS Messaging Concepts

This example demonstrates receiving an incoming SMS via a POST request to your SMS URL, sending SMS messages to group members via the REST API and responding to the sender using a plain-text response to the incoming message HTTP request.

Implementation Overview

groupsms

  1. An SMS message is sent to your Twilio phone number
  2. Twilio sends a POST request to your phone number’s SMS URL (for this example it would be http://example.com/IncomingMessage).
  3. The message processor checks the message body for a command like START or STOP and changes the member’s group membership accordingly (the member list is stored in a database).
  4. If the message contains any other content and the sender is a member of the group, forward the included message to all other members via the Twilio REST API.
  5. Respond to the original sender with a confirmation message of the action taken.

Technical Requirements

This example was built with Visual Studio 2010, .NET 4, ASP.NET MVC 2, LINQ to SQL and SQL Server Express 2008. The code will work with a Visual Studio 2008, .NET 3.5 SP1 and ASP.NET MVC 1 project as well. This example also uses the TwilioRest C# SDK which can be found at http://github.com/twilio/twilio-csharp

Download

Download TwilioGroupSms.zip

Setup

For this example we’re using a simple LINQ to SQL class. You don’t have to use LINQ to SQL; any .NET data access strategy will work. Just replace the calls to the database with the equivalents in your favorite ORM. A sample database and .dbml file are included in the download.

[sql]
CREATE TABLE [Member] (
[MemberId] [int] IDENTITY(1,1) NOT NULL,
[PhoneNumber] [nvarchar](50) NULL
)
[/sql]

Database schema

In one of your controllers, create an action method to receive the SMS messages. Here’s a sample controller structure that also includes a LINQ-to-SQL DataContext for easy reference. We’ll fill in the contents of IncomingMessage below with our message processing logic.

[csharp]
public class HomeController : Controller
{
GroupSmsDataContext DB = new GroupSmsDataContext();
[HttpPost] // or [AcceptVerbs(HttpVerbs.Post)] in MVC1
public ActionResult IncomingMessage(string From, string To, string Body)
{
return View();
}
}
[/csharp]

Update your routes to allow this action to be accessed at /IncomingMessage:

[csharp]
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("Default", "{action}", new { controller = "Home", action = "Index" } );
}
[/csharp]

Message Handling

All of our message processing will be handled inside the IncomingMessage action method.

When Twilio makes the POST request to your SMS URL it includes three values (To, From, Body) which will be bound by ASP.NET MVC to the appropriate method parameter. Once we know who the message is from, where it’s going and what it contains we can process it.

We first check for a join or leave command. If the contents of the message are one of the four supported commands, we add or remove the number from the group accordingly.

[code lang="csharp"]
public ActionResult IncomingMessage(string From, string To, string Body) {
string response;
switch (Body.ToLowerInvariant().Trim()) {
case "start":
case "join":
// subscribe member
AddMemberToGroup(From);
response = "SYSTEM: Welcome to the club :) Keep those messages under 140 characters! Send STOP to leave.";
break;
case "stop":
case "leave":
// unsubscribe member
RemoveMemberFromGroup(From);
response = "SYSTEM: See ya later alligator.";
break;
[/code]

If the message contains any other content we want to 1) check to see if they’re a member of the group already and 2) if so, forward the message on to all other members in the group.

[code lang="csharp"]
default:
// prevent non-members from sending messages to the group
var member = DB.Members.FirstOrDefault(m => m.PhoneNumber == From);
if (member == null) {
response = "SYSTEM: Send START to send/receive messages from this group";
break;
}

// set up the Twilio client
var accountSid = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // TODO: replace with your account ID
var secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // TODO: replace with your key
var account = new TwilioRest.Account(accountSid, secretKey);

// grab all the members of the group, except the sender
var members = DB.Members.Where(m => m.MemberId != member.MemberId).ToList();
foreach (var recipient in members) {
// send the message to each member
var url = string.Format("/2008-08-01/Accounts/{0}/SMS/Messages", accountSid);
var values = new Hashtable();
values.Add("To", recipient.PhoneNumber);
values.Add("From", To);
values.Add("Body", From + ": " + Body.Trim());
account.request(url, "POST", values);
}

response = string.Format("SYSTEM: Message sent to {0} members", members.Count);
break;
}
[/code]

Lastly we respond back to the sender by outputting some plain text which Twilio reads and sends via SMS to the original sender.

[code lang="csharp"]
// respond with confirmation message
return Content(response, "text/plain");
}
[/code]

The membership management methods are implemented as follows. You can replace this implementation with the data access method of your choice.

[code lang="csharp"]
private void RemoveMemberFromGroup(string phoneNumber) {
// retrieve member for this phone number
var member = DB.Members.FirstOrDefault(m => m.PhoneNumber == phoneNumber);
// if they exist, delete them from the database
if (member != null) {
DB.Members.DeleteOnSubmit(member);
DB.SubmitChanges();
}
}

private void AddMemberToGroup(string phoneNumber) {
// retrieve member for this phone number
var member = DB.Members.FirstOrDefault(m => m.PhoneNumber == phoneNumber);

// if they're already a member, just ignore
if (member != null) return;

// add new member to database
member = new Member();
member.PhoneNumber = phoneNumber;
DB.Members.InsertOnSubmit(member);
DB.SubmitChanges();
}
[/code]

Next Steps

There are a lot of ways you can extend this application. Here are a couple ideas to get you started:

  • Require a PIN to join the group
  • Allow members to set a display name
  • Handle messages longer than 140 characters
  • Add an option to mute messages for X hours
  • Allow members to specify quiet hours

That’s it, you’re done!

It is super easy to build a group messaging application with Twilio and ASP.NET MVC. If you want to set this up to use yourself, download the source code, create a free Twilio account (we’ll give you $30 when you do) and start chatting away!