It's time to continue my series (I Want More Mobile (Web) Services and Flight Lookup Web Service, Package Lookup Web Service, and Movie Lookup Web Service) of useful Web Services for Windows Mobile with a service to look up definitions of words in a dictionary. I sometimes want to get the definition of a word that I've stumbled on, and since I'm often in a discussion or reading something when this happens, I want to do it wherever I am at that moment. Since a good dictionary is extensive (also regularly updated) and therefore not very suitable to install/store on a mobile device, a simple client to a web service would be a nice solution. As for the other Web Services in this series, you can get the code on CodePlex in a project called Windows Mobile Web Services.
As in previous posts, you find the UX on the right, and this is the code behind the right menu button (somewhat simplified)...
WebServices.Service ws = new WebServices.Service();
definitionTextBox.Text = ws.DictionaryLookup(wordTextBox.Text).Replace("\n", "\r\n");
...so when a word is entered in the text box, the following code on the server is run...
[WebMethod]
public string DictionaryLookup(string word)
{
const string host = "www.dict.org";
const int port = 2628;
const string database = "wn";
// Connect to dictionary (RFC 2229) server
TcpClient tc = new TcpClient(host, port);
StreamReader sr = new StreamReader(tc.GetStream());
DictServerStatus status = new DictServerStatus(sr.ReadLine());
if(status.Code != (int)DictServerStatusCodes.Banner)
throw new Exception(status.ToString());
// Send command (DEFINE)
string command = string.Format("DEFINE \"{0}\" \"{1}\"\r\n", database, word);
Encoding enc = System.Text.Encoding.ASCII;
tc.GetStream().Write(enc.GetBytes(command), 0, enc.GetBytes(command).Length);
// Get definition(s) for word
status = new DictServerStatus(sr.ReadLine());
if(status.Code != (int)DictServerStatusCodes.Definitions)
throw new Exception(status.ToString());
// Parse definitions
int definitionCount = Convert.ToInt32(status.Message.Substring(0,
status.Message.IndexOf(" ") + 1));
Hashtable definitions = new Hashtable(definitionCount);
for(int i = 0; i < definitionCount; i++)
{
status = new DictServerStatus(sr.ReadLine());
if(status.Code == (int)DictServerStatusCodes.Definition)
{
string responseText = string.Empty;
string s = sr.ReadLine();
while(s != ".")
{
responseText += s + "\r\n";
s = sr.ReadLine();
}
Match definitionLine = Regex.Match(status.Message, "^\\\"(?<word>[^\\\"]+)\\\"\\s+(?<database>[\\S]+)\\s+\\\"(?<dbname>[^\\\"]+)\\\"$");
definitions.Add(definitionLine.Groups["database"].ToString(),
responseText);
}
else
throw new Exception(status.ToString());
}
string definition = string.Empty;
status = new DictServerStatus(sr.ReadLine());
if(status.Code == (int)DictServerStatusCodes.Ok)
definition = definitions[database].ToString();
else
throw new Exception(status.ToString());
return definition;
}
...and in contrast to the previous posts in this series, this Web Service isn't using "scraping" to get the info from a Web page. Instead, the method used to access the dictionary is the standard Dictionary Server Protocol (RFC 2229). It's a text-based protocol (not HTTP, so plain sockets are used) that defines a range of dictionary functionality, and the above code is just using the ability to lookup (command DEFINE) a word in a dictionary.
The dictionary used is the WordNet database located at the DICT Development Group site.