Menu

Rate this page:

Thanks for rating this page!

We are always striving to improve our documentation quality, and your feedback is valuable to us. How could this documentation serve you better?

Dynamic Call Center with C# and ASP.NET MVC

Download the Code

In this tutorial we will show how to automate the routing of calls from customers to your support agents. In this example customers would select a product, then be connected to a specialist for that product. If no one is available our customer's number will be saved so that our agent can call them back.

This is what the application does at a high level:

  • Configure a workspace using the Twilio TaskRouter REST API.
  • Listen for incoming calls and let the user select a product with the dial pad.
  • Create a Task with the selected product and let TaskRouter handle it.
  • Store missed calls so agents can return the call to customers.
  • Redirect users to a voice mail when no one answers the call.
  • Allow agents to change their status (Available/Offline) via SMS.
Let's get started!

Configure the Workspace

In order to instruct TaskRouter to handle the Tasks, we need to configure a Workspace. We can do this in the TaskRouter Console or programmatically using the TaskRouter REST API.

In this ASP.NET MVC application this step will be executed in the Application_Start event every time you run the app.

A Workspace is the container element for any TaskRouter application. The elements are:

  • Tasks - Represents a customer trying to contact an agent
  • Workers - The agents responsible for handling Tasks
  • Task Queues - Holds Tasks to be consumed by a set of Workers
  • Workflows - Responsible for placing Tasks into Task Queues
  • Activities - Possible states of a Worker. Eg: idle, offline, busy

We'll use a TaskRouterClient provided in the twilio-csharp helper library to create and configure the workspace.

Loading Code Sample...
      
      
      
      
      TaskRouter.Web/App_Start/WorkspaceConfig.cs

      Create, Setup and Configure the Workspace

      TaskRouter.Web/App_Start/WorkspaceConfig.cs

      Now let's look in more detail at all the steps, starting with the creation of the workspace itself.

      See how to create a new workspace

      Create a Workspace

      Before creating a workspace, we need to delete any others with the same friendlyName as the one we are trying to create. In order to create a workspace we need to provide a friendlyName and a eventCallbackUrl where a requests will be made every time an event is triggered in our workspace.

      Loading Code Sample...
          
          
          
          
          TaskRouter.Web/App_Start/WorkspaceConfig.cs

          Create Workspace

          TaskRouter.Web/App_Start/WorkspaceConfig.cs

          We have a brand new workspace, now we need workers. Let's create them on the next step.

          Check out how to create a couple of workers

          Create the Workers

          We'll create two workers, Bob and Alice. They each have two attributes: contact_uri a phone number and products, a list of products each worker is specialized in. We also need to specify an activity.Sid and a name for each worker. The selected activity will define the status of the worker.

          A set of default activities is created with your workspace. We use the Idle activity to make a worker available for incoming calls.

          Loading Code Sample...
              
              
              
              
              TaskRouter.Web/App_Start/WorkspaceConfig.cs

              Create Workers

              TaskRouter.Web/App_Start/WorkspaceConfig.cs

              After creating our workers, let's set up the Task Queues.

              See how to create the Task Queues

              Create the Task Queues

              Next, we set up the Task Queues. Each with a friendlyName and a targetWorkers, which is an expression to match Workers. Our Task Queues are:

              1. SMS - Will target Workers specialized in Programmable SMS, such as Bob, using the expression "products HAS \"ProgrammableSMS\"".
              2. Voice - Will do the same for Programmable Voice Workers, such as Alice, using the expression "products HAS \"ProgrammableVoice\"".
              Loading Code Sample...
                  
                  
                  
                  
                  TaskRouter.Web/App_Start/WorkspaceConfig.cs

                  Create Task Queues

                  TaskRouter.Web/App_Start/WorkspaceConfig.cs

                  We have a Workspace, Workers and Task Queues... what's left? A Workflow. Let's see how to create one next!

                  Check out the code to create a Workflow

                  Create a Workflow

                  Finally, we create the Workflow using the following parameters:

                  1. friendlyName as the name of a Workflow.
                  2. assignmentCallbackUrl and fallbackAssignmentCallbackUrl as the public URL where a request will be made when this Workflow assigns a Task to a Worker. We will learn how to implement it on the next steps.
                  3. Timeout as the maximum time we want to wait until a Worker is available for handling a Task.
                  4. workflowConfiguration which is a set of rules for placing Tasks into Task Queues. The routing configuration will take a Task's attribute and match this with Task Queues. This application's Workflow rules are defined as:
                    1. "selected_product==\ "ProgrammableSMS\"" expression for SMS Task Queue. This expression will match any Task with ProgrammableSMS as the selected_product attribute.
                    2. "selected_product==\ "ProgrammableVoice\"" expression for Voice Task Queue.
                  Loading Code Sample...
                      
                      
                      
                      
                      TaskRouter.Web/App_Start/WorkspaceConfig.cs

                      Create a Workflow

                      TaskRouter.Web/App_Start/WorkspaceConfig.cs

                      Our workspace is completely setup. Now it's time to see how we use it to route calls.

                      See how we handle incoming Twilio requests

                      Handle Twilio's Request

                      Right after receiving a call, Twilio will send a request to the URL specified on the number's configuration.

                      The endpoint will then process the request and generate a TwiML response. We'll use the Say verb to give the user product alternatives, and a key they can press in order to select one. The Gather verb allows us to capture the user's key press.

                      Loading Code Sample...
                          
                          
                          
                          
                          TaskRouter.Web/Controllers/CallController.cs

                          Handling Twilio's Requests

                          TaskRouter.Web/Controllers/CallController.cs

                          We just asked the caller to choose a product, next we will use their choice to create the appropiate Task.

                          See how to create a Task

                          Create a Task

                          This is the endpoint set as the action URL on the Gather verb on the previous step. A request is made to this endpoint when the user presses a key during the call. This request has a Digits parameter that holds the pressed keys. A Task will be created based on the pressed digit with the selected_product as an attribute. The Workflow will take this Task's attributes and match them with the configured expressions in order to find a Task Queue for this Task, so an appropriate available Worker can be assigned to handle it.

                          We use the Enqueue verb with a WorkflowSid attribute to integrate with TaskRouter. Then the voice call will be put on hold while TaskRouter tries to find an available Worker to handle this Task.

                          Loading Code Sample...
                              
                              
                              
                              
                              TaskRouter.Web/Controllers/CallController.cs

                              Create a Task

                              TaskRouter.Web/Controllers/CallController.cs

                              After sending a Task to Twilio, let's see how we tell TaskRouter which Worker to use to execute that task.

                              See how to assign a Worker

                              Assign a Worker

                              When TaskRouter selects a Worker, it does the following:

                              1. The Task's Assignment Status is set to 'reserved'.
                              2. A Reservation instance is generated, linking the Task to the selected Worker.
                              3. At the same time the Reservation is created, a POST request is made to the Workflow's AssignmentCallbackURL, which was configured using the WorkspaceConfig class when the application is initialized. This request includes the full details of the Task, the selected Worker, and the Reservation.

                              Handling this Assignment Callback is a key component of building a TaskRouter application as we can instruct how the Worker will handle a Task. We could send a text, e-mail, push notifications or make a call.

                              Since we created this Task during a voice call with an Enqueue verb, let's instruct TaskRouter to dequeue the call and dial a Worker. If we do not specify a to parameter with a phone number, TaskRouter will pick the Worker's contact_uri attribute.

                              We also send a post_work_activity_sid which will tell TaskRouter which Activity to assign this worker after the call ends.

                              Loading Code Sample...
                                  
                                  
                                  
                                  
                                  TaskRouter.Web/Controllers/CallbackController.cs

                                  Assign a Worker

                                  TaskRouter.Web/Controllers/CallbackController.cs

                                  Now that our Tasks are routed properly, let's deal with missed calls in the next step.

                                  Check out how to collect missed calls

                                  Collect Missed Calls

                                  This endpoint will be called after each TaskRouter Event is triggered. In our application, we are trying to collect missed calls, so we would like to handle the workflow.timeout event. This event is triggered when the Task waits more than the limit set on Workflow Configuration-- or rather when no worker is available.

                                  Here we use TwilioRestClient to route this call to a Voicemail Twimlet. Twimlets are tiny web applications for voice. This one will generate a TwiML response using Say verb and record a message using Record verb. The recorded message will then be transcribed and sent to the email address configured.

                                  Note that we are also listening for task.canceled. This is triggered when the customer hangs up before being assigned to an agent, therefore canceling the task. Capturing this event allows us to collect the information from the customers that hang up before the Workflow times out.

                                  Loading Code Sample...
                                      
                                      
                                      
                                      
                                      TaskRouter.Web/Controllers/CallbackController.cs

                                      Collect Missed Calls

                                      TaskRouter.Web/Controllers/CallbackController.cs

                                      Most of the features of our application are implemented. The last piece is allowing the Workers to change their availability status. Let's see how to do that next.

                                      See how to allow Workers change their availability status

                                      Change a Worker's Activity

                                      We have created this endpoint, so a worker can send an SMS message to the support line with the command "On" or "Off" to change their availability status.

                                      This is important as a worker's activity will change to Offline when they miss a call. When this happens, they receive an SMS letting them know that their activity has changed, and that they can reply with the On command to make themselves available for incoming calls again.

                                      Loading Code Sample...
                                          
                                          
                                          
                                          
                                          TaskRouter.Web/Controllers/MessageController.cs

                                          Changing a Worker's Activity

                                          TaskRouter.Web/Controllers/MessageController.cs

                                          Congratulations! You finished this tutorial. As you can see, using Twilio's TaskRouter is quite simple.

                                          Where to next?

                                          Where to Next?

                                          If you're a .NET developer working with Twilio, you might also enjoy these tutorials:

                                          Browser-Calls

                                          Learn how to use Twilio Client to make browser-to-phone and browser-to-browser calls with ease.

                                          ETA-Notifications

                                          Learn how to implement ETA Notifications using ASP.NET MVC and Twilio.

                                          Did this help?

                                          Thanks for checking out this tutorial! If you have any feedback to share with us, we'd love to hear it. Tweet @twilio to let us know what you think!

                                          Agustin Camino Jose Oliveros David Prothero Kat King Hector Ortega

                                          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.

                                          Loading Code Sample...