# Thursday, May 13, 2010

Nick Randolph and I have been kicking around the idea of adapting the OpenNETCF.IoC project to Silverlight Mobile on Windows Phone 7 (and by "discussing" I mean I'm trying to convince him to do it for me).  I just noticed over on the IoC stats page that we've had some referrals from someone who apparently has either already done it or is in the process of adapting it for PRISM.  I've contacted him to see if we might collaborate, but this is exciting news. Having a dependency injection framework right out of the box for phone development can only help the community provide solid applications.

Thursday, May 13, 2010 6:19:01 PM (Central Daylight Time, UTC-05:00)  #     | 
# Thursday, May 06, 2010

We recently ported a desktop SCSF/CAB application over to use the OpenNETCF.IoC framework.  The primary thinking here was that the SCSF has way, way more stuff than we really need, want or use and the SCSF wizards had done wacky things to a few Studio installations, so we wanted to get rid of all of that as well.

I've checked in the fruits of the labors into the Codeplex project, including new desktop project and solution files.

Now you can be even closer to one codebase for both desktop and device projects.  If nothing else, it allows you to not have to remember two different injection frameworks if, like me, you end up doing a lot of work on both platforms.

Thursday, May 06, 2010 5:48:28 PM (Central Daylight Time, UTC-05:00)  #     | 

I've just rolled a new Padarn release - version 1.4.10126 - to add a new Authentication feature.  In previous versions of Padarn, you had to put your username/password pairs into the WebServer's configuration file.  This isn't too useful if you want to do run-time checking of credentials against something like a database.

Currently Padarn using what would be an analog to IIS authentication - that is to say that the user credentials are checked before any page code is run.  This means that, for now anyway, Forms authentication is not an option.  Instead I opted to allow you to set up the server to give you a callback whenever an authentication request occurs whether you're using Basic or Digest authentication.  For simplicity, the simple act of setting the callback tells the server to no longer look in the user list in the config file.

Setting up for dynamic authentication looks something like this.  First, you create your server instance and then simply set the authentication callback:

m_ws = new WebServer();
m_ws.Configuration.Authentication.AuthenticationCallback = VerifyUsername;

And then you might define you callback like this (note that I've desinged it to handle both Basic and Digest - you probably would pick just one):

bool VerifyUsername(IAuthenticationCallbackInfo info)
{
  // no username is invalid
  if (string.IsNullOrEmpty(info.UserName)) return false;

  // first do a lookup of the password - this might come from a database, file, etc
  string password = GetPasswordForUser(info.UserName);
  if (password == null) return false;

  // determine the type
  BasicAuthInfo basic = info as BasicAuthInfo;
  if (basic != null)
  {
    // we're using basic auth
    return (basic.Password == password);
  }

  // it wasn't basic, so it must be digest
  DigestAuthInfo digest = info as DigestAuthInfo;
  return digest.MatchCredentials(password);
}

The GetPasswordForUser function would look up a password given a username.
 

Thursday, May 06, 2010 11:32:58 AM (Central Daylight Time, UTC-05:00)  #     | 
# Wednesday, April 28, 2010

Somehow we'd missed migrating one of our shared source libraries - the Mobile Ink library - over to CodePlex.  I got that done this afternoon.  More info on using the library can be found here.

 

Wednesday, April 28, 2010 5:23:01 PM (Central Daylight Time, UTC-05:00)  #     | 
# 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

Friday, February 05, 2010 4:51:01 PM (Central Standard Time, UTC-06:00)  #     | 

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.
 

Friday, February 05, 2010 4:18:58 PM (Central Standard Time, UTC-06:00)  #     | 
# 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)

Wednesday, January 13, 2010 12:26:21 PM (Central Standard Time, UTC-06:00)  #     |