Overview
In today’s IT world "Error Messages" or
"Information Messages" in any systems are inevitable. In application development
the messages are normally coupled into the system. So, whenever the customer asks
for changes in messages, developers get into the code and change the messages,
which is generally error prone. When trying to change the messages there are
possibilities that new bugs may get introduced.
With the power of .NET and XML, it is possible to de-couple the messages
outside the system and it is easy for maintenance. Whenever customer asks for
change in messages, they themselves can go and change the messages in the XML
repository or it is easy for any one who knows to operate the computers to
change the messages without shutting down the application.
Let us have a look how we can achieve it with .NET and XML.
Brief Architecture Description
All the messages of the system are stored in the form of XML with unique ids.
We can have a common method/function to retrieve the messages by passing their
respective ids. In this way we can de-couple the messages outside the system.
With powerful caching features available in .NET, we can cache the XML file and
set a dependency to it. So, for the first request the XML file is cached in to
the server’s memory and the subsequent requests will read from the cached object
and service the client requests. We can even use resource files, but changing
the resource files again needs to compile. Also, changing the XML doesn’t need
restart of the server or application since it has cache dependency. So, whenever
customer needs a change in messages he can just change the text in XML and the
subsequent requests by the client to that particular message will be served with
new messages.
Detailed Functional Description
1. XML Part
Let us have a look at the format of the
XML.
="1.0"="utf-8"
<Messages>
<Message>
<MsgId>100</MsgId>
<MsgValue>Please Enter Project Name <MSG></MsgValue>
</Message>
<Message>
<MsgId>101</MsgId>
<MsgValue>Please Enter Project Date</MsgValue>
</Message>
</Messages>
The XML file has root tag of "Messages". It has "Message" node, which
has "MsgId" and "MsgValue" as its child nodes. Basically, these nodes have
information about the Messages. Message Id (MsgId) is maintained as 3 digits, so
that the first digit represents Module Id and the other 2 digits represents the
Message. Number of digits can be changed depending upon the number of messages,
Also it may have any combination of characters to be uniquely identified. For
example, "MOD-001".
The "MsgValue
" node contains the actual message to be displayed. The message
should not have some XML reserved characters like "<" or ">" etc. If these
characters or to be included in the message try give the HTML Encode value for
it or add XML escape characters.
For example, Message like "Password can’t be blank" can be given as "Password
can\’t be blank".
Have a look at the Message Value of Id 100 in the XML. The message has "<MSG>". This is a pattern given in the message which can be
replaced and used for general messages. For Example. If you have messages that
change only a part of sentence can be put as same and while calling the
method/function, we can pass the value as parameter.
Consider these messages, "Please enter Project Name" and "Please enter
Project Description". We can have single message in the XML like "Please enter
Project <MSG>" and we can call it as GetMessage("100","Name")
to
display first message and GetMessage("100","Description")
for second message. On
seeing the code we will understand how it is possible.
2. C#
Part
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.Caching;
using System.Collections.Specialized;
using System.Xml;
using System.Xml.XPath;
using System.IO;
namespace CacheExample
{
public class ErrorMessage
{
public ErrorMessage()
{
}
static public string GetMessage(string intErrId,string strOptErrMsg)
{
StringDictionary objStrDictionary = new StringDictionary();
XmlDocument objXmlDocument = new XmlDocument();
XmlNodeList objNodeList;
string strXPath = string.Empty;
string strChildXPath = string.Empty;
string strFilePath = string.Empty;
string strErrDescription= string.Empty;
HttpContext objContext = HttpContext.Current;
try
{
strFilePath = objContext.Server.MapPath("ErrorMsg.xml");
if (objContext.Cache["strdictErrorMsg"]== null)
{
strXPath = "Messages/Message";
objXmlDocument.Load(strFilePath);
objNodeList = objXmlDocument.SelectNodes(strXPath);
foreach(XmlNode objNode in objNodeList)
{
objStrDictionary.Add(objNode.SelectSingleNode(
"MsgId").InnerText,objNode.SelectSingleNode("MsgValue").InnerText);
}
CacheDependency dependency = new CacheDependency(
objContext.Server.MapPath("ErrorMsg.xml"));
objContext.Cache.Insert("strdictErrorMsg", objStrDictionary,dependency);
}
else
{
objStrDictionary = (StringDictionary)objContext.Cache["strdictErrorMsg"];
}
if(objStrDictionary.ContainsKey(intErrId))
{
strErrDescription = objStrDictionary[intErrId];
if (strOptErrMsg != string.Empty)
{
strErrDescription = strErrDescription.Replace("<MSG>",strOptErrMsg);
}
return strErrDescription;
}
else
{
strErrDescription="";
return strErrDescription;
}
}
catch (Exception ex)
{
return "Invalid Error Id / Module Name";
}
}
}
}
In the C# code above, the high lighted code is important as it puts the
StringDictionary
object in to server’s cache, so that XML parsing needs not to
be done for each request.
"StringDictionary
" object is used as it is
more efficient than "HashTable
" as our collection contains only
strings. The "ErrorMsg.XML" is the XML file mentioned above. Keep it in the
application path so as for the above source code to work; else path should be
changed in the code. "GetMessage" method accepts 2 parameters. The first Parameter is the
MessageId and Second Parameter is the optional message to be shown with the
required message. This scenario is discussed above. For general call the second
parameter will be "string.Empty".
VB.NET users can convert the above code to VB.NET.
3. ASPX Part
Even JavaScript Messages in ASPX pages can be moved to this XML file. You can
access the messages as shown in script below.
<script language="javascript">
function test()
{
var xyz = '<%=ErrorMessage.GetMessage ("101","")%>';
alert(xyz);
}
</script>
Ensure the relevant namespaces are imported in
the ASPX file.
For Example. Here my Namespace is
<%@ Import Namespace="CacheExample"%>
Conclusion
You can enhance the above code for reusability. Certain customizations can be
made
like passing more than one custom message to the function and appropriately
servicing the client etc. Hope this article helps you. Kindly send your
clarifications and queries.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.