Friday, October 29, 2010

Sending SMS With ASP.NET MVC

Introduction

In this post, I will be sharing the experience I had (integrating SMS) during the development of Delight. With the rising usage of mobile devices, statistics have shown that SMS is the most effective way to communicate, especially for all type of businesses. Honestly, SMS integration to a website if you ask me I would say is easy if you want to stick to just one provider no matter what the future brings. However, this was not the case for Delight, we needed solution that won't require us to rewrite the entire procedure in case we find a better offer by other SMS gateway providers in the future.

The SMS gateway provider I would be using for this post is SMSLive (http://smslive247.com). Before you can use their gateway to send SMS, you must sign-up an account with them and create a sub-account that will be used for sending SMS from your application, the account registration is free.

In other to have a better understand of this tutorial, you need the API documentation (optional for this tutorial) which you can download from their website.

Final view of the application.



















Programming the SMS functionality

Enter the following settings in your web.config AppSettings section.

<add key="SmsUrl" value="http://www.smslive247.com/http/index.aspx"/>
<add key="SmsAccount" value="YOUR-SMSLIVE-EMAIL-ADDRESS"/>
<add key="SubAccount" value="YOUR-SMSLIVE-SUBACCOUNT"/>
<add key="SubAccountPass" value="YOUR-SMSLIVE-SUBACCOUNT-PASSWORD"/>

Now we need a way to access those information in the web.config AppSetings section. Create a new class and name it “ConfigService” and enter the codes below.


public class ConfigService
    {
       public ConfigService(){}

        /// <summary>
        /// Get the SMS gateway url
        /// </summary>
        public string SmsUrl
        {
            get { return getAppSetting(typeof(string), "SmsUrl").ToString(); }
        }

        /// <summary>
        /// Get teh gateway account to use in sending sms message
        /// </summary>
        public string SmsAccount
        {
            get { return getAppSetting(typeof(string), "SmsAccount").ToString(); }
        }

        /// <summary>
        /// Get the sub account to use for the sending of sms
        /// </summary>
        public string SubAccount
        {
            get { return getAppSetting(typeof(string), "SubAccount").ToString(); }
        }

        /// <summary>
        /// Get the sub account password for the sms gateway
        /// </summary>
        public string SubAccountPwd
        {
            get { return getAppSetting(typeof(string), "SubAccountPass").ToString(); }
        }

        private static object getAppSetting(Type expectedType, string key)
        {
            string value = ConfigurationManager.AppSettings[key]; //.Get(key);

            if (value == null)
            {
                throw new Exception(
                    string.Format("The config file does not have the key '{0}' defined in the AppSetting section.", key));
            }

            if (expectedType.Equals(typeof (int)))
            {
                return int.Parse(value);
            }

            if (expectedType.Equals(typeof (string)))
            {
                return value;
            }
            else
                throw new Exception("Type not supported.");
        }
    }

Let’s create a model for our SMS so it will be easier for us to validate it if we want to.

public class SMS
    {
        public string Numbers { get; set; }

        public string SenderId { get; set; }

        public string Message { get; set; }
    }

Remember we are not planning to stick with the current SMS provider for life, at least not when we have a better offer from another provider. This will make our SMS integration a bit lengthy but will pay in the long run.

Create a new class, name "SmsService" and add the following codes.

public class SmsService
    {
        private ConfigService _config;
        private Cache _cache;

        private string sessionId_cahe_key = "SmsSessionId_" + "GetSessionId";

        public SmsService()
        {
            _config = new ConfigService();
            _cache = HttpContext.Current.Cache;
        }

        //Default method for making request to the SMS gateway. This method is not likely to be changed no matter what 
        //SMS gateway provider you want to use in the future.
        private string makeHttpRequest(string url)
        {
            //Initialize the web request
            var webReq = (HttpWebRequest)WebRequest.Create(url);
            webReq.ContentLength = 0;

            webReq.Method = "POST";//We're making a post request. This is the recommended method by the gateway.
            webReq.Timeout = 600000;//Set the timeout for the request

            var webResp = (HttpWebResponse)webReq.GetResponse();

            //Read the response and output it.
            Stream answer = webResp.GetResponseStream();
            StreamReader _answer = new StreamReader(answer);

            string result = _answer.ReadToEnd();

            return result;
        }

        //Instead of providing the subaccount and password in information every request to the SMS gateway, 
        //we use this method to get a session id from the gateway and pass to the service. 
        //This approach is more secure.
        public string Login()
        {
            string result = null;
            //Get the gateway url from the web.config AppSettings section
            string smsUrl = _config.SmsUrl;

            //Form the command for login to send to the gatway. You can download the api documentation 
            //from http://smslive247.com
            string smsCmd = "?cmd=login&owneremail=" + _config.SmsAccount + "&subacct=" + _config.SubAccount +
                            "&subacctpwd=" + _config.SubAccountPwd;

            try
            {
                return result = makeHttpRequest(smsUrl + smsCmd);
            }
            catch (Exception err)
            {
                throw err;
            }
        }

        public string GetSessionId()
        {
            string result = null;//hold the returned message from the request
            bool success = false;//indicate if request is seccessful or not

            //First look for the session id in the cache items, if it does not exist, then trying making a request to the SMS gateway
            //for session id, otherwise get it from the cache
            if (_cache[sessionId_cahe_key] != null)
                result = (string)_cache.Get(sessionId_cahe_key);
            else
            {
                string response = Login();//Call the login method to get the session id from the sms gateway

                string errMsg = null;
                //process and return the response data from the login call in a friendly format
                result = GetResponseMessage(response, out success, out errMsg);

                if (success)//add the session id to the cache if the login request was successful
                {
                    _cache.Add(sessionId_cahe_key, result, null, DateTime.Now.AddHours(2), Cache.NoSlidingExpiration,
                               CacheItemPriority.Normal, null);
                }
            }
            return result;//return the session id
        }

        //Process the response from the sms gateway. By default, the gateway's response is in format below
        //OK: [RESPONSE-Message] -or- ERR: [ERROR NUMBER]: [ERROR DESCRIPTION]
        public string GetResponseMessage(string response, out bool success, out string errMsg)
        {
            //if the response contains 'OK', then the request was successful
            bool isSuccess = response.Substring(0, response.IndexOf(":") + 1).Contains("OK");
            //This holds the code returned from the request. Anything other than 0 means error
            string code = null;
            //This variable holds the description of the error message
            string errDesc = null;

            //get the code for the request
            if (isSuccess)
            {
                code = response.Substring(response.IndexOf(":") + 2);
            }
            else
            {
                code = response.Substring(response.IndexOf(":") + 2, response.LastIndexOf(":") - 1);
                errDesc = response.Substring(response.LastIndexOf(":") + 2);
            }

            success = isSuccess;
            errMsg = errDesc;
            return code;
        }

        public string Send(SMS sms)
        {
            string sessionId = GetSessionId(); //Get the session id
            string smsUrl = _config.SmsUrl; //Get the sms gatway url from the config file

            //Form the command for sending message. You can download the API documentation for full list of commands
            //from http://smslive247.com
            string smsCmd = String.Format("?cmd=sendmsg&sessionid={0}&message={1}&sender={2}" +
                                          "&sendto={3}&msgtype=0", sessionId, sms.Message, sms.SenderId, sms.Numbers);

            bool isSuccess = false;
            string errMsg = null;
            //Send sms message
            string response = makeHttpRequest(smsUrl + smsCmd);

            //Process the response from the gateway
            string code = GetResponseMessage(response, out isSuccess, out errMsg);

            //401 error code indicate invalid Session ID. If the session id is not valid, then delete it from cache and make a 
            //request to get a new session id from the sms gateway
            if (code == "401")
            {
                _cache.Remove(sessionId_cahe_key);//delete the session id from the cache

                sessionId = GetSessionId(); //Get the session id
                smsCmd = String.Format("?cmd=sendmsg&sessionid={0}&message={1}&sender={2}" +
                                          "&sendto={3}&msgtype=0", sessionId, sms.Message, sms.SenderId, sms.Numbers);

                return makeHttpRequest(smsUrl + smsCmd);//resend the sms to the gateway
            }

            return response;
        }
    }

I would be using ASP.NET MVC in the following example, the process to implement this in whatever C# application you want to use it in is the same. If you are working on ASP.NET web-form for example, all you need to do is just substitute the Action method to the control’s method you want to trigger the sending of SMS from.

[HttpPost, ActionName("send-sms")]
        public ActionResult SendSMS(SMS sms)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    bool isSuccess = false;
                    string errMsg = null;
                    string response = _smsService.Send(sms); //Send sms

                    string code = _smsService.GetResponseMessage(response, out isSuccess, out errMsg);

                    if (!isSuccess)
                    {
                        ModelState.AddModelError("", errMsg);
                    }
                    else
                    {
                        ViewData["SuccessMsg"] = "Message was successfully sent.";
                    }
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                }
            }

            return View(sms);
        }

The HTML

<%=Html.ValidationSummary() %>
<%if (ViewData["SuccessMsg"]!=null){%>
<div class="success"><%=ViewData["SuccessMsg"] %></div>
<%} %>

<form action="<%=Url.Action("send-sms","home") %>" method="post">
<label for="Numbers">Send To</label><br />
<%=Html.TextBox("Numbers") %><br /><br />

<label for="Message">Message</label><br />
<%=Html.TextArea("Message","",new{rows="4",cols="35"}) %><br /><br />

<label for="SenderId">SenderId</label><br />
<%=Html.TextBox("SenderId") %><br /><br />

<input type="submit" value="Send Now" />
</form>

That’s it, we now have a functional website with SMS functionality. You can download the full source code here.

Conclusion

I hope you find this useful. Depending on the kind of Application you’re building, there’s so much more you can do with SMS to make things easier for your users.



203 comments:

«Oldest   ‹Older   201 – 203 of 203   Newer›   Newest»
Anonymous said...

Как раз вовремя для всех любителей кулинарии! Хочу поделиться отличным ресурсом, где можно найти потрясающие фоны для кулинарных тем. Загляните на сайт https://ybis.ru/oboi/kulinariya-fon и выберите идеальный фон для своих кулинарных шедевров. Эти фоны подойдут как для блогеров, так и для профессионалов в области кулинарии. Уверен, они придадут вашим фото и рецептам особый шарм и стиль!

Anonymous said...

Шустро в деле? Тогда смотри, у меня для тебя тема - День консервирования! Это же просто супер способ сохранить твою урожайку на зиму! ���� А еще, я нашел крутой сайт, где есть куча советов и рецептов по консервированию. Там, кстати, можно узнать, как правильно засолить огурчики, насколько долго варенье сгущается и даже как делать кисель. Короче, если тебя интересует эта тема, советую заглянуть сюда: https://cvam.ru/konservirovaniya. Там много практической инфы для разных уровней подготовки, так что ты точно найдешь что-то новенькое! ����#консервируюЛайками

Anonymous said...

شركة مكافحة حشرات بالخبر xFx5CceP6C

«Oldest ‹Older   201 – 203 of 203   Newer› Newest»

Post a Comment