Latest Posts
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
Managed Code in the Embedded World
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.
Managed Code in the Embedded World
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)
Managed Code in the Embedded World
For those following the OpenNETCF IoC Framework,
I've checked in another
set of fixes. So yes, it's still an active project.
Managed Code in the Embedded World
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.
Managed Code in the Embedded World
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).
Managed Code in the Embedded World
If you've ever done mstest unit testing with a Smart Device project, then you're painfully
aware of how badly Microsoft dropped the ball on this one. Debugging a unit
test requires making device
registry modifications, adding a call to Debugger.Break in your code, then telling
Studio to Attach to Remote Process once the breakpoint has been hit. Seriously,
that's their officially
published answer to how you debug a Smart Device unit test!
If you know anything about testing, you know that keeping the cycle time for a test
to a minimum. The longer it takes a developer to go from "start testing" to
a break point where they can step, then the less productive they're going to be.
Even worse, if the process is painful, slow and convoluted (check, check and check
for Microsoft's recommendation), they're likely to just skip writing tests altogether.
Internally we get around this by using our own test runner which uses Reflection to
load up and run tests. I've decided to once again give back to the community
and publish this gem as part of Project
Resistance (it will get checked in to the IoC
Framework as well).
It does not support everything that mstest does, but it's got enough to get you going,
and I think it's at least reasonably easy to modify if it doesn't meet your needs.
The currently supported attributes are:
It also might now be obvious how to set it up for your own app. You need to
add a reference to your test assemblies (so VS will deploy them - for some stupid
reason you can't tell it to do so via the Configuration Manager) and make sure all
projects are set to deploy to the same place.
As usual, if you have feedback or updates, please let me know. Submitting a
patch right on one of the project portals is probably the easiest way (hint, hint).
It's probably worth noting here that the code for this is the CFTestRunner project,
and you have to pull it from the source tab on the project site (it's not
in the release download yet).
Managed Code in the Embedded World
For those following Project
Resistance, this is probably going to be a week with little progress. I've
got a major milestone on another project that we're trying to prepare for followed
by an on-site installation so my activity in the code base will be very, very limited.
I believe Alex is also on-site and swamped this week as well. We will be back
at it next week though, hopefully with some new graphics so we can hammer out the
final details of the UI.
Managed Code in the Embedded World
So my final piece of functionality for the week in Project
Resistance was to add key handling to the code base. The idea is that if
you're running on a non-touch device (or for some reason want to use the D-Pad on
a touch device) then you need some ability to "select" a resistance band to change.
I plumbed through events from the Form down to the ResistorController, and back up
to the View so now you can move left or right to select a resistance band and then
up or down will cycle the band just like a gesture will. Of course there's nothing
yet to *visually* show you what band is selected, but the code is in place for it.
What's most interesting about the way this works is that I'm not using the standard
old EventHandler subscription mechanism in code. Instead I'm using a pattern
called "event aggregation." It's a bit odd, but I couldn't find a reasonable
definition online of exactly what event aggregation is, so instead of a link, I'll
actually have to provide a bit more information.
Event aggregation is the ability of a framework to automatically collect up (or aggregate)
event information and wire publishers to subscribers. The OpenNETCF.IoC
framework, which Project Resistance is using for Dependency Injection and as well
as the UI framework, also provides Event Aggregation through simple Attributes.
Let's look at this key-handling as an example.
In the normal old-school event handling way of thinking, if the ResistorController
wanted to get events when a KeyDown happened on the Form, the controller would need
a reference to the Form so it could do a form.KeyDown += new KeyEventHandler(Foo).
The problem with this is that to do this, the Controller now has to know about the
Form, meaning that they get coupled together. That's bad from a maintenance
and extensibilty standpoint, and it really sucks from a test standpoint.
Sure, I could interface the Form and then pass an interface reference in, but still,
why does the Controller need to know anything about the Form? Really it just
wants to know when some other component wants to change the currently selected band
or change the value of the selected band.
Well this is a classic case of where Event Aggregation rocks. In the OpenNETCF.IoC
framework, we simply need to know the string name of the event (which is stored in
a global constant so everyone can use it).
The Form "publishes" the event with a simple attribute like this:
[EventPublication(EventNames.DPadEvent)]
public event KeyEventHandler
DPadKeyPressed;
The anything that wants to receive the event simply uses an attribute to subscribe.
This is what it looks like in the ResistorController:
[EventSubscription(EventNames.DPadEvent,
ThreadOption.Caller)]
public void DPadHandler(object sender,
KeyEventArgs e)
{
...
}
By the nature of the fact that these objects were inserted into one of the IoC framework's
DI container collections, the two automagigically get paired up. No references
get passed around, no interfaces get unnecessarily polluted, and out objects stay
nicely decoupled. All that is required is that both attributes use the same
string name for the event and that the handler method signature matches the expected
publisher's delegate.
Managed Code in the Embedded World
I didn't do much today with Project Resistance,
but that didn't stop progress. Alex got all of the background paionting ironed
out today while I was screwing around with paying work. It looks pretty nice
(well, except for the lower workspace, which is awaiting artwork):
I did do some thinking on the broader process of developing WinMo apps, though.
One thing that most Windows developers (as well as a great many devs for other OSes)
have come to rely on is the good old WYSIWYG editor for Form/Screen/View layouts.
Generally speaking, they've been around for a good while now and not counting that
major backslide called Visual
InterDev, they've done a pretty good job of presenting a design time what you
see at runtime.
Well for everything except Smart Device projects. We at OpenNETCF have been
building controls and libraries for devices since before we were a company.
We've seen all the iterations of Microsoft's tools (all the way back to the add-in
for VB 6 in fact). Never has designing a Form in the tool been easy once you go
past the basic Label, Textbox and Button UI.
Since Studio '03, to get any form of custom control to render properly you had to
do a whole load of extra work.
And to make matters worse, how you had to do it seems to have changed with every new
release of Studio, meaning you have to re-do a lot of the work for existing controls
to get the new tools to support them. I think this is one of the reasons there
are so few 3rd-party vendors doing nice controls (especially with any sort of designer
support). To make thigs even worse, trying to support just the current tool runs
into bugs almost immediately.
So what do those of use who build these apps day-in and day-out do? Well we
live with a rectangle, or a series of them, in the designer and do all of the
actual layout by iterating with a device or the emulator. So the run-time view
you see above looks like this in the designer:
Fancy, eh? And what, you ask, is the upper "DeckWorkspace"? Well
it's a container object from the OpenNETCF.IoC
framework. It basically holds a UserControl, which is what that resistor
image is. It, similarly, gives you very little as design time:
Yes, this is the state-of-the-art. If you're coming to device development from
the desktop, be prepared to be a bit frustrated. Could we have added designer
support for the resistor to this project? Sure. But I bet it would take
more than twice the time we have already into the entire project just to get it to
render, and even then it would come with caveats (like it would work with CF 3.5 but
not 2.0 projects or similar silliness).
So the moral of the story is that you just get used to it. Unless you plan to
be a control vendor don't bother wasting your time even trying to get designer support
working. You'll only end up frustrated, behind schedule, and with a load of
convoluted code that you'll have to rewrite the next time Microsoft releases a new
version of Studio. Maybe things will change in VS10,
but based on the track record I seriously doubt it.
Don't take all of this as being completely down on Studio though. As far as
a development tool it's still the best thing out there (well it's not so great for
C++, but that's another diatribe - just do yourself a favor and get SourceInsight for
that). I've used a lot of tools, and Studio, by far, is the most stable and
feature-rich tool that I've ever used. It's just that there's still a lot of
room for improvement.
Managed Code in the Embedded World
We've made more today progress on Project
Resistance. It turns out that the earlier
bug was indeed due to the fact that in the Compact Framework Color.Transparent
is not a transparent color. How intuitive. If you do Graphics.Clear(Color.Transparent)
what actually occurs is that the underlying bitmap gets filled with white. We
(and by "we" I mean "Alex") had to create some utility functions to directly manipulate
the HDC and do actual transparency.
Again, it's more than a little awkward, and how Microsoft might expect the vast majority
of developers out there to get this right I'm not sure. Even if everyone could write
this code, I still think they shouldn't have to. We should be focused on solving
our business problems, not solving platform problems.
At any rate, we got a fix into the code, and I added gesturing support for the resistance
bands in the ResistorView as well.
You can see that the background is not right, but that's an offset math issue (again
due to the inability to draw transparent controls on a Form) that should be simple
to fix. Yes, the View for the numeric data at the bottom is hideous, but right
now it's simply there to ensure that events get properly wired from the view above,
down to the controller and back out. Making it look good will require work from
the graphic designer.
As a side note, Alex seems to be having some difficulties using SVN as a CodePlex
client and that's why the fix took so long to get published. I'm not having
any problems with the TFS client.
Managed Code in the Embedded World
Today has been a slow day here for Project
Resistance because I'm neck deep in writing other code. I did manage to
get the gesture events for the Tolernace band on the ResistorView plumbed in so now
you can swipe up/down with your finger and it actually changes the band color (though
I noticed I need to fix a couple images) and it updates a second View with a text
representation of the tolerance. Right now that view looks like an engineer created
it, so no screen shot today - I'd rather not embarass myself.
On another, more fun note, fellow MVP and iPhone
development author Christopher Fairbairn has started
an iPhone port of Project
Resistance. He's also started blogging about his
project. Looking at his posts and how easy a time he's having so far makes me
almost jealous. If it weren't for the facts that you have to subject your eyes
to the abomination known as Objective-C and you have to work on a Mac I just
might be. It should be interesting to see how the two projects track toward
getting a product to market. So far we're both just barely out of the gate.
Managed Code in the Embedded World
Back in May 2008, I wrote a blog post about checking
for Win32 methods. I was recently reminded of this when a customer emailed us
about a scenario that exactly matched the intended use case.
The customer was using the Smart Device
Framework with a Windows CE 5.0 device and was receiving a MissingMethodException
"Can't find an Entry Point 'xxx' in a PInvoke DLL 'yyy'". The exception message
is detailed enough to explain the situation -- since Windows CE is modular, whoever
created the OS image had not added a required component, resulting in the native functions
to be missing from coredll.dll. This is not an uncommon scenario in the Windows CE
world.
Below is an example of how you can gracefully handle calling the PlaySound function
from coredll.dll even on devices that don't support the function. The important
part is the call to Device.Win32Library("coredll").HasMethod("PlaySound").
This is return false if coredll.dll does not exist or if coredll.dll does not export
the PlaySound function. Of course, you could raise a PlatformNotSupportedException or
try another mechanism for playing the sound file instead of just returning without
calling the native PlaySound function. The important point is that you should code
in a way that can handle scenarios where the native function is not available and
adapt accordingly.
Imports System.Runtime.InteropServices
Imports OpenNETCF.Reflection
Partial Public Class MainForm
Friend Class NativeMethods
Private Const SND_ASYNC As Integer = &H1
Private Const SND_FILENAME As Integer = &H20000
Public Shared Sub SafelyPlaySound(ByVal soundFile As String)
If Not Device.Win32Library("coredll").HasMethod("PlaySound") Then
Exit Sub ' Function is not exported so we silently return
End If
' Coredll exists and the PlaySound function has been exported
' so we can safely make the P/Invoke call
PlaySound(soundFile, IntPtr.Zero, SND_ASYNC And SND_FILENAME)
End Sub
_
Private Shared Function PlaySound(ByVal szSound As String, _
ByVal hMod As IntPtr, _
ByVal flags As Integer) As Integer
End Function
End Class
End Class


Last week we quietly launched a fantastic new promotion for our Padarn
Web Server product:
Padarn is a lightweight, single-purpose web server that supports a growing subset
of ASP.NET. It is written entirely in C# and can be used as stand-alone web server,
or embedded into an existing application. Padarn can be used to create elegant, data-driven
web sites using SQL Server Compact Edition, or interface with a whole myriad of hardware
peripherals, such as web cams, sensors, controllers, etc.
If you would like more information on Padarn, please send an email to padarn@opennetcf.com.

Note: This blog post only applies to Smart Device Framework Standard or Professional
Edition customers.
>
If you open the SDF Public Source solution that ships with Smart Device Framework
2.3 and then build the source, you'll come across the following error:
Friend access was granted to 'OpenNETCF,PublicKey=...', but the output assembly is
named 'OpenNETCF, Version=2.3.0.21, Culture=neutral, PublicKeyToken=null'. Try
adding a reference to 'OpenNETCF,PublicKey=...' or changing the output assembly name
to match.
(Note that I've replaced the actual public key with ellipses in the above. You will
see an extraordinarily long hexadecimal number in your errors list in Visual Studio.)
The easiest way to remedy this is through a quick search & replace. Hit Ctrl-H to
bring up the Find & Replace window. In the Find what text box, enter
the following:
,PublicKey=00240000048000009400000006020000002400005253413100040000010001002beeba3
bfe7c548e085cffb8c2b6fd61ddd02b06d70864bb7de8bb22473edf5ab4b2196ff98e232c3e87f11fd
7986b743d5d3fdd6ecaf624bacfed116e1cefa50cd652365371d0ebd2702eb1084fed46df79ac0f59f4
d66c547918613d56dcf106843f3458516d3cd26f057a346d9f645fc24a7410a095c754835916e13cdbe
Make sure the Replace with text box is empty and the Look in combobox
is showing Entire Solution. Click the Replace All button. When the search
& replace has completed, build the solution again and it will succeed.
If you wish to do this manually (you may only want to use 1 or 2 of the 16 projects),
you will need to modify the AssemblyInfo.cs file for the following projects:
-
OpenNETCF
-
OpenNETCF.Configuration
-
OpenNETCF.Net
-
OpenNETCF.Windows.Forms
>

Today, we released Smart Device Framework
2.3. This is the long awaited release of the Smart Device Framework for Visual
Studio 2008.
It's been a painful path to get to this point, what with contending with frustrating
bugs in Visual Studio 2008 forms designer and all, but we finally got there. Thanks
for you patience and understanding.
Along with the new version is a new naming convention. We've dropped the name Smart
Device Framework Extensions for Visual Studio with its Standard and Premium editions.
Instead, say hello to Smart Device Framework Standard Edition and Professional
Edition. Be sure to check out the new feature
matrix to find out how each edition differs.
We've got some pretty cool stuff features in the libraries, notably OpenNETCF.Core which
contains a dozen or so extension methods for common scenarios, as well as OpenNETCF.Net.Mail,
for sending mail via SMTP directly from the device -- this eliminates the need to
configure a mail account on the device.

When you reference an assembly compiled against .NET Compact Framework 2.0 in a project
targeting .NET Compact Framework, it's quite likely you will receive a number of ResolveAssemblyReferences warnings,
similar to this:
ResolveAssemblyReferences:
Consider app.config remapping of assembly "System.Windows.Forms, Culture=neutral,
PublicKeyToken=969db8053d3322ac, Retargetable=Yes" from Version "2.0.0.0" [] to
Version "3.5.0.0" [C:\Program Files\Microsoft.NET\SDK\CompactFramework\v3.5\
WindowsCE\System.Windows.Forms.dll] to solve conflict and get rid of warning.
This warning occurs when the compiler has loaded the .NET Compact Framework 3.5 base
class libraries (BCLs) and the referenced assembly, but the metadata contained in
the referenced assembly references the .NET Compact Framework 2.0 BCLs.
To remove the warnings you can add an App.Config to your project and redirect the
assembly bindings from the 2.0 versions to the 3.5 equivalents. Below is an example
of the XML required in the App.Config to redirect the 2.0 version of System.dll to
the 3.5 version.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentassembly>
<assemblyidentity name="System" culture="neutral" publickeytoken="969db8053d3322ac" />
<bindingredirect newVersion="3.5.0.0" oldVersion="2.0.0.0" />
</dependentassembly>
</assemblybinding>
</runtime>
</configuration>
You will need to add a dependentassembly element for each of the ResolveAssemblyReferences
warnings that you receive.
Make sure the Build Action property of the App.Config is set to Content and
the Copy To Output Directory property is set to Only if newer. Then,
rebuild your solution and the warnings should not appear.

There's been a lot of internal discussion today on how to leverage C# 3.0 features
without requiring .NET Compact Framework 3.5. Mark has the low down on using extension
methods with a little compiler misdirection hack.
The discussions kicked off because I discovered that you can use lambda
expressions with .NET Compact Framework 2.0 projects in Visual Studio 2008. I
even twittered about it yesterday. (Note: it didn't take me too long to realize it's
not a bug, but due to Visual Studio 2008 using the C# 3.0 compiler.) Code
like the following just works -- no hacks required:
delegate double PowerOf(double x, double y);
static void Main()
{
PowerOf pwr = (x, y) => Math.Pow(x, y);
double result = pwr(2, 3);
}
If you are using Visual Studio 2008 and still need to target .NET Compact Framework
2.0, the little things like this go a long way to creating and maintaining reusable
code.

Over the last few months we've been working hard to attain the Gold Level partner
status in the Microsoft Partner Program and I'm extremely pleased to say that we've
done it! For our customers, this is an assurance that by choosing to work with OpenNETCF
products and our consultants, you really are choosing a high calibre company.
Massive amounts of credit for Mark for
driving this internally. Good job!

The next Smart Device Development Chat will take place on MSDN at 10am PST on Wednesday,
July 16.
Please join experts from the Windows Mobile, Windows CE, SQL Server CE and .NET Compact
Framework communities in a chat around application development for smart devices.
These chats are a great opportunity to have your questions answered by experts from
around the world.
Add
to Calendar
If you cannot attend the MSDN Chat, there is a permanent chat room available on the web and
via IRC (irc://irc.freenode.net/mobiledev).
Engage with your peers online today!

A little later than I intended, but here is the transcript to Smart Device Development
chat from May 13, 2008: Read
it here

I was browsing around over lunch when I came across an upcoming title from Wrox that
I thought might be interesting to someone out there.
The book, being writing by Samuel Phung of ICOP,
is titled Professional
Microsoft Embedded CE 6.0. A book like this is sorely needed as most of the knowledge
exists primarily in the embedded newsgroup or scattered around in a handful of blogs.
The 20-chapter book will cover everything from creating an image to development in
C# and VB.NET, as well as C++ and is scheduled to be released in November. Wrox have
made a number of chapters available through
their Wrox First subscription service.
