Search code examples
c#twiliotwilio-twiml

change Twiml response message <say>


I have created application and i am using twilio to make outbound calls. But, whenever i make call i have same XML document with me that has static Hello, your account is deleted. but this time i want to add parameters in it too. for example Hello, your account {accountnumber} is deleted. My code is as follow :-

public void call()
{
    // Find your Account Sid and Token at twilio.com/console
    const string accountSid = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    const string authToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    TwilioClient.Init(accountSid, authToken);
    try
    {


        var call = CallResource.Create(
                    method: Twilio.Http.HttpMethod.Get,
                    url: new Uri("https://automatecondominium.com/Services/Twilio/VoiceMessages/twiliomessage.xml"),
                    to: new Twilio.Types.PhoneNumber("+917018244303"),
                    from: new Twilio.Types.PhoneNumber("+15206197315")
                    );


    }
    catch (Exception)
    {

        throw;
    }


}

Solution

  • You should not be sending having large parameters as part of the URL.

    You are having language, voice and message parameters as part of the URL. You should be generating those values as part of the code, they should not be coming as parameters. You should only have a parameter value based on which you can generate all these values and send in TwiML.

    Consider following.

    public void MakeCall()
    {
        const string accountSid = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        const string authToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
        TwilioClient.Init(accountSid, authToken);
        try
        {
            //Generate and store message data in some datastore and 
            //Create and identifier to get that data later.
            // GenerateMessageData method does the same thing.
            var messageId = GenerateMessageData();
    
            //Pass the messageId as URL parameter.
            var call = CallResource.Create(
                        method: Twilio.Http.HttpMethod.Get,
                        url: new Uri("https://automatecondominium.com/twilio/twiml?p="+messageId),
                        to: new Twilio.Types.PhoneNumber("+917018244303"),
                        from: new Twilio.Types.PhoneNumber("+15206197315")
                        );
    
        }
        catch (Exception)
        {
             throw;
        }
    }
    
    private string GenerateMessageData()
        {
            var messageId = Guid.NewGuid().ToString();
    
            var messageContent = "Some Message"; // This could be any message you want.
            var language = "Somelanguage"; //this could be any language you want.
            var voice = "SomeVoice"; // Male or Female whichever you want. 
            var messageData = new MessageData {MessageId = messageId, Message =  messageContent, Language = language, Voice = voice };
    
            //Save messageData to database or some data store so that you can retrieve it later.
    
            return messageId;
        }
    

    Following is the MessageData class.

    public class MessageData
    {
        public string MessageId {get;set;}
        public string Voice {get;set;}
        public string Language {get;set;}
        public string Message {get;set;}       
    }
    

    Now I need to create a controller action to server request comint to twilio/twiml?p.

    Consider following controller action method in my TwilioController class.

    [Route("~/twiml/{p}")]
        [HttpPost]
        public IActionResult GetTwiml(string p)
        {
            //Get the messagedata from the datastore based on the messageId retrieved in request.
            var messageData = GetMessageData(p);
            //initializing Voice Response For creating XML
            var response = new VoiceResponse();
    
            // I have no idea why you have lot of comparison of Voice with string.empty and "0" 
            // so I am not changing it.
            // I am just replacing the Voice, Language and Message variables 
            //with the property values from messageDat object.
            if ((messageData.Voice != string.Empty && messageData.Voice != "0") && (messageData.Voice == "0"))
            {
                //Combining dynamic Message and selecting voice for reading message
                response.Say(messageData.Message, voice: messageData.Voice);
                var XML = new TwiMLResult(response.ToString());
                return XML;
            }
            if ((messageData.Voice != string.Empty && messageData.Voice != "0") && (messageData.Voice != string.Empty && messageData.Voice != "0"))
            {
                //Combining dynamic Message and selecting voice for reading message
                response.Say(messageData.Message, voice: messageData.Voice, language: messageData.Language);
                var XML = new TwiMLResult(response.ToString());
                return XML;
            }
            if ((messageData.Voice == string.Empty || messageData.Voice == "0") && (messageData.Voice == string.Empty || messageData.Voice == "0"))
            {
                //Combining dynamic Message and selecting voice for reading message
                response.Say(messageData.Message);
                var XML = new TwiMLResult(response.ToString());
                return XML;
            }
            return null;
        }
    
    private MessageData GetMessageData(string messageId)
    {
        MessageData messageData ;
        //retrieve message data based on the messageId and return;
    
        return messageData;
    }
    

    This way you can keep your URL shorter and still generate dynamic content for Voice Call.

    In above code, MessageData class is there for example. You might have complete different scenario based on your requirements.