.NET Wrapper for Text Messaging API

TxtSignalService.cs

- This is the low-level service class for TXT Signal's API. It sits atop the XmlService class and provides the mechanism for making TXT Signal requests and processing their responses.

< Previous | Home | Next >
#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using TxtSignal.CoreServices;
using System.Xml;
using System.Net;
using System.Configuration;
#endregion

namespace TxtSignal
{
    /// <summary>
    /// ******************************************************************
    /// *                                                                *
    /// * This code was written by your good friends at SplashTone.com.  *
    /// * This code is offered freely in the spirit of knowledge sharing.*
    /// * If you find good use out of it, check out our site and maybe   *
    /// * drop us a line (support@splashtone.com)!                       *
    /// *                                                                *
    /// * SplashTone.com is a site for booking bands online.             *
    /// * SplashTone.com is run by OpenBracketLLC.com.                   *
    /// *                                                                *
    /// ******************************************************************
    /// 
    /// Extends the basic XmlService class to include details for communicating with the 
    /// TXT Signal XML API. This makes it easier for callers to call into this service - they
    /// don't have to worry about the idiosyncracies (sp) of TXT Signal's XML format.
    /// </summary>
    public class TxtSignalService : XmlService
    {
        #region Members and Constructors
        private string _username;
        private string _password;
        private string _clientID;

        private TxtSignalActionType _actionTypeNative;
        private string _actionType;
        private bool _skipParsingParameters = false;

        private XmlNode _xRequest;
        private XmlNode _xAction;

        public TxtSignalService()
            : this(ConfigurationManager.AppSettings["Credentials.TxtSignal.Username"],
            ConfigurationManager.AppSettings["Credentials.TxtSignal.Password"],
            ConfigurationManager.AppSettings["Credentials.TxtSignal.ClientID"])
        {
        }

        public TxtSignalService(string username, string password, string clientID)
            : this(username, password, clientID, ConfigurationManager.AppSettings["ServiceUrls.TxtSignal"])
        {
        }

        public TxtSignalService(string username, string password, string clientID, string txtSignalAPIUrl)
            : base(txtSignalAPIUrl)
        {
            _username = username;
            _password = password;
            _clientID = clientID;
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets that type of API call we wish to make.
        /// </summary>
        public TxtSignalActionType ActionType
        {
            get { return _actionTypeNative; }
            set
            {
                _actionTypeNative = value;
                switch (value)
                {
                    case TxtSignalActionType.CreateContact: _actionType = "create_contact";
                        break;
                    case TxtSignalActionType.UpdateContact: _actionType = "update_contact";
                        break;
                    case TxtSignalActionType.DeleteContact: _actionType = "delete_contact";
                        break;
                    case TxtSignalActionType.CreateTeam: _actionType = "create_team";
                        break;
                    case TxtSignalActionType.QueryTeam: _actionType = "query_team";
                        break;
                    case TxtSignalActionType.DeleteTeam: _actionType = "delete_team";
                        break;
                    case TxtSignalActionType.SendMessage: _actionType = "send_message";
                        break;
                    case TxtSignalActionType.QueryCarriers: _actionType = "list_carriers";
                        break;
                    default: throw new InvalidProgramException("Unexpected action type: '" + value + "'");
                }
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Creates the document and the primary node that will contain the request to send.
        /// </summary>
        private void CreateDocument()
        {
            _requestXml = new XmlDocument();
            AddXmlDeclaration();
            _xRequest = _requestXml.CreateElement("txtsig_request") as XmlNode;
            XmlAttribute xVersion = _requestXml.CreateAttribute("version");

            _xRequest.Attributes.Append(xVersion);
            xVersion.InnerText = "1.0";
            _requestXml.AppendChild(_xRequest);
        }

        /// <summary>
        /// Adds the credentials to the xml document to authenticate us to the service.
        /// </summary>
        private void AddCredentials()
        {
            XmlNode xCreds = _requestXml.CreateElement("credentials") as XmlNode;
            XmlNode xUsername = _requestXml.CreateElement("api_username") as XmlNode;
            XmlNode xPassword = _requestXml.CreateElement("api_password") as XmlNode;
            XmlNode xClientID = _requestXml.CreateElement("client_id") as XmlNode;

            xUsername.InnerText = _username;
            xPassword.InnerText = _password;
            xClientID.InnerText = _clientID;

            xCreds.AppendChild(xUsername);
            xCreds.AppendChild(xPassword);
            xCreds.AppendChild(xClientID);

            _xRequest.AppendChild(xCreds);
        }

        /// <summary>
        /// Adds the action node that specifies the type of API call we are wanting to make.
        /// </summary>
        private void AddAction()
        {
            _xAction = _requestXml.CreateElement("action") as XmlNode;
            XmlAttribute xType = _requestXml.CreateAttribute("type");

            _xAction.Attributes.Append(xType);
            _xRequest.AppendChild(_xAction);

            xType.InnerText = _actionType;
        }

        /// <summary>
        /// Creates all the action-specific parameters to send data to the service.
        /// </summary>
        private void AddActionParameters()
        {
            foreach (string key in Parameters.Keys)
            {
                string val = Parameters[key];

                XmlNode xParam = _requestXml.CreateElement("param") as XmlNode;
                XmlAttribute xName = _requestXml.CreateAttribute("name");

                xName.InnerText = key;
                xParam.InnerXml = val;
                xParam.Attributes.Append(xName);
                _xAction.AppendChild(xParam);
            }
        }

        /// <summary>
        /// Parses out the response to see if an error occurred.
        /// </summary>
        /// <exception cref="XmlException">If there's something wrong with the format
        /// of the response.</exception>
        /// <exception cref="WebException">If the service is returning an error.</exception>
        private void ParseXmlResponse()
        {
            string exceptionInfo = string.Format(".{0}Request = {1}{2}Response = {3}",
                Environment.NewLine,
                _requestXml.OuterXml,
                Environment.NewLine,
                _responseXml.OuterXml);

            XmlNode xContent = _responseXml.SelectSingleNode("txtsig_response/content");
            if (xContent == null)
                throw new XmlException("TXT Signal response expected to have 'content' xml element" + exceptionInfo);

            XmlAttribute xType = xContent.Attributes["type"];
            if (xType == null)
                throw new XmlException("TXT Signal response expected to have 'content@type' xml element" + exceptionInfo);

            if (xType.InnerText.ToLower().Equals("error"))
            {
                XmlNode xDescription = xContent.SelectSingleNode("item/element[@name='error_text']");
                if (xDescription == null)
                    throw new XmlException("TXT Signal response expected to have 'error_text' xml element" + exceptionInfo);

                throw new WebException("TXT Signal Error: " + xDescription.InnerText + exceptionInfo);
            }

            XmlNodeList xSuccesses = xContent.SelectNodes("item/element[@name='success']");
            foreach (XmlNode xSuccess in xSuccesses)
            {
                string val = xSuccess.InnerText;
                bool success;
                if (!bool.TryParse(val, out success))
                    success = false;
                if (val.Trim().Equals("1"))
                    success = true;
                if (val.Trim().Equals("0"))
                    success = false;

                // TODO: Temporarily put this in because their API is returning a blank string for
                // calls to query_team.
                if (val.Trim().Equals(""))
                    success = true;

                if (!success)
                    throw new WebException("TXT Signal responded with success = 'false'" + exceptionInfo);
            }
        }

        /// <summary>
        /// Gets the value expected by the TXT Signal API for these cell phone carriers.
        /// If the list of carriers ever changes, this list needs to be updated.
        /// </summary>
        /// <param name="carrier">The carrier to translate to the API value.</param>
        /// <returns>The expected API value for these carriers.</returns>
        public string GetCellCarrier(TxtSignalCellCarrier carrier)
        {
            switch (carrier)
            {
                case TxtSignalCellCarrier.Alltel: return "alltel";
                case TxtSignalCellCarrier.ATT_Cingular: return "cingular";
                case TxtSignalCellCarrier.BellMobility_Canada: return "bellmobility_ca";
                case TxtSignalCellCarrier.BoostMobile: return "boostmobile";
                case TxtSignalCellCarrier.CellularOne: return "cellularone";
                case TxtSignalCellCarrier.CellularSouth: return "cellularsouth";
                case TxtSignalCellCarrier.CentennialWireless: return "centennial";
                case TxtSignalCellCarrier.CincinnatiBell: return "cincinnatibell";
                case TxtSignalCellCarrier.ClassicATT: return "att";
                case TxtSignalCellCarrier.Fido_Canada: return "fido_ca";
                case TxtSignalCellCarrier.MetroPCS: return "metropcs";
                case TxtSignalCellCarrier.Nextel: return "nextel";
                case TxtSignalCellCarrier.nTelos: return "ntelos";
                case TxtSignalCellCarrier.Rogers_Canada: return "rogers_ca";
                case TxtSignalCellCarrier.Sprint: return "sprint";
                case TxtSignalCellCarrier.SunCom: return "suncom";
                case TxtSignalCellCarrier.Telus_Canada: return "telus_ca";
                case TxtSignalCellCarrier.TMobile: return "tmobile";
                case TxtSignalCellCarrier.Unicel: return "unicel";
                case TxtSignalCellCarrier.USCellular: return "uscellular";
                case TxtSignalCellCarrier.Verizon: return "verizon";
                case TxtSignalCellCarrier.VirginMobile: return "virginmobile";
                case TxtSignalCellCarrier.VirginMobile_Canada: return "virginmobile_ca";
                default:
                    throw new InvalidProgramException("Unexpected TxtSignalCellCarrier: '" + carrier + "'");
            }
        }
        #endregion

        #region Overrides
        /// <summary>
        /// Submits a raw TXT Signal API call. This method requires that the caller formatted
        /// the XML appropriately and doesn't benefit from the main work of this class.
        /// </summary>
        /// <param name="xml">The xml to send directly to the TXT Signal API.</param>
        public virtual void Submit(string xml)
        {
            try
            {
                _skipParsingParameters = true;
                _requestXml = new XmlDocument();
                _requestXml.LoadXml(xml);
                Submit();
            }
            finally
            {
                _skipParsingParameters = false;
            }
        }

        /// <summary>
        /// Retrieves the full xml message that will be sent to the service.
        /// </summary>
        /// <returns>The xml request data.</returns>
        public string GetPreparedXmlMessage()
        {
            return GetParameterData();
        }

        /// <summary>
        /// Translates the xml request document into parameter data that can be posted to 
        /// the service.
        /// </summary>
        /// <returns>The xml request data.</returns>
        protected override string GetParameterData()
        {
            if (!_skipParsingParameters)
            {
                CreateDocument();
                AddCredentials();
                AddAction();
                AddActionParameters();
            }

            return base.GetParameterData();
        }

        /// <summary>
        /// Parses the response to see if an error was returned.
        /// </summary>
        protected override void OnSuccess()
        {
            base.OnSuccess();
            ParseXmlResponse();
        }
        #endregion
    }
}
< Previous | Home | Next >
Send any comments or questions here and we will do our best to respond! support@splashtone.com.
Bored? Check out our blog.