A Completely Dynamic View Model

by Administrator 29. December 2011 11:43

Recently, I was working on a project where there was a requirement to print certain documents.  These documents were stored, in pieces, in the database and then loaded and assembled at runtime.  This allowed parts of the documents to be reused as needed.

The Xaml for these documents contained bindings to data that originated from the database.  The usual drill would be to statically define all the required properties on the view model and then write code to populate them from the database.  There's nothing wrong with this approach, but the project was in a mode where new documents were being generated quickly and they required new properties to be defined on the view model making the view model code a hot spot.

The data required in the bindings was largely stored as name/value pairs in the database.  Wouldn't it be much nice if new values added to the database just showed up at runtime without having to create new properties and the code to populate them?

Using dynamic objects would be a great way to go, if you could bind to them.  Unfortunately, they don't support reflection which is required for binding.  A second problem is that adding properties to a dynamic object requires a syntax like this:

Connect to XMPP
  1. dynamic vm = new object();
  2.             vm.PropertyName = 5;

Which, of course, requires you to know all property names to be added, ahead of time.  Since I'd like to be able to add properties that I find in the database, this is unsuitable.

I did some research and found this blog post by Lester Lobo.  The solution accompanying the post contained this class.

Connect to XMPP
  1. using System.Collections.Generic;
  2. using System.Collections.ObjectModel;
  3. using System.ComponentModel;
  4. using System.Dynamic;
  5. using System.Windows.Data;
  6. using System;
  7.  
  8. namespace DynamicVM
  9. {
  10.     public class DynamicObjectClass : DynamicObject, INotifyPropertyChanged
  11.     {
  12.         #region DynamicObject overrides
  13.  
  14.         public DynamicObjectClass()
  15.         {
  16.         }
  17.  
  18.         public override bool TryGetMember(GetMemberBinder binder, out object result)
  19.         {
  20.             return members.TryGetValue(binder.Name, out result);
  21.         }
  22.  
  23.         public override bool TrySetMember(SetMemberBinder binder, object value)
  24.         {
  25.             members[binder.Name] = value;
  26.             OnPropertyChanged(binder.Name);
  27.             return true;
  28.         }
  29.  
  30.         public override IEnumerable<string> GetDynamicMemberNames()
  31.         {
  32.             return members.Keys;
  33.         }
  34.  
  35.         public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
  36.         {
  37.             int index = (int)indexes[0];
  38.             try
  39.             {
  40.                 result = itemsCollection[index];
  41.             }
  42.             catch (ArgumentOutOfRangeException)
  43.             {
  44.                 result = null;
  45.                 return false;
  46.             }
  47.             return true;
  48.         }
  49.  
  50.         public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
  51.         {
  52.             int index = (int)indexes[0];
  53.             itemsCollection[index] = value;
  54.             OnPropertyChanged(System.Windows.Data.Binding.IndexerName);
  55.             return true;
  56.         }
  57.  
  58.         public override bool TryDeleteMember(DeleteMemberBinder binder)
  59.         {
  60.             if (members.ContainsKey(binder.Name))
  61.             {
  62.                 members.Remove(binder.Name);
  63.                 return true;
  64.             }
  65.             return false;
  66.         }
  67.  
  68.         public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes)
  69.         {
  70.             int index = (int)indexes[0];
  71.             itemsCollection.RemoveAt(index);
  72.             return true;
  73.         }
  74.  
  75.         #endregion DynamicObject overrides
  76.  
  77.         public void AddProperty(string propertyName, object value)
  78.         {
  79.             members[propertyName] = value;
  80.         }
  81.  
  82.         #region INotifyPropertyChanged
  83.  
  84.         public event PropertyChangedEventHandler PropertyChanged;
  85.  
  86.         private void OnPropertyChanged(string propertyName)
  87.         {
  88.             if (PropertyChanged != null)
  89.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  90.         }
  91.  
  92.         #endregion INotifyPropertyChanged
  93.  
  94.         #region Public methods
  95.  
  96.         public object AddItem(object item)
  97.         {
  98.             itemsCollection.Add(item);
  99.             OnPropertyChanged(Binding.IndexerName);
  100.             return null;
  101.         }
  102.  
  103.         #endregion Public methods
  104.  
  105.         #region Private data
  106.  
  107.         Dictionary<string, object> members = new Dictionary<string, object>();
  108.         ObservableCollection<object> itemsCollection = new ObservableCollection<object>();
  109.  
  110.         #endregion Private data
  111.     }
  112.  
  113. }

This class was almost just what I needed.  It solved the problem of not being able to bind to a dynamic, but I still needed a way to add properties on the fly.  For this, I added the AddProperty() method, which you'll see in the above listing.

Using the class is easy.  Below is an example.

Connect to XMPP
  1. AValue = new DynamicObjectClass();
  2.             AValue.Foo = "Hello"; //use the out-of-the-box syntax for adding a property
  3.  
  4.             AValue.AddProperty("Bar", 5); //add a property discovered at runtime.
  5.             AValue.AddProperty(propName, propValue);

So, using the above, I can simply read the name/value pairs out of the database and then add each to my view model at  runtime.  This means that any new value added to the database will automatically be available on the now dynamic view model for binding.

One Offs

Of course, you don't have to use a completely dynamic view model.  It's just as easy to define properties at design time and have one of those properties be a dynamic type.  Also, it's possible to have a dynamic view model that contains a property that is, itself, a dynamic.

Tags: , , ,

.Net | Database | WPF | dynamic

An Introduction to KnockoutJS for XAML Developers

by Administrator 17. December 2011 18:58

I've recently been working with KnockoutJS and have found it to be a very comfortable paradigm to use in constructing a web site.  Having worked with XAML a good bit over the last few years, the benefits of MVVM have been made apparent to me time and again and the approach is familiar.

KnockoutJS lets you use very nearly the same MVVM approach you're used to using in WPF or Silverlight development.  I've attached a sample application, below.  Let's have a look at it.

If you run the sample application, you'll see the following web page open in the browser.

RunningApp

There is an editable table that allows the user to edit existing contacts. Clicking the Add Contact button adds a new blank row to the table.

The ViewModel

The project contains a Javascript file named ViewModel.cs, in the Scripts directory.  The contexts of this file are listed below.

   1:  var viewModel = {
   2:      contacts : ko.observableArray([
   3:          { firstName : "Bob", lastName : "Marley" },
   4:          { firstName : "Larry", lastName : "The Cable Guy" },
   5:          { firstName : "Maxwell", lastName : "Smart" }
   6:      ]),
   7:   
   8:      addContact : function() {
   9:          this.contacts.push( { firstName : "", lastName : "" } );
  10:      }
  11:  }
  12:   
  13:  $(document).ready(function() {
  14:      
  15:      ko.applyBindings(viewModel); 
  16:  })
 
 

In the first code block, lines 1 – 11, we create a view model.  In WPF or Silverlight, out view model would contain properties and commands that we could bind to in our view.  The same is true with KnockoutJS.  Here, we have a property that is a collection of contacts and a function (command).  In lines 13 – 16, we ask Knockout to parse our view and connect the data bindings to our view model.

Notice that our property is an instance of an observableArray.  In XAML data binding, we have the concept of  the view and view model communicating with one another where events are raised when values change so that data and the controls bound to it stay in sync.  This same functionality is encapsulated in the observableArray for arrays and observable for simple properties.    So, modifying a bound property from the view model will cause a control in the view that is bound to the property to change, as well.  The reverse is also true, modifying the contents of the control will update the view model property.

The View

   1:  @{
   2:      Layout = null;
   3:  }
   4:   
   5:  <!DOCTYPE html>
   6:  <html>
   7:  <head>
   8:      <title>Index</title>
   9:      <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
  10:      <script src="../../Scripts/jQuery.tmpl.js" type="text/javascript"></script>
  11:      <script src="../../Scripts/knockout-1.2.1.js" type="text/javascript"></script>
  12:      <script src="../../Scripts/ViewModel.js" type="text/javascript"></script>
  13:  </head>
  14:  <body>
  15:      <div>
  16:          <fieldset>
  17:              <legend>Email Addresses</legend>
  18:   
  19:                  <table>
  20:                  <thead>
  21:                      <tr>
  22:                          <th>First Name</th>
  23:                          <th>Last Name</th>
  24:                      </tr>
  25:                  </thead>
  26:                  <tbody 
  27:                    data-bind='template: { name: "contactRowTemplate", foreach: contacts }'>
  28:                  </tbody>
  29:              </table>
  30:   
  31:              <button data-bind="click: addContact">Add Contact</button>
  32:   
  33:              <script type="text/html" id="contactRowTemplate">
  34:                  <tr>
  35:                      <td><input class="required" 
  36:                          data-bind="value: firstName, uniqueName: false"/></td>
  37:                      <td><input class="required" 
  38:                          data-bind="value: lastName, uniqueName: false"/></td>
  39:                  </tr>
  40:              </script>
  41:   
  42:          </fieldset>
  43:      </div>
  44:  </body>
  45:  </html>
 

We start by setting up our html table.  All probably looks familiar up to line 27.  In Xaml, we use Binding expressions to state what we want to bind to and how that binding is to behave.  KnockoutJS uses the "data-bind" attribute to specify these bindings.  In line 27 a binding is expresses that says, "for each item in the collection of contacts on the view model, create and populate an instance of the template named 'contactRowTemplate'".  You can see the template definition in lines 33 – 40.

Compare this binding with a similar Xaml binding and you'll find:

  • It's possible to do an ItemsSource type binding in KnockoutJS where an item is generated for each entry in an array.
  • Adding or removing an item from the array causes row corresponding to that item to appear or disappear respectively.
  • A template can be specified for how each item in the list will be constructed.  Compare this with the ability to specify an ItemTemplate in Xaml (note that you can organize the container of the list as you wish which is very similar to ControlTemplate's.
  • In Xaml, the data context flows in a predictable way through all an item's sub-items.  Note that the binding on the <tbody> element is to an array and the bindings inside the template are to a single item in the array.  This behaves the same as in Xaml.

The button in line 31 uses a click binding to bind the click event to the function we defined on our view model.

Yes, the binding syntax is different and there are many more binding types available than are used in this simple sample, but the library is very well documented here and the familiarity of the MVVM approach to constructing a UI make KnockoutJS a very easy library to get started with.

Download File - KnockoutSampleSolution

Tags: , , , ,

.Net | ASP.Net | JavaScript | Silverlight | WPF

What is a JavaScript Closure, Anyway?

by Administrator 10. December 2011 14:15

Back in the late nineties, during the .com boom, I worked on a huge web application that used XmlHttp (now known as AJAX) and extensive lots of JavaScript.  The language and how it's perceived has changed a lot since then and so has the maturity of the community using it.  Techniques have come about that make JavaScript easier to use in large internet applications.  Most of these techniques have come about because developers are learning to go with the flow of the language instead of fighting it; to use the unique qualities of the language to advantage.

An Example

Consider the following JavaScript:

   1:  function MyClass(x) {
   2:     var Addend = x;
   3:   
   4:      return AddTo = function (y) {
   5:          return y + Addend;
   6:      }
   7:  }
   8:   
   9:  var AddToTen = MyClass(10);
  10:  alert(AddToTen(10));
  11:   
  12:  var AddToFive = MyClass(5);
  13:  alert(AddToFive(10));

Beginning in line 1, a function is being defined.  Inside this function, we define a local variable and set its value equal to the passed in parameter.  Then, an inner function is returned.  This inner function refers to the local variable defined in the outer function.  Once the outer function has completed execution, it cannot be garbage collected because it is still being referred to by the inner function.  It's also very important to understand that whatever value the local variable has at the time the inner function is returned, is the value that will be visible to the inner function when it is executed from an external call.

When lines 9 and 10 run, 10 is passed in to the outer function and the local variable is set to 10.  When the inner function is returned, it will always see Addend as having the value of 10.  Thus, this script will pop the first alert with a value of 20 and then a second with the value of 15. 

In short, whenever an inner function is returned from an outer one, a logical copy of the outer functions state is made available to the inner function and this state can be accessed each time the inner function is invoked.

What About a .Net Example

We can duplicate this behavior in C#.  I created a Console application to illustrate this.

    class Program
    {
        static void Main(string[] args)
        {
            var five = MyMethod(5);
            Console.WriteLine(five(10));

            var ten = MyMethod(10);
            Console.WriteLine(ten(10));
            Console.ReadLine();
        }

        static Func<int, int> MyMethod(int x)
        {
            int addend = x;

            return new Func<int, int>((y) =>
            {
                return addend + y;
            });
        }
    }

Tags: , ,

.Net | ASP.Net | JavaScript

Dynamically Loading XAML

by Administrator 14. November 2011 04:13

Occasionally it's useful to be able to load a piece of XAML as a string. This allows you to be able to decide, at runtime, what the UI will look like. This XAML can be composed beforehand and stored away in a file or the database, or it can be generated on-the-fly at runtime. In any case, the XAML can be a simple string and loaded into the the visual tree at runtime.

There are a few things you'll need to keep in mind, however.

Remove the Class attribute

The Class attribute is specified on the root element of a XAML document and specified the code file containing the code-behind code that is associated with the document. If this attribute is specified, it is expected that the class exists. Using code-behind kind of defeats the purpose of dynamically loading your XAML.

Explicitly Specify Namespaces and Assemblies

A good rule of thumb is that if you have to add a namespace to your document in order to be able to access its contents, you need to also specify the assembly containing the namespace. For example:

xmlns:cnvtr="clr-namespace:MyConverters.Sub.Xaml.Converters;assembly=MvcConverters"

 

Load the XAML

Once you have clean XAML in a string format, you can load it as below:

            var stringReader = new StringReader(value);
            var xmlTextReader = new XmlTextReader(stringReader);
 
            var control = XamlReader.Load(xmlTextReader);

In the above, "value" is a string that contains the XAML. We set it ass the source of a StringReader, which is set as the source of an XmlTextReader. This is passed into the XamlReader's Load method. Here, the XAML is parsed and a visual tree is constructed.

The Load method returns the root element of your control as a type "object". All that's left to do is to either set the control's DataContext or inject it into an already existing visual tree through, say, binding.

Tags: , , ,

.Net | WPF

Smart House Alerts

by mgordon 25. August 2011 09:15

Bad weather on the way? My Smart House let's me know. I have an appointment this afternoon? It lets me know. A favorite blog has an update? Yep.

I decided early on that I wanted my smart house to notify me of some things. As a result, the time I used to spend checking the weather site, checking for blog updates, checking my calendar is now free time. These things are pushed to me, now, by my smart home.

The system has a series of alerts that do little more than poll various end-points or database records on timers. When conditions are such that I need to be notified, I get a message.

How does the application know how to reach me? Well, a couple of ways. In my system, there is a concept of a communication channel. This channel is associated with a particular user of the system and a certain mode of communication (IM, SMS, email, more to come). When I log into IM, for example, the system knows I'm online and that channel is marked as being open. If an alert occurs, it knows I can be reached on that channel.

For other channels, such as email and SMS, the channel always remains open. For these, I can configure the application to notify me on that channel or not depending on the alert.

IM

I use the XMPP protocol for IM communication with my Smart House. This allows me to use Google Talk or Jabber to get messages from or send messages to the system. I have taken a dependency on the the XMPP SDK from Ags. It allows me to connect to the network, to be notified when any of the Smart House's buddies go on or off line, and to send and receive messages.

Connecting is simple. First, instantiate and configure a connection.

Connect to XMPP
  1. Conn = new XmppClientConnection(ConfigurationManager.AppSettings["XmppServer"]);
  2. Contacts = null;
  3. Contacts = new List<Contact>();
  4. Conn.EnableCapabilities = true;
  5. Conn.ClientSocket.ConnectTimeout = 60000;
  6. Conn.AutoResolveConnectServer = false;
  7. Conn.ConnectServer = "talk.google.com";
  8. Conn.Port = int.Parse(ConfigurationManager.AppSettings["XmppPort"]);
  9. Conn.UseStartTLS = false;
  10. Conn.UseSSL = true;

Then, add some event handlers.

Set Event Handlers
  1. Conn.OnError += conn_OnError;
  2. Conn.OnMessage += conn_OnMessage;
  3. Conn.OnPresence += _conn_OnPresence;
  4. Conn.OnLogin += s =>
  5. {
  6. IsConnected = true;
  7. var p = new Presence(ShowType.chat, "Online") { Type = PresenceType.available };
  8. Conn.Send(p);
  9. };
  10. Conn.OnAuthError += (s, e) => StructuredSpeech2.Logging.Logging.Log("XMPP Authentication Error");
  11. Conn.OnRegisterError += (s, e) => StructuredSpeech2.Logging.Logging.Log("XMPP Register Error: " + e.InnerXml);
  12. Conn.OnSocketError +=
  13. (s, e) =>
  14. StructuredSpeech2.Logging.Logging.Log("XMPP Socket Error: " + e.Message + " :: " + e.StackTrace);
  15. Conn.OnStreamError += (s, e) => StructuredSpeech2.Logging.Logging.Log("XMPP Stream Error: " + e.InnerXml);

Finally, connect.

Connect
  1. try
  2. {
  3. Conn.Open(ConfigurationManager.AppSettings["XmppUsername"],
  4. ConfigurationManager.AppSettings["XmppPassword"]);
  5. }
  6. catch
  7. {
  8. Initialize();
  9. }

Notice that many of the event handlers we're handling have to do with various things that can go wrong. There are logged for investigation later. The OnLogin event fires when a connection to the network has been established. Here, I'm setting the system's status to online and available.

When a login fails, we recurse and try again.

The OnPresence event fires when the presence status of a user has changed such as their becoming available or signing off. The event args let us know the buddy and what their new presence value is. When I handle this event, I evaluate the new presence value and then do two things. I keep a collection of all online contacts so I can quickly broadcast a message. The first thing I do when I get a presence event is to update this collection by adding or removing the contact as appropriate. The second thing I do is update the state of the communication channel for the user the buddy represents.

The OnMessage event fires when a message has been received from a buddy. The event arguments specify the the buddy the message is from and the text of the message. When a message is received, I check to see that the buddy is a user on the system and if they are, I process the message with the Language Processor. If the user is not found, a response is sent to the buddy stating they are not a known user and cannot interact with the system.

Finally, I can send a message to any online buddy by calling the send method on the connection class. As with the the previous discussions about the Speech Processor, the entire conversation is logged and used in processing the text sent in a particular message. In the case of IM, the conversation starts when the buddy connects to the network and ends when they disconnect. When a message has been received, the Language Processor processes it and then uses this send method to reply to the appropriate user. Alerts are send in the same way.

The bottom line is that I can send commands to my house via IM and have it act appropriately or it can send me messages to alert me if my attention is needed. A true conversational interface.

Email

I'm using OpenPop to provide the functionality need to check and manipulate emails on the POP server. My Smart House has it's own email account which it polls on a timer. Each time, all messages are pulled from the email account, processed and then deleted. OpenPop allows the system to connect to the pop account and pull down all the messages. First, the connection object is created and configured.

Connect to POP3 account
  1. _client = new Pop3Client();
  2. _client.Connect(_popEmailServer, _popEmailPort, _popEmailUseSsl);
  3. _client.Authenticate(_popEmailUname, _popEmailPassword);
  4. _client.Reset();

Next, the messages are pulled down and processed.

Process Email Messages
  1. _emailCheckTimer.Stop();
  2. try
  3. {
  4. ConnectClient();
  5. if (!_client.Connected)
  6. return;
  7. int messageCount = _client.GetMessageCount();
  8. var messages = new List<Message>(messageCount);
  9. for (int i = 1; i <= messageCount; i++)
  10. {
  11. messages.Add(_client.GetMessage(i));
  12. _client.DeleteMessage(i);
  13. }
  14. List<Message> staticMessages = messages;
  15. var enc = new ASCIIEncoding();
  16. foreach (Message msg in staticMessages)
  17. {
  18. string request = enc.GetString(msg.FindFirstPlainTextVersion().Body);
  19. string fromAddress = msg.Headers.From.Address;
  20. User user = UserRepository.GetUserByEmail(fromAddress);
  21. if (user == null)
  22. {
  23. SendResponse("I don't know this email address.", msg.Headers.From.Address, msg.Headers.Subject);
  24. return;
  25. }
  26. if (_client != null)
  27. {
  28. _client.Disconnect();
  29. _client.Dispose();
  30. }
  31. CommandProcessor.ProcessCommand(request, user, ConversationMode.Email, fromAddress);
  32. }
  33. }
  34. catch (Exception ex)
  35. {
  36. StructuredSpeech2.Logging.Logging.Log("Checking mail " + ex.Message + ex.StackTrace);
  37. }
  38. finally
  39. {
  40. if (_client.Connected)
  41. _client.Disconnect(); ;
  42. _client.Dispose();
  43. }
  44. _emailCheckTimer.Start();

For sending emails, I use the SmtpClient class in the .Net Framework. See its documentation for usage.

SMS

Once email has been implemented, SMS is easy. I use SMS for outgoing messages, only. Most cell phone carriers allow SMS messages to be send via email. For example, an email sent to an address such as 10digitnumber@txt.att.net, will be received as an SMS message on the AT&T network phone having that 10 digit number. For this reason, I use exactly the same approach to send SMS messages as I do for sending emails.

Tags: , ,

.Net | Smart Home | Natural Language Processing

Letting My Smart Home Keep a TODO List for Me

by mgordon 25. August 2011 05:26

In my last post, I summarized how I created a Natural Language Processor around which I am building a Home Automation solution. I want my smart home to be able to more than just turn things on an off, so I have been adding pieces of functionality that will automate more than that. The first piece of functionality I added was the ability to create and manage items on a TODO list.

Add the Tokens

If you'll recall from my last post, the language processor contains several Token classes that know how to parse out and tokenize words or phrases. These classes are the building blocks which are used to define the system's vocabulary. For the TODO list functionality, we need to define Token classes for the following:

  • "todo"
  • "list", "get", "show"
  • "create"
  • "delete"
  • "mark"
  • "done"
  • "for", "on"
  • dates and times

The language processor will parse the command we specify into a list of tokens that will be compared to the parameter lists of our command methods. When a match is found, that method is called. We need to define our command methods, next.

Create the Command Methods

In the end, we are wrapping little more than CRUD operations for a TODO list table in the database. One example of a command method is below.

Code Snippet
  1. public static void CreateNewToDoItem(ConversationContext cContext, TokenCreate create, TokenToDo todo, TokenQuotedPhrase phrase)
  2. {
  3. var repos = new ToDoRepository();
  4. var newTodo = repos.CreateNewTodo((string)phrase.Value, null, cContext.ConversationUser.UserId);
  5. cContext.Say("Added ToDo \"" + phrase.Value + "\"", newTodo);
  6. }

 

This method takes a token for "create", one for "todo" and another for a quoted phrase which is any phrase found between quotes. So an example of a command that might result in this method's being called would be

create a new todo "Call the hardware store about paint"

You can see that when the method is executed, a new record is created for the todo item. The first parameter is the conversation context. This context contains information such as what channel the communication is on (IM, email, etc.), the user being conversed with and a list of incoming and outgoing messages in this conversation. This is important in some cases. Consider when the user wants to delete a todo item. We could allow them to specify the item by its text, but that could be error prone and a lot of typing. It'd be better if they could specify only a number. So, in my implementation, the user requests a list of their items and what is returned is a numbered list. The user can then say, "delete 2" to remove the second item.

How does the system know which item was number 2? When the list is generated, it's stored in the context such that 2 corresponds to a particular item. From that point on, it doesn't matter what else happens to the records in the database because 2 doesn't just mean the second item, but the item that was second in that list at that point in time. This is possible because of the context.

The reply to the user gets sent to the right user through the right channel because of the context. In this implementation, we don't have to worry about these details in the command method, the context keeps it sorted out for us.

By repeating the process of creating the necessary tokens to build up our vocabulary and then creating rules to match, functionality is layered onto the system to allow the user to associate a due date and time with the item,

create new todo "call the insurance man" for tomorrow 1:30

Tags: , ,

.Net | Smart Home | Natural Language Processing

Natural Language Processing

by mgordon 15. June 2011 10:05

I can’t remember a time when I didn’t have an interest in home automation.  Finally, I decided to take the plunge and started thinking about  what a system might look like.  At the top of my list of requirements was a way to communicate with the system in sentences…via email, SMS, IM and voice.

 

Requirements

What I had in mind was a something that would take what was input, figure out what was being asked for and then perform some action based on how the sentence was interpreted.  The system didn’t need to be able to figure out any possible sentence, but at the same time I didn’t want to have to remember an exact syntax for each command, so some flexibility needed to exist, as well.  Sense I predict the system will be expanded upon in an ongoing way, the addition of functionality and the commands to invoke it had to be relatively easy to add.

 

Existing Tools

I did a fair amount of research into what tools were available and invested a good deal of thought into how I might use them.  As for existing tools, I found that most (like Antelope and SharpNLP)  use maximum entropy to determine the meaning of a sentence.  They break down the sentence into its constituent parts such as phrases and words and define the part of speech each represents.  For each word, it’s also possible to look up its synonyms and definition.  I found that this approach, however, would be quite labor intensive to use.  Also, these tools, curiously, did not understand the concept of certain temporal phrases like “tomorrow” or “last Friday”.

I though these tools could be useful in that a command could be pre-processed and certain parts of it, like the verb and object, could be stored away.  Then, when a command was input, it could be processed and then compared with the stored information.

About this time, I came across Ian Mercer’s blog.  There, he describes an NLP engine that he has built and it became the inspiration for the engine I ended up building.

 

Step by Step

There are three steps I take in processing an input phrase or sentence, Tokenize, Organize and Evaluate.  The input is parsed and tokens are created for the recognized portions of the string.  These tokens are then grouped and organized into a particular order so they can be compared to method signatures defined  to represent recognized commands.   You’ll see that this approach also allows for a good deal of flexibility in how the command is expressed by the user.

 

Tokenize

There are several token classes defined and these are all instantiated at system startup.  Each is responsible for searching out one particular piece of text and correctly interpreting it. The token class also keeps track of where in the string the text was found and its length.  The token classes range in complexity from a simple text search to converting a piece of text into a DateTime or numeric value.  Each token class returns one or more TokenResult classes.  Each of these contains information about the text that was tokenized, where it was found, its length and its value.

The value returned depends on the text being tokenized.  For example, if the text “12” was found to be in the input by the TokenNumeric class, it would return an int, long and double with the value of 12.  It would also return an ordinal value indicating the 12th in a series and DateTime representing the 12th day of the current month. 

All of these Token classes inherit from a Token base class and are in class hierarchies of varying depths.  This allows for the use of polymorphism during the evaluation step.  We’ll see more about this later.

An example of a simple Token class would be the TokenTurn class:

 

[DataContract]
   public class TokenTurn : Token
   {
       public TokenTurn()
       {
           Words = new List<string> { "turn", "set" }; 
       }
   }

 

The base class, Token, defines the member variable “Words” and a method, “Parse”, that knows how to locate occurrences of any of the words in the Words collection.  So, in this decendant class, all that’s required is the definition of the strings to locate.  Once an occurrence is found, the TokenResult that’s returned notes the fact that it was a TokenTurn that located the string.  We’ll use this information later when we look for matching command definitions.  Notice that we have defined two words in our Words collection.  Since either could be found and in either case the meaning of the word would be interpreted as having the same meaning, we are in essence defining synonyms.  This is one way that flexibility is introduced.  For example, the user could say, “turn livingroom lamp on” or “set livingroom lamp on” and the command would be invoked the same way.

In some cases, another level of hierarchy exists.  One example is with the temporal tokens.  The TokenTemporal class knows about its own set of sub-tokens, if you will, that know how to parse bits and pieces of a Date or Datetime.  It cycles through each of these tokens and collects the token results.  It then evaluates them to determine a single date or time value.  This value, in turn, is passed back up the call chain to the main processing logic.

 

At system startup, all Token classes are located and instantiated using reflection.

 

private static List<Token> GetTokens()
       {
           var tokens = new List<Token>();
           var assemblies = new List<Assembly>();
           var currentAssembly = Assembly.GetExecutingAssembly();
           string path = currentAssembly.Location;

           foreach (string dll in Directory.GetFiles(Path.GetDirectoryName(path), "*.dll"))
           {
               try
               {
                   assemblies.Add(Assembly.LoadFile(dll));
               }
               catch (Exception)
               {
               }

           }

           foreach (var assembly in assemblies)
           {
               foreach (Type type in assembly.GetTypes())
               {
                   if ((type.Namespace == "StructuredSpeech2.Tokens.Nouns" ||
                        type.Namespace == "StructuredSpeech2.Tokens.Prepositions" ||
                        type.Namespace == "StructuredSpeech2.Tokens.Temporal" ||
                        type.Namespace == "StructuredSpeech2.Tokens.Verbs" ||
                        type.Namespace == "StructuredSpeech2.Tokens") &&
                       type.Name.StartsWith("Token") &&
                       type.Name != "TokenResult" &&
                       type.Name != "Token" &&
                       type.Name != "TokenNoun")
                   {
                       ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
                       tokens.Add((Token)ci.Invoke(null));

                   }
               }
           }
           return tokens;
       }

When input is received, each token class in the collection has it’s “Parse()” Method called and the input is passed in.  The return from this method is a collection of TokenResult instances.  These are all added to a collection.

 

var results = new List<TokenResult>();

            foreach (var token in Tokens)
            {
                results.AddRange(token.Parse(input));
            }

 

Organize

At this point, we have a collection of tokens that were identified.  They are in no particular order and order is going to be important to us when we start looking for a matching command definition.  So, all the tokens are organized into a dictionary of List<Token>.  The dictionary key is the start position of where the tokenized text was found in the input.  This way, we have an entry for each start position and a collection of Tokens that represent the particular piece of text found there.

 

var buckets = new Dictionary<int, List<TokenResult>>();

            foreach (var result in results.OrderBy(r => r.Start))
            {
                if (!buckets.ContainsKey(result.Start))
                {
                    buckets[result.Start] = new List<TokenResult>(); 
                }

                buckets[result.Start].Add(result);
            }

 

Evaluate

As I’ve alluded to many times, there are also method signatures defined to represent each command the systems knows about.  This methods might look like this:

 

public static void GetWeather(ConversationContext cContext, TokenList list, TokenWeather weather)
        {
            cContext.Say(WeatherService.GetTodaysWeather(cContext.ConversationUser), null);
        }

Each method defined for this purpose takes as its first parameter an instance of ConversationContext.  This object represents the conversation up to this point and allows a method to search back through the context to find things of interest.  For example, if I request a list of things from the system and it returns a list, I can add that list to the conversation context.  At some later time, if I ask the system to delete item number 4, how will the system know which item was number 4 unless it has access to the list that was returned before?  You might say that it could just re-retrieve the list, but what of the list of items has changed somehow?  If an item has been deleted from the list since it was returned last, number 4 might now be number three and the wrong item would be deleted. 

The context is also persisted in the database for durability.

The next two parameters are each tokens and we’ll try to match these with the tokens we have parsed out.

At startup, reflection is used to load all the methods into a collection.

 

var rules = new List<MethodInfo>();
           var assemblies = new List<Assembly>();
           var currentAssembly = Assembly.GetExecutingAssembly();
           string path = currentAssembly.Location;
           IEnumerable methods = null;

           foreach (string dll in Directory.GetFiles(Path.GetDirectoryName(path), "*.dll"))
           {
               try
               {
                   assemblies.Add(Assembly.LoadFile(dll));
               }
               catch (Exception)
               {
               }

           }

           foreach (var assembly in assemblies)
           {
               List<Type> ruleClasses = (from t in assembly.GetTypes()
                                         where !t.IsInterface
                                         where !t.IsAbstract
                                         where t.GetInterface("StructuredSpeech2.IRulesClass") != null
                                         select t).ToList();

               foreach (var ruleClass in ruleClasses)
               {
                   if (ruleClass == null)
                       continue;

                   methods = from m in ruleClass.GetMethods()
                             where m.IsStatic
                             select m;

                   rules.AddRange(methods.Cast<object>().Cast<MethodInfo>());
               }
           }

           return rules.ToList();

We look for any classes that implement the interface StructuredSpeech2.IRulesClass and then load all methods in these classes.

 

When input is received and after the Tokenization and organization steps, we loop through each of these methods.  For each, the parameters each expects are inspected.  The second parameter (remember the first is always our context) is compared with all the tokens found in the first list in the token dictionary to see if there is a match.  If so, the next parameter is compared with tokens in the second list and so on until all parameters have been inspected or we run out of either parameters or lists to compare.  For each method, we retain how many parameters match the tokens we have.

After all methods have been evaluated, we find the one method which matched on all parameters and that method is invoked via reflection.

 

Flexibility

I mentioned earlier that we could simulate synonyms by having our tokens pare out words with similar meaning in our context.  The other greatest point of flexibility is in how the command methods are defined.  Note that in the above example method that the two tokens in the definition were TokenList (which looks for “list”, “get” and “show”) and TokenWeather (which looks for “weather”).  The combination of the token definitions and the command definition allow any of the following to invoke the command.

list weather
list the weather (note that there is no token for “the” so it is effectively ignored
get weather
get the weather
show weather
show the weather

Tags: , ,

.Net

More about Silverlight RawFaults

by mgordon 31. July 2009 15:32

While writing the Silverlight applications at FunkyTools.com, I quickly found that not being able return exceptions from my WCF calls was a huge problem for me.  I located a solution that had been released by the Silverlight WCF team and, at the time, learned just enough about the code to get it integrated into my solution.  I documented how to use the code in a previous blog post. Recently, however, I’ve taken the time to dig into the code and learn more about how it works.

 

Why Faults Don’t Get Returned To Silverlight In The First Place

When Silverlight makes a WCF call, the communication with the server does not happen from the Silverlight application.  Rather, Silverlight uses the browser API to originate the call and the response comes back to the browser, first, and it passes it back to our application.  When an exception occurs in the WCF service, the return HTTP Response Code is changed from 200 to some other value to indicate the call was problematic.  If a response code other than 200 is returned to the browser, Silverlight gets handed back a “Not Found”" Exception from the browser and the actual exception information is lost.

 

The Sample Solution

The sample solution contains 4 projects.

  • SilverlightFaultBehavior – Defines a behavior that is added to a customer binding we can use to enable to have out exceptions returned.
  • SilverlightMessageInspector – Defines a new Channel and Binding for use in the solution.  This Project wires up the Channel, Binding,  and behavior.  These first two projects define all that’s needed to set up the server side of the functionality we desire.
  • SilverlightRawFaults – Defines a single class that is of interest which is a message inspector – more on this in a second.
  • SilverlightRawFaults.Web – A test web site to host the sample service.

 

SilverlightFaultBehavior Project

This project defines a single class, SilverlightFaultBehavior, which extends BehaviorExtensionElement and IEndPointBehavior.  Basically, it adds an additional behavior that we can tie to our bindings.  In this class, there is a method IDispatchMessageInspector.BeforeSendReply that contains the following code:

 

if (reply.IsFault)
{
   HttpResponseMessageProperty property = new HttpResponseMessageProperty();
   property.StatusCode = System.Net.HttpStatusCode.OK; // 200

   reply.Properties[HttpResponseMessageProperty.Name] = property;
}

 

So, basically, just before the response is returned to the browser, this behavior sets the return code to 200 if it’s any other value.

 

SilverlightMessageInspector Project

This project is basically a plumbing project.  It composes the behavior, channel and the message inspector into a binding, which when used, is pre-configured to return the exceptions we desire.

 

SilverlightRawFaults Project

This project contains file SilverlightFaultRawMessageInspector.cs and defines the two classes needed on the client side.  The file contains two classes; RawFaultException, a custom CommunicationException and SilverlightFaultMessageInspector which implements IClientMessageInspector.  In the latter of these classes a method, AfterReceiveReply, contains this code:

 

if (reply != null && reply.Version == MessageVersion.Soap11)
{
    if (reply.IsFault)
    {
        throw new RawFaultException(reply.GetReaderAtBodyContents());
    }
}

 

So, when the reply is received by Silverlight, but before it is returned to our application, this method checks to see if the reposonse contains a Soap 1.1 Fault and if it does, and instance of the custom CommunicationException is created that contains the fault details (error code, message and stack trace) and that exception instance is thrown into our application.

 

So, our response is inspected on the server and its response code is set back to 200 so the browser will interrupt the flow of our fault.  Once Silverlight gets the response, our client side message inspector checks to see if a fault is contained in the response and if so, the fault is converted into an exception and thrown back to the method in our application that originated the call.  

Tags: ,

.Net | Silverlight

Access Role Provider from ASP.Net Ajax and Silverlight

by mgordon 19. June 2009 05:00

In an earlier postI detailed how to access the Membership provider’s services from Silverlight and ASP.Net Ajax.  This is great for logging users into your site, but what if you want to make only certain parts of the application available to these users based on their role in the system at the time they log in or just check the user’s role before allowing them to perform an action? 

I found a great post by Satheesh Babu that describes how to access the Role provider from within the browser. 

Tags:

.Net | ASP.Net | Silverlight

The Best Service Reference Strategy for Silverlight

by mgordon 12. June 2009 06:08

When first learning Silverlight, having often utilized the “Add Web Reference” functionality in Visual Studio in days gone by, I reached for the alluring “Add Service Reference” functionality when adding references to WCF services to my Silverlight projects. I encountered a few problems using this approach and began to search for a better way to reference WCF services.

Project Bloat

The first problem I noticed was the sheer number of files generated by Visual Studio when you add a service reference.  If you’re using source control (and you should be), any modification made to a service reference is going to delete several files and replace them with new ones.  When checking these changes into source control, it can sometimes be confusing trying to figure out how to get your source checked in in a valid state.

Reusing Referenced Assemblies

Second problem I found I was having was that I was often getting errors and warnings when adding or modifying a service reference.  These came in different flavors, but most all complained about the format of the WSDL being received from the service.  With some trial and error, I figured out that the problems were being caused by the default behavior of Visual Studio when adding a reference in respect to reusing types in referenced assemblies. When adding a service reference, the below dialog appears.

AddRef

If you click on the Advanced button, this dialog appears.

Advanced

By default, the “Reuse types in referenced assemblies” checkbox is checked and the “Reuse types in all referenced assemblies” radio button is selected.  If you’re having problems getting client proxies to generate for your services, try clearing the checkbox as this seemed to be the solution for me.

Location, Location, Location

The third problem I’ve had with adding references this way is probably the most important.  With the Add Web Reference I knew and loved, it was a fairly simple matter to modify the generated Reference.cs file to pull the URL for the web service endpoint from a configuration file.  But, when adding a service reference with visual studio, whatever endpoint you specify when adding the reference gets scattered through various of the generated files which makes manual modification extremely difficult.

When I’m working with a Silverlight project, I typically like to have all the services running locally while I’m developing to facilitate debugging and modification of the services which means that my service references need to be pointing to localhost.  Before I deploy, I have to go to each reference and reconfigure it to point to the production server which means that any modified version of my services have to already exist on the server and all this makes deployment a huge headache.  If my shop employed a full set of environments - dev, QA, staging, prod – I’m sure I’d go postal.

The Search for a Better Way

In thinking about the problem, I realized that what I needed was a simple way to generate a client proxy.  I could then build my address, binding and channel in code, pulling any of the necessary pieces of configuration from a config file.  My first thought was to create the proxy class using SvcUtil.exe.  I soon found, though, that the proxies generated by this tool are incompatible with Silverlight.  I then found out about a tool called SlSvcUtil.exe that generates proxies specifically for Silverlight.  Unfortunately, this tool is supposed to ship with Silverlight 3 and I’m still working in version 2.

For now, I’ve found two alternatives.  First is a bit of a hack, but still a fairly easy way to generate proxies that I found here.  Basically, this blog post suggests using the “Add Service Reference” functionality in Visual Studio to generate a reference.cs, saving that class and then deleting the service reference.  I also found an article by David Betz, here, that takes you through an excellent explanation of the details of the inner workings of WCF with Silverlight and suggests writing proxies by hand.

It’s good to have choices and I’m sure I can find circumstances where each approach will be beneficial.

Tags:

.Net | ASP.Net | Silverlight | WCF

About the author

Mitch Gordon lives and works in the great state of Georgia.

RecentPosts

Month List