Twilio Company Directory Example

Software, Web

Moving on from the very simple “Hello, World” sample I discussed in my last post, I’ll now describe how to create a simple company directory application that uses Twilio in ASP.NET, C#, LINQ, and SQL Server.

This sample is translated pretty directly from the PHP example found on the Twilio demo page.

Unlike the last sample, this one actually uses some C# code-behind and has a backing database to look up and retrieve information.

OK, let’s begin with the database code. Open SQL Server Management Studio and create a new table called directory. You can do this manually via the GUI, or you can run this script:

1
2
3
4
5
CREATE TABLE directory
(
	extension varchar(12) NOT NULL PRIMARY KEY CLUSTERED,
	phone_number varchar(30)
)

Insert data into your new table using the following script:

1
2
INSERT INTO directory (extension, phone_number) VALUES (“0”, “206-555-1212”)
INSERT INTO directory (extension, phone_number) VALUES (1234,206-555-3434)

Using  Visual Studio, create a new C# web application project.

Add a new LINQ to SQL file called twilio_demo.dbml.  This will contain the LINQ mappings between your ASP.NET application and your database.

In the Server Explorer, add a new data connection by right-clicking the Data Connections folder and selecting Add Connection.

image

This will show you the Add Connection dialog:

clip_image001

Open the DBML file in the editor.

In the Server explorer, drill down through your new data connection to the Tables node.  You should see a single table called directory.

Using your mouse, drag the table to your DBML editor pane.  You’ll see a visual representation in the editor like so:

image

Next, you need to set up your content.  I opted to create separate XML files for this purpose, rather than writing the XML inline.  To do this, create three XML files as follows:

initial_greeting.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"; encoding="utf-8" ?>
<response>
	<gather>
		<say>Thank you for calling Crowdify.</say>
		<say>
			If you know your party's extension, please enter it now,
			followed by the pound sign.  Otherwise, stay on the line for the receptionist.
		</say>
	</gather>
	<say>Connecting you to the operator, please stay on the line</say>
	<dial>
		{0}
	</dial>
</response>

dialing.xml

1
2
3
4
5
6
7
<?xml version="1.0"; encoding="utf-8" ?>
<response>
	<say>Thank you, dialing now</say>
	<dial>
		{0}
	</dial>
</response>

not_found.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"; encoding="utf-8" ?>
<response>
	<gather>
		<say>I'm sorry, we couldn't find the extension {0}.</say>
		<say>
			If you know your party's extension, please enter it now,
			followed by the pound sign.  Otherwise, stay on the line for the receptionist.
		</say>
	</gather>
	<say>Connecting you to the operator, please stay on the line</say>
	<dial>
		{1}
	</dial>
</response>

You’ll notice that these XML files have string placeholders of the format {n}, into which we’ll put the dynamically-retrieved information from the database.  You could do this in a more type-safe way by using XSLT and passing parameters, but we’ll stay simple for now.

Now you’re ready to code your page that will handle the incoming Twilio requests.  Add a new ASPX page called default.aspx.

Open the file in the HTML editor and delete everything but the <%@ Page %> directive.  This is because this file will be displaying XML and we don’t want any of the default HTML hanging around.

To set up your file for displaying the correct MIME content-type, add this line to your Page_Load() method:

Page.ContentType = “text/xml”;

Now for the rest of the code.  For brevity, I’ll display the whole code of the default.aspx.cs file below, and comment afterward.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using System.Xml.Linq;
 
namespace Twilio.Web.directory_simple
{
    public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Page.Response.ContentType = &quot;text/xml&quot;;
            string extension = this.GetExtensionFromRequest();
            string receptionistNumber = this.GetReceptionistNumber();
 
            if (extension == null)
            {
                this.WriteInitialGreeting(receptionistNumber);
            }
            else
            {
                string number = this.GetPhoneNumberByExtension(extension);
                if (number != null)
                {
                    this.WriteDialing(number);
                }
                else
                {
                    this.WriteNotFound(extension, receptionistNumber);
                }
            }
        }
 
        /// <summary>
        /// Page POST variable retreival
        /// </summary>
        protected virtual string GetExtensionFromRequest()
        {
            string extension = null;
            object digits = Request[&quot;Digits&quot;];
            if (digits != null)
            {
                extension = digits.ToString();
            }
            return extension;
        }
 
        /// <summary>
        /// XML helper method
        /// </summary>
        protected virtual void WriteXmlToResponse(string fileName, string[] values)
        {
            System.Xml.XmlDocument doc = new XmlDocument();
            string path = Server.MapPath(Page.Request.ApplicationPath) + @"\directory_simple\" + fileName;
            doc.Load(path);
            string xml = doc.OuterXml;
            xml = string.Format(xml, values);
            Response.Write(xml);
        }
 
        #region Database Methods
 
        protected virtual string GetPhoneNumberByExtension(string extension)
        {
            string phone = null;
            string connString = ConfigurationManager.ConnectionStrings["twilio_demoConnectionString"].ConnectionString;
            using (twilio_directoryDataContext tdc = new twilio_directoryDataContext(connString))
            {
                var item = tdc.directories.SingleOrDefault(x => x.extension == extension);
                if (item != null)
                {
                    phone = item.phone_number;
                }
            }
 
            return phone;
        }
 
        protected virtual string GetReceptionistNumber()
        {
            return this.GetPhoneNumberByExtension("0");
        }
 
        #endregion
 
        #region Write Methods
 
        protected virtual void WriteInitialGreeting(string receptionistNumber)
        {
            this.WriteXmlToResponse("initial_response.xml", new string[1] { receptionistNumber });
        }
 
        protected virtual void WriteDialing(string number)
        {
            this.WriteXmlToResponse("dialing.xml", new string[1] { number });
        }
 
        protected virtual void WriteNotFound(string number, string receptionistNumber)
        {
            this.WriteXmlToResponse("not_found.xml", new string[2] { number, receptionistNumber });
        }
 
        #endregion
 
    }
}

Comments about this code:

In order to use the ConfigurationManager class, you need to add a reference to System.Configuration, version 2.0.50727, via the Add References dialog.

You’ll see the method GetPhoneNumberFromExtension uses the LINQ data context that was created automatically when you created your .DBML file. LINQ makes data access incredibly easy.

The Page_Load() method contains some simple logic to write out the appropriate XML content based on whether or not we’ve gotten a Digits parameter via the Post variable. I intentionally left it open to retrieving QueryString variables as well, for debugging purposes.

The XML writing helper method is self-explanatory. Note that the code for this example lives in a /directory_simple/ subdirectory of my web application.

The Connection String information was generated for you when you created your twilio_demo DBML file. It’s placed by default in the web.config file:

1
2
3
<connectionStrings>
		<add name="twilio_demoConnectionString" connectionString="Data Source=ANTHONYS-M1330\SQL2005DEV;Initial Catalog=twilio_demo;Integrated Security=True" providerName="System.Data.SqlClient"/>
	</connectionStrings>

Once you compile and deploy your web application (including the XML files), you can dial your Twilio number and work your way through the possible workflows:

  • Initial greeting; enter an extension
  • Initial greeting; wait for receptionist
  • Extension not found
  • Extension found; dialing

Again, this is a fairly simple example that doesn’t begin to tap the full power of Twilio, but shows you how to get going with a simple database-driven telephony app.

Technorati Tags:

Share and Enjoy:
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Furl
  • Ma.gnolia
  • Reddit
  • TwitThis
2 Comments

No Comments

2 Trackbacks

Leave a Reply

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">