Thursday, August 5, 2010

Universal USSD Menu Builder Using .NET

USSD or Unstructured Supplementary Service Data is a capability of all GSM phones. It is generally associated with real-time or instant messaging type phone services. Response times for interactive USSD-based services are generally quicker than SMS. Samples USSD service in Indonesia are the bill status services accessed by dialing *123#(XL) or *388#(IM3).
Some of the USSD applications that we use regularly are:

  • Changing various VAS services.
  • Recharging using prepaid vouchers.
  • Alerts About special offers and services.

The Menu Builder makes it simple to create USSD applications. It is fast, flexible and easy to use and solves many of the inherent problems of creating USSD applications like rapidly USSD development, prototyping and intelligent menu generation. The Menu Builder supports hierarchical menus and can automatically enable the application with forward and back navigation options.



using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;

using System.Configuration;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Security;

using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;

using Extend.Lib.Common;
using Extend.Lib.Common.Umb;
using Umb.Lib.Data.Business;

namespace Umb.Handler.ContentEngine
{

public class UmbHttpInterfaceHandler : IHttpHandler
{
public enum UmbMenuState
{

Root = 91,
Branch = 92,
}

public struct StructUmbMenus
{

public int UmbMenuPK;
public string UmbHeaderText;
public string UmbMenuText;
public int? ParentUmbMenuFK;
public int UmbMenuLevel;
public short UmbMenuIndex;
public short? WebSvcMethodFK;
public string Content;
public bool IsSmsMT;
public string LineAge;
public string UmbMenuTypeID;
}

public struct StructUserInput
{
public string I1;
public string I2;
public string I3;
public string I4;
public string I5;
public string I6;
public string I7;
public string I8;
}

public void ProcessRequest(HttpContext context)
{

string _DefaultItemUrl = ConfigurationManager.AppSettings["DefaultItemUrl"].Trim();
string _SiteTitle = ConfigurationManager.AppSettings["SiteTitle"].Trim();

List<UmbXml.ItemMenu> items = null;
string qNextState = string.Empty;
int iqNextState = -1;
int iqUserInput = -1;
int iqParentMenuPK = -1;
int childMenuPK = -1;

StructUserInput qUIn = new StructUserInput();

string currentRawUrl = HttpContext.Current.Request.RawUrl;

string umbXmlResponse = string.Empty;

string querystring = string.Empty;

int iqs = currentRawUrl.IndexOf('?');
if (iqs >= 0)
{

querystring = (iqs < currentRawUrl.Length - 1) ? currentRawUrl.Substring(iqs + 1) : String.Empty;
}

NameValueCollection rxQueryStrings = System.Web.HttpUtility.ParseQueryString(querystring);

string qParentMenuPK = string.Empty;
int? iqParentMenuPKNullable = null;

string qMsgID = string.Empty;
string qDeliverMode = "0";
string qUserInput = string.Empty;
string qDateTime = string.Empty;
string qImsi = string.Empty;
string qMsisdn = string.Empty;
string qServiceCode = string.Empty;
string itemUrl = string.Empty;
string umbMenuTypeID = string.Empty;
int umbMenuLevel = 1;
string umbHeaderText = string.Empty;

qUIn.I1 = string.Empty;
qUIn.I2 = string.Empty;
qUIn.I3 = string.Empty;
qUIn.I4 = string.Empty;
qUIn.I5 = string.Empty;
qUIn.I6 = string.Empty;
qUIn.I7 = string.Empty;
qUIn.I8 = string.Empty;

if (rxQueryStrings["MSISDN"] != null)
{

qMsisdn = rxQueryStrings["MSISDN"].ToString();
if (string.Compare(StringHelper.SubstringSafe(qMsisdn, 1, 2), "62") == 0)
{

qMsisdn = string.Format("0{0}", StringHelper.SubstringSafe(qMsisdn, 3, qMsisdn.Length - 2));
}
}
if (rxQueryStrings["SERVICECODE"] != null) qServiceCode = rxQueryStrings["SERVICECODE"];
if (rxQueryStrings["USERINPUT"] != null) qUserInput = rxQueryStrings["USERINPUT"];
if (rxQueryStrings["DATETIME"] != null) qDateTime = rxQueryStrings["DATETIME"];
DateTime? dateTime = MiscHelper.ConvertStringToDateTimeWithoutSeparator(qDateTime);
if (rxQueryStrings["DELIVERMODE"] != null) qDeliverMode = rxQueryStrings["DELIVERMODE"];
if (rxQueryStrings["IMSI"] != null) qImsi = rxQueryStrings["IMSI"];
if (rxQueryStrings["MSGID"] != null) qMsgID = rxQueryStrings["MSGID"];

if (rxQueryStrings["NEXTSTATE"] != null) qNextState = rxQueryStrings["NEXTSTATE"];

if (rxQueryStrings["PARENTMENUPK"] != null) qParentMenuPK = rxQueryStrings["PARENTMENUPK"];

if (rxQueryStrings["UIN1"] != null) qUIn.I1 = rxQueryStrings["UIN1"];
if (rxQueryStrings["UIN2"] != null) qUIn.I2 = rxQueryStrings["UIN2"];
if (rxQueryStrings["UIN3"] != null) qUIn.I3 = rxQueryStrings["UIN3"];
if (rxQueryStrings["UIN4"] != null) qUIn.I4 = rxQueryStrings["UIN4"];
if (rxQueryStrings["UIN5"] != null) qUIn.I5 = rxQueryStrings["UIN5"];
if (rxQueryStrings["UIN6"] != null) qUIn.I6 = rxQueryStrings["UIN6"];
if (rxQueryStrings["UIN7"] != null) qUIn.I7 = rxQueryStrings["UIN7"];
if (rxQueryStrings["UIN8"] != null) qUIn.I8 = rxQueryStrings["UIN8"];

if (!string.IsNullOrEmpty(qNextState)) { Int32.TryParse(qNextState, out iqNextState); }

if (!string.IsNullOrEmpty(qParentMenuPK)) { Int32.TryParse(qParentMenuPK, out iqParentMenuPK); }
else { iqParentMenuPK = -1; }

if (iqParentMenuPK > 0) iqParentMenuPKNullable = iqParentMenuPK;

UmbMenus umbMenus = new UmbMenus();

switch (iqNextState)
{
case (int)UmbMenuState.Root:
items = MenuRoot(_DefaultItemUrl, ref qUIn);
umbXmlResponse = UmbXml.MenuPageDisplay(items, "NONE", "0", _SiteTitle);
break;
case (int)UmbMenuState.Branch:
umbMenus.GetChildUmbMenuTypeIDByParent(iqParentMenuPKNullable, ref umbMenuTypeID);
switch (umbMenuTypeID.ToUpper())
{

case "MULTIPLECHOICE":
iqUserInput = (qUserInput != null) && (qUserInput.Trim().Length != 0)
? Int32.Parse(qUserInput) : 0;
if ((iqUserInput) > 0)
umbMenus.GetChildUmbMenuPKByParentAndIndex(iqParentMenuPKNullable, iqUserInput, ref childMenuPK);
break;
case "TEXTANSWER":
umbMenus.GetChildUmbMenuPKByParent(iqParentMenuPKNullable, ref childMenuPK);
break;
case "CLOSING":
umbMenus.GetChildUmbMenuPKByParent(iqParentMenuPKNullable, ref childMenuPK);
break;
}

umbMenus.GetChildUmbMenuLevelByParent(iqParentMenuPKNullable, ref umbMenuLevel);
SetUserInput(qUserInput, umbMenuLevel, ref qUIn);
bool isHaveChilds = false;
umbMenus.IsHaveChilds(childMenuPK, ref isHaveChilds);
if (isHaveChilds)
{

umbMenus.GetChildUmbMenuTypeIDByParent(childMenuPK, ref umbMenuTypeID);
umbMenus.GetChildUmbHeaderTextByParent(childMenuPK, ref umbHeaderText);
switch (umbMenuTypeID.ToUpper())
{
case "MULTIPLECHOICE":
items = MenuMultipleChoice(_DefaultItemUrl, qUIn, childMenuPK);
umbXmlResponse = UmbXml.MenuPageDisplay(items, "NONE", "0", umbHeaderText);
break;
case "TEXTANSWER":
MenuTextAnswer(_DefaultItemUrl, qUIn, childMenuPK, ref itemUrl, ref umbHeaderText);
umbXmlResponse = UmbXml.InputPageDisplay(umbHeaderText, itemUrl);
break;
case "CLOSING":
umbMenus.GetChildUmbHeaderTextByParent(childMenuPK, ref umbHeaderText);
umbMenus.Process(childMenuPK, qMsisdn, qUIn.I1, qUIn.I2, qUIn.I3, qUIn.I4, qUIn.I5,
qUIn.I6, qUIn.I7, qUIn.I8);
umbXmlResponse = UmbXml.ResultPageDisplay(umbHeaderText);

break;
}

}

break;

default:
itemUrl = string.Format(
@"{0}?&NEXTSTATE={1}&PARENTMENUPK={2}", _DefaultItemUrl,
((int)UmbMenuState.Root), string.Empty);
umbXmlResponse = UmbXml.InputPageDisplay("Masukkan kode server :", itemUrl);
break;
}

context.Response.Write(umbXmlResponse);
}


private void SetUserInput(string qUserInput, int? level, ref StructUserInput qUIn)
{

switch (level)
{
case 1:
qUIn.I1 = qUserInput;
break;
case 2:
qUIn.I2 = qUserInput;
break;
case 3:
qUIn.I3 = qUserInput;
break;
case 4:
qUIn.I4 = qUserInput;
break;
case 5:
qUIn.I5 = qUserInput;
break;
case 6:
qUIn.I6 = qUserInput;
break;
case 7:
qUIn.I7 = qUserInput;
break;
case 8:
qUIn.I8 = qUserInput;
break;
}

}



private List<UmbXml.ItemMenu> MenuRoot(string defaultItemUrl, ref StructUserInput qSUIn)
{

string itemUrl = string.Empty;
string umbMenuTypeID = string.Empty;
UmbMenuState umbMenuState = UmbMenuState.Branch;

DataTable dt = null;
List<UmbXml.ItemMenu> items = null;
UmbXml.ItemMenu itemMenu;
items = new List<UmbXml.ItemMenu>();

UmbMenus umbMenus = new UmbMenus();
dt = umbMenus.GetAllRoot();

StructUmbMenus s = new StructUmbMenus();

if (dt != null)
{

foreach (DataRow row in dt.Rows)
{

GetRow(row, true, ref s);

umbMenus.GetChildUmbMenuTypeIDByParent(s.UmbMenuPK, ref umbMenuTypeID);

switch (umbMenuTypeID.Trim().ToUpper())
{

case "MULTIPLECHOICE":
umbMenuState = UmbMenuState.Branch;
break;
case "TEXTANSWER":
umbMenuState = UmbMenuState.Branch;
break;
case "CLOSING":
umbMenuState = UmbMenuState.Branch;
break;
}


itemUrl = string.Format(
@"{0}?UIN1={1}&UIN2={2}&UIN3={3}&UIN4={4}&UIN5={5}&UIN6={6}&UIN7={7}&UIN8={8}&NEXTSTATE={9}&PARENTMENUPK={10}",
defaultItemUrl, qSUIn.I1, qSUIn.I2, qSUIn.I3, qSUIn.I4, qSUIn.I5,
qSUIn.I6, qSUIn.I7, qSUIn.I8, ((int)umbMenuState), string.Empty);

itemMenu = new UmbXml.ItemMenu(s.UmbMenuIndex.ToString(), "NONE", "0", itemUrl, "0", s.UmbMenuText);
items.Add(itemMenu);
}

}

return items;
}


private List<UmbXml.ItemMenu> MenuMultipleChoice(string defaultItemUrl, StructUserInput qSUIn, int? umbMenuPK)
{

string itemUrl = string.Empty;
string umbMenuTypeID = string.Empty;
UmbMenuState umbMenuState = UmbMenuState.Branch;

DataTable dt = null;
List<UmbXml.ItemMenu> items = null;
UmbXml.ItemMenu itemMenu;
items = new List<UmbXml.ItemMenu>();

UmbMenus umbMenus = new UmbMenus();
dt = umbMenus.ListMyChildsOnelevel(umbMenuPK);

StructUmbMenus s = new StructUmbMenus();

string strUmbMenuPK = string.Empty;
if (umbMenuPK != null) strUmbMenuPK = umbMenuPK.ToString().Trim();
else strUmbMenuPK = null;

if (dt != null)
{

foreach (DataRow row in dt.Rows)
{
GetRow(row, true, ref s);

umbMenus.GetChildUmbMenuTypeIDByParent(s.UmbMenuPK, ref umbMenuTypeID);

switch (umbMenuTypeID.Trim().ToUpper())
{

case "MULTIPLECHOICE":
umbMenuState = UmbMenuState.Branch;
break;
case "TEXTANSWER":
umbMenuState = UmbMenuState.Branch;
break;
case "CLOSING":
umbMenuState = UmbMenuState.Branch;
break;
}


itemUrl = string.Format(
@"{0}?UIN1={1}&UIN2={2}&UIN3={3}&UIN4={4}&UIN5={5}&UIN6={6}&UIN7={7}&UIN8={8}&NEXTSTATE={9}&PARENTMENUPK={10}",
defaultItemUrl, qSUIn.I1, qSUIn.I2, qSUIn.I3, qSUIn.I4, qSUIn.I5,
qSUIn.I6, qSUIn.I7, qSUIn.I8, ((int)umbMenuState), strUmbMenuPK);

itemMenu = new UmbXml.ItemMenu(s.UmbMenuIndex.ToString(), "NONE", "0", itemUrl, "0", s.UmbMenuText);
items.Add(itemMenu);
}

}

return items;
}


private string MenuTextAnswer(string defaultItemUrl, StructUserInput qSUIn, int? umbMenuPK,
ref string itemUrl, ref string umbHeaderText)
{

itemUrl = string.Empty;
umbHeaderText = string.Empty;
UmbMenus umbMenus = new UmbMenus();
umbMenus.GetChildUmbHeaderTextByParent(umbMenuPK, ref umbHeaderText);

itemUrl = string.Format(
@"{0}?UIN1={1}&UIN2={2}&UIN3={3}&UIN4={4}&UIN5={5}&UIN6={6}&UIN7={7}&UIN8={8}&NEXTSTATE={9}&PARENTMENUPK={10}",
defaultItemUrl, qSUIn.I1, qSUIn.I2, qSUIn.I3, qSUIn.I4, qSUIn.I5,
qSUIn.I6, qSUIn.I7, qSUIn.I8, ((int)UmbMenuState.Branch), umbMenuPK);

return itemUrl;
}


public void GetRow(DataRow row, bool isconvertnull, ref StructUmbMenus s)
{

s.UmbMenuPK = Convert.ToInt32(row["UmbMenuPK"]);
if (isconvertnull) s.UmbHeaderText = row.IsNull("UmbHeaderText") ? null : Convert.ToString(row["UmbHeaderText"]);
else s.UmbHeaderText = row.IsNull("UmbHeaderText") ? string.Empty : Convert.ToString(row["UmbHeaderText"]);
s.UmbMenuText = Convert.ToString(row["UmbMenuText"]);
if (isconvertnull) s.ParentUmbMenuFK = row.IsNull("ParentUmbMenuFK") ? null : (int?)Convert.ToInt32(row["ParentUmbMenuFK"]);
else s.ParentUmbMenuFK = row.IsNull("ParentUmbMenuFK") ? 0 : (int?)Convert.ToInt32(row["ParentUmbMenuFK"]);
s.UmbMenuLevel = Convert.ToInt32(row["UmbMenuLevel"]);
s.UmbMenuIndex = Convert.ToInt16(row["UmbMenuIndex"]);
if (isconvertnull) s.WebSvcMethodFK = row.IsNull("WebSvcMethodFK") ? null : (short?)Convert.ToInt16(row["WebSvcMethodFK"]);
else s.WebSvcMethodFK = row.IsNull("WebSvcMethodFK") ? 0 : (short?)Convert.ToInt16(row["WebSvcMethodFK"]);
if (isconvertnull) s.Content = row.IsNull("Content") ? null : Convert.ToString(row["Content"]);
else s.Content = row.IsNull("Content") ? string.Empty : Convert.ToString(row["Content"]);
s.IsSmsMT = Convert.ToBoolean(row["IsSmsMT"]);
if (isconvertnull) s.LineAge = row.IsNull("LineAge") ? null : Convert.ToString(row["LineAge"]);
else s.LineAge = row.IsNull("LineAge") ? string.Empty : Convert.ToString(row["LineAge"]);
}

private bool RedirectIsValid(string redir, Uri currentUri)
{
String val1 = redir.ToLower();
String url = currentUri.AbsoluteUri.ToLower();
String host = currentUri.Host.ToLower();

if (val1 == url) { return false; }

if (val1 == ("http://" + host)) { return false; }
if (val1 == ("http://" + host + "/")) { return false; }

if (val1 == host) { return false; }
if (val1 == (host + "/")) { return false; }

return true;
}

public bool IsReusable
{

get { return false; }
}

}

}

4 comments:

zor said...

Hi Salcad,
thank you for sharing your knowledge and experience. I realy liked your USSD menu builder .NET artical but I could not run it because of missing libraries:
Extend.Lib.Common;
Umb.Lib.Data.Business;

Could you share those libraries as well.

Thank you.Much appriciated.

Cheers
Zor(my email:zorlju@gmail.com)

CCknights said...

Hello,

I found this quite useful as I am exploring different methods of building USSD Apps. However, I cannot seem to compile this because of missing:

Extend.Lib.Common;
Umb.Lib.Data.Business;

Can anyone help here?

Regards,

Paul (crystalik2000@gmail.com)

CCknights said...

Hello,

I found this quite useful as I am exploring different methods of building USSD Apps. However, I cannot seem to compile this because of missing:

Extend.Lib.Common;
Umb.Lib.Data.Business;

Can anyone help here?

Regards,

Paul (crystalik2000@gmail.com)

September 13, 2013 at 8:21 PM Delete

simon said...

Hello thanks for this code.
Please assist me with this dll
Extend.Lib.Common;
Umb.Lib.Data.Business;

sinmwa3@gmail.com

Indonesia To Blog -Top Site
SEO - search engine submission and optimisation