Friday, February 05, 2010

In the last article we looked at setting up Padarn for using custom HttpHandlers.  In this article we'll look at exactly how we use a custom handler to get data.

The GET Service

Probably the most common HTTP method is the GET method.  It's what your browser used to pull the content of this page, and it's what our REST service will use to get back a list of all Books in our database.

First, I create an entity that defines a Book.  This code file will actually get shared between the device and desktop projects to make things simple.

public class Book
{
  public int ID { get; set; }
  public string Title { get; set; }
  public string Author { get; set; }
  public int? Pages { get; set; }

  public static Book FromXml(string xml)
  {
    // omitted for brevity
  }

  public string AsXml()
  {
    // omitted for brevity
  }
}

I've left out the XML serialization/deserialization routines because they take up a lot of space and aren't really that interesting.  They're in the example source (I'll post it when I get these articles up - be patient) if you want to see them.

So next I need a way to get a list of these from my Database.  To encapsulate all of this logic, I created a DatabaseConnector singleton class that resides in the same assembly as the HttpHandlers.  Remember, these handlers are stateless and get created and called every time a URL is requested, so it would be pointless to put a connector instance in the handler itself.

The DatabaseConnector exposes a GetAllBooks method:

public Book[] GetAllBooks()
{
  string sql = "SELECT BookID, Title, Author, Pages FROM Books";
  List<Book> books = new List<Book>();

  using(SqlCeCommand cmd = new SqlCeCommand(sql, Connection))
  using(var resultset = cmd.ExecuteResultSet(ResultSetOptions.Scrollable))
  {
    if (resultset.HasRows)
    {
      while (resultset.Read())
      {
        books.Add(new Book
        {
          ID = resultset.GetInt32(0),
          Title = resultset.GetString(1),
          Author = resultset.GetString(2),
          Pages = resultset.IsDBNull(3) ? null : (int?)resultset.GetInt32(3)
        });
      }
    }
  }

  return books.ToArray();
}

Now all that I need to do is call this from my GetHandler like so:

public class GetHandler : BaseHandler
{
public override void ProcessRequest(HttpContext context)
{
  string entity = GetEntityName(context.Request.Path);

  // the only entity we support is "Books"
  if (string.Compare(entity, "books", true) != 0)
  {
    throw new HttpException(HttpErrorCode.NotFound, string.Format("Entity '{0}' not supported", entity));
  }

  Book[] books = DataConnector.GetInstance().GetAllBooks();

  StringBuilder sb = new StringBuilder(XML_HEADER);
  sb.Append("<books>");

  foreach (var b in books)
  {
    sb.Append(b.AsXml());
  }

  sb.Append("</books>");

  context.Response.Write(sb.ToString());
  context.Response.Flush();
}

That's all there is to it.  We now have implemented a REST service to get all Books from our Windows CE device.  When the Padarn server sees a GET request at http://<ip address>/books/ it will return an XML stream of all of the books in the database.  Here's an example of the output:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book>
    <id>1</id>
    <title>The Count of Monte Cristo</title>
    <author>Alexandre Dumas</author>
    <pages>1573</pages>
  </book>
  <book>
    <id>2</id>
    <title>Programming WCF Services</title>
    <author>Juval Loewy</author>
    <pages>610</pages>
  </book>
</books>

The GET Client

Now let's look at how a non-browser client (i.e. a desktop application) might make use of this service.

First, since I like abstraction and encapsulation, I created a class named RestConnector that handles all communications for REST services and a class named BookClient who's job is to handle nothing but interactions with the Books service.  RestConnector handles any GET requirements through the following methods:

public string Get(string directory)
{
  string page = string.Format("http://{0}/{1}", DeviceAddress, directory);

  StringBuilder sb = new StringBuilder();

  byte[] buf = new byte[8192];

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(page);

  HttpWebResponse response = (HttpWebResponse)request.GetResponse();

  return GetResponseData(response);
}

private string GetResponseData(HttpWebResponse response)
{
  StringBuilder sb = new StringBuilder();

  byte[] buf = new byte[8192];

  Stream stream = response.GetResponseStream();

  string result = null;
  int count = 0;

  do
  {
    count = stream.Read(buf, 0, buf.Length);

    if (count != 0)
    {
      // look for a UTF8 header
      if ((buf[0] == 0xEF) && (buf[1] == 0xBB) && (buf[2] == 0xBF))
      {
        result = Encoding.UTF8.GetString(buf, 3, count - 3);
      }
      else
      {
        result = Encoding.UTF8.GetString(buf, 0, count);
      }
      sb.Append(result);
    }
  } while (count > 0);

  return sb.ToString();
}

The BookClient uses the Get method to retrieve the XML for a list of books from the service and then deserializes that XML like this:

public Book[] GetAllBooks()
{
  List<Book> books = new List<Book>();

  string xml = Connector.Get(ENTITY_NAME);

    XmlDocument doc = new XmlDocument();
  doc.LoadXml(xml);

  foreach (XmlNode node in doc.SelectNodes("books/book"))
  {
    books.Add(Book.FromXml(node.OuterXml));
  }

  return books.ToArray();
}

It's really that simple.  At this point we have a simple array of Book instances passed from our service to our desktop client so we can do whatever we'd like with them (I'm just displaying them).

Up next: Using POST to add a new entity

2/5/2010 5:51:01 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 

I've spent a bit of time lately adding HttpHandler support to our Padarn Web Server for Windows CE, and today I just wrapped up the code for a pretty in-depth example for using it to host RESTful Web Services.  I'm going to give some highlights on how it works here in my blog as well, because while it's remarkably easy to get working, there's still a lot going on.

Background

The general idea is to have a database on a Windows CE device and a client application on the desktop that could access that database via a Web Service hosted on the device.  I want to be able to do all of the CRUD operations through the service, and nicely these to the HTTP methods:

POST - Create a new entity in the database
PUT - Update an existing entity in the database
GET - Read an entity (or list of entities) from the database
DELETE - Delete an entity from the database

To make things simple, I created a very simple database that contains only one table.  The simple data model isn't real-world, but if you can make it work for one table, making it work for your entire database is really just an extension of the code base.

Setting Up Padarn

I'm going to use custom HttpHandlers to act as the service entry points.  HttpHandlers in Padarn look and work just like they do under IIS, the only difference is how they get "installed:. For Padarn, the handlers are configured, like everything else, in Padarn's configuration file.  To make my life simpler, and the code easier to read, I'll create a separate handler for each separate HTTP method, so one for GET, one for POST and so on.  This is how they get registered with the server:

<httpHandlers>
  <assembly>SampleSite.dll</assembly>
  <add verb="GET" path="/*" type="SampleSite.Handlers.GetHandler, SampleSite"/>
  <add verb="PUT" path="/*" type="SampleSite.Handlers.PutHandler, SampleSite"/>
  <add verb="POST" path="/*" type="SampleSite.Handlers.PostHandler, SampleSite"/>
  <add verb="DELETE" path="/*" type="SampleSite.Handlers.DeleteHandler, SampleSite"/>
</httpHandlers>

Pretty simple. the "add" nodes simply say what method/verb in any given server path maps to a given class.  Padarn uses regex to parse the path, so the first add line basically says "for GET methods to any path on the server, call into an instance of a GetHandler class".  Since the GetHandler is in a separate assembly from my hosting executable, Padarn needs to know about that assembly so it can load it at run time.  The assembly node simply tells Padarn to load up that assembly before it tries creating any custom handler class instances.

Once this is configured, the only thing left to do is to implement the handlers.  An HttpHandler is really simple - it contains a single overriden method that gets called when a page is requested.  Here's what the GetHandler stub looks like:

namespace SampleSite.Handlers
{
  public class GetHandler : BaseHandler
  {
    public override void ProcessRequest(HttpContext context)
    {
      // do stuff here
    }
  }
}

I get in an HttpContext, which has both the HttpRequest and HttpResponse objects. Note how we're trying very hard to mirror the object model Microsoft uses to make the learning curve much easier and to make your code more portable.  The HttpRequest contains, among other things, the incoming path and data.  The HttpResponse is where we write back out our data. 

SImple enough so far, right?  Next up: getting data from our RESTful service.
 

2/5/2010 5:18:58 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Wednesday, January 13, 2010

Well I blew the VB cobwebs out of my brain this morning and wrote a very basic example of getting AP info like signal strength using the SDF.  It took me nearly 2 hours and a whole lot of search engine work to remind me of syntax to crank out a simple 70-line application (I actually had to find a machine with VB installed first, as it's no longer in my "default" install of Studio).  Hard to believe I was once fluent enough in the language to have written a book.

At any rate, here's the sample: BasicWiFiSample.rar (532.46 KB)

1/13/2010 1:26:21 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Wednesday, January 06, 2010

For those following the OpenNETCF IoC Framework, I've checked in another set of fixes.  So yes, it's still an active project.

1/6/2010 1:42:12 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Tuesday, January 05, 2010

Ages ago I did a science project where I was reading and writing registers from managed code.  It worked well and there is absolutely no reason that you shouldn't be able to do this kind of thing.  Windows CE is an embedded platform, and affecting hardware is what we do in the embedded world.

Well, as with any code posted on the web (and in fact this got rolled into the Smart Device Framework), it got used in some actual shipping products.  Great!  i'm not the only one who thinks we should be able to do this stuff.

Well, over the past 6 months or so I had a few different people contact me saying that the code either didn't work, or did work on their earlier hardware, but was now giving strange behavior.

Most telling was that if you hooked up a scope to the memory, you would see 4 write pulses when writing to a register.  Furthermore, all 4 bytes in the register ended up getting set to the last byte in the array you wanted to write.  For example, if you wrote 0x12345678 to a register, it would actually get set to 0x56565656.

Now I know that this code originally worked.  I wrote it using actual hardware (PXA255) so the behavior was new.  The fact that there were 4 strobes on the memory strongly suggested that the code was actually doing 4 individual writes for the 4 bytes, not a single, atomic 4-byte write.

I looked at the code and it couldn't be more simple.  A write boiled down to this:

public void WriteInt32(int data)
{
   Marshal.WriteInt32(m_addressPointer, data);
}

A bit more investigation found that the behavior was fine under CF 1.0, but started failing in CF 2.0.  What that means is that Microsoft changed the underlying implementation of the Marshal class, and in a bad way.  Why would they do such a stupid, stupid thing?  The new mechanism is going to not only cause a break for the writes we're looking at, but it's also a lot slower.

Since I don't know who did this, I can only guess as to what happened.  If you write a 4-byte value to an address that is not DWORD aligned (i.e. not evenly divisible by 4) then an ARM processor with throw a fault and puke on you (x86 throws, but handles it internally).  My bet is that some edge case got reported that the CF was throwing an unaligned exception, and some idiot developer decided that the heavy-handed solution of changing the write to happen byte-by-byte would be the solution.  Yes, it prevents the error, but it causes bugs and is bad, bad form.  Personally I'd like to slap the persone who made the change and the person who reviewed the change and thought it was ok.

So how do you get around this?  Well by doing what the CF itself should have done.  Instead of using Marshal, you use unsafe code and pointers, and check address alignnment before writing.  Something like this:

public unsafe void WriteInt32(int data, int offset)
{
  int baseAddr = (m_addressPointer.ToInt32() + offset);
  if (baseAddr % 4 == 0)
  {
    // dword aligned
    uint* pDest = (uint*)(baseAddr);
    *pDest = (uint)data;
  }
  else if (baseAddr % 2 == 0)
  {
    // word aligned
    ushort* pDest = (ushort*)(baseAddr);
    *pDest = (ushort)(data >> 0x10);
    pDest += 2;
    *pDest = (ushort)(data & 0xFFFF);
  }
  else
  {
    // byte aligned
    byte* pDest = (byte*)(baseAddr);
    foreach (byte b in BitConverter.GetBytes(data))
    {
      *pDest = b;
      pDest++;
    }
  }
}

This is a classic case of someone not understanding the problem they are solving.  This logic should have been done well below us - that's the whole point of using managed code, right?  To simplify things.  Unfortunately it also allows many developers to write code without understanding what it's really doing, and in my mind that's crazy risky. 

Testing also shows that the Read and Copy methods are similarly broken and all of these bugs still exist in CF 3.5, and I strongly suspect it will remain broken in future versions.  So beware, if you're using Marshal for moving data, you could probably get 4x performance improvement by using a pointer instead.

1/5/2010 12:53:28 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Wednesday, November 25, 2009

Long, long ago I wrote an article for MSDN on creating a multi-Form CF application that used a Form Stack.  Since we all tend to grow and learn as developers, we find different ways to do things (and generally we scoff at code we wrote years before as inferior crap). 

Well Peter Nowak is giving a presentation of the OpenNETCF.IoC framework next week and I decided that a sample of using the UI elements of the library (Workspaces, SmartParts, etc) might be handy and so I decided to rewrite the Form Stack following my latest thinking.  Basically the idea is to allow a user to navigate through Forms (actually Views - you are separating your Views from the Model, right?) like you would on a browser.  You can move forward and back as well as "adding" to the end or top of the stack.  We also don't want to be constantly creating new instances of the View classes because we like applications to perform well.

Here's a look at the new application (yes, I know it's "developer ugly" but this is about architecture, not aesthetics):

You can see the stack in the list, and our current position is noted by the asterisk.  "Fwd" will move down to View B, "Back" will move up to Form A, or you can push a new A or B onto the stack at the current location, which will truncate everything currently above (after) the current position.  Again, think of how your browser works.  It's important to know, also, that there are only 3 total View instances created at this point (one of each specific type).

The code for this application is in source control over at the OpenNETCF.IoC Framework Codeplex site.  You'll notice it's called FormStackCS, hinting that there may be a FormStackVB coming.  If you'd like to volunteer to do that port, by all means let me know (meaning don't hold your breath waiting for me to do it).

11/25/2009 12:21:11 PM (Eastern Standard Time, UTC-05:00)  #    Comments [4]  |