got net?

Kevin Hazzard's Brain Spigot

About the author

Welcome to Kevin Hazzard's blog.
E-mail me Send mail

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009

How I Learned to Love Metaprogramming

UPDATED on 30 June 2009

I spoke at the CodeStock 2009 conference and I thought it would be helpful for the attendees and others to be able to download my code and slides. The title of my presentation was "How I Learned to Love Metaprogramming" and it concerns Dynamic Language Runtime architecture, performance of dynamic typing and Python to C# integration. The slides and source code are linked below. I will be giving this talk again in September at the Charlottesville .NET User Group meeting. Both of the demos require C# 4.0 which is available in Visual Studio 2010.

  • Demo One - shows how to do XML parsing using a fluent interface based on a DynamicObject derivation in C# 4.0
  • Demo Two - shows how the Level 0, 1 and 2 CallSite and ActionBinder caches perform. UPDATED: I added a demo on 30 June 2009 that shows how the DLR 0.9 compares by invoking dynamic code through the DLR hosting APIs, thereby bypassing the CallSite caching mechanisms. The results are very instructive, showing that the DLR's polymorphic inline caching can yield a 250000% increase in performance. You read that correctly: a two hundrend fifty thousand percent increase in performance.

Slides in PDF (Acrobat) format (688.49 kb) 
Slides in PPTX (PowerPoint 2007) format (639.23 kb) 
Demo One Source Code - MetaObjectPlay200905.zip (5.17 kb) 
Demo Two Source Code - PythonIntegration200906.zip (5.33 kb)


Posted by kevin on Saturday, June 27, 2009 8:40 AM
Permalink | Comments (1) | Post RSSRSS comment feed

Remembering the Sony Magic Link

Sony Magic Link PIC-1000

I admit that I've been a geek for a good long while now. 30 years ago, I was taking computers apart and soldering new things into them to experiment or to force them to suit my needs. Those were fascinating times in the computer industry to be sure. Operating systems were simple enough to be understood in their entirety by a single person. Software applications were also very simplistic. Kids in 2009 would LOL at our total lack of sophistication but we were enthralled to be able to move circle and squares sloppily about the screen to simulate bombs or gnomes or whatever we could imagine. We had to use our imagination more in those early days and it wasn't a bad thing per se. Poor graphics and poor sound weren't an impediment to us because we didn't know that they were bad. But we knew they could be better and that kept us going.

At the halfway point on my journey thus far, I bought a Sony Magic Link PIC-1000 handheld computer. It was 1994. I think I paid about $800 for it at the time. I remember the excitement I felt as I opened the package and powered it up. It ran the Magic CAP operating system from General Magic and it was a thing of pure joy, I'll tell you. The screen sporting 16 shades of gray was organized into a virtual desktop complete with drawers that you could open and close by tapping them. You could drag objects into and out of the drawers. It had a filing cabinet, an on screen keyboard and a graphical toolbar of contextual tool icons at the bottom of the screen. The built-in modem would allow you to connect an e-mail or fax provider to exchange messages and documents with others.

I used my Sony Magic Link every day for a couple of years and it taught me a lot about the value of good software design. Some of the applications were clunky but, for the most part, it was a very functional device. Sony positioned the Magic Link as an upscale alternative to Apple's Newton. Having used both of them, I believed the Magic Link to be a far superior device for getting things done. The screen was bigger. It did decent animations. It had a built-in modem and a PCMCIA card slot. And the sound was good for the period. The Newton was cool but it was a glorified notepad, in my opinion. There's no doubt that Apple studied the Magic Link with great care to learn from it. As an iPhone user today, I often think about how similar my iPhone is, in so many ways, to the seminal PDA from Sony. Many of the Magic Link's gestures and graphical metaphors live on in the iPhone today, with or without attribution from Apple. Microsoft didn't seem to learn much from it though as Windows Mobile 6.5 still feels like a desktop OS crammed into a device not so well designed to run it. The truth hurts, I know.

I'm pretty sure that I still have that old Magic Link lying around in the attic somewhere. As I sit here in the White Hawk Music Café waiting for my son to complete his guitar lesson, I bristle with some of that old excitement I felt in 1994, wondering if I find that old device in the attic, will it still work? Will it be as fun today as it was then? Is there something I can solder into it to make it do something fun and new? Some things never change, I suppose. And that's good, too. Never stop learning. That goes for you, too, Mr. Ballmer. Watch and learn.


Categories: CapTech | Fun
Posted by kevin on Wednesday, June 17, 2009 7:00 PM
Permalink | Comments (6) | Post RSSRSS comment feed

Fluent XML Parsing Using C#'s Dynamic Type Part 2

In part 1 of this article, I showed you how to create a fluent parser for XML documents as a dynamic type in C# 4. With that dynamic class, you can use the dot (.) and index ([]) operators to traverse any XML document with a very natural syntax. Being able to read XML fluently is great. But to be really useful, our dynamic class should allow the programmer to modify the XML document fluently as well. To do this, we'll need to modify the behavior of the overridden TryGetMember method to create missing XElements whenever they are referenced by the code. Here's the modified code for the TryGetMember method:

public override bool TryGetMember(
    GetMemberBinder binder, out object result)
{
    result = null;

    /* handle the Value and Count special cases */
    if (binder.Name == "Value")
        result = _elements[0].Value;
    else if (binder.Name == "Count")
        result = _elements.Count;
    else
    {
        /* try to find a named attribute first */
        var attr = _elements[0].Attribute(
            XName.Get(binder.Name));
        if (attr != null)
        {
            /* if a named attribute was found,
               return that NON-dynamic object */

            result = attr;
        }
        else
        {
            /* find the named descendants */
            var items = _elements.Descendants(
                XName.Get(binder.Name));
            if (items != null && items.Count() > 0)
            {
                /* prepare a new dynamic object with
                   the list of found descendants */

                result = new DynamicXml(items);
            }
        }
    }
    if (result == null)
    {
        /* not found, create a new element here */
        _elements[0].AddFirst( new XElement( binder.Name ) );
        result = new DynamicXml( _elements[0].Descendants().First() );
    }
    return true;
}

Notice near the bottom of the TryGetMember method that when the object named in the binder is not found, a new XElement is created and added as the first child of the current element. Then, a DynamicXml wrapper is created to continue the fluent chain to the next call as may be necessary. Since the specially handled "Value" member is used to get the value of a DynamicXml element, we also need to handle the "set" case for the times when the programmer attempts to assign a Value to an element. To do that, we need to override the TrySetMember method in the DynamicXml class like this:

public override bool TrySetMember(
    SetMemberBinder binder, object value)
{
    if (binder.Name == "Value")
    {
        /* the Value property is the only one that
            may be modified. TryGetMember actually
            creates new XML elements in this
            implementation */

        _elements[0].Value = value.ToString();
        return true;
    }
    return false;
}

With these two changes in place, we can write code to modify the underlying XML document, too. In the following code that exercises both of the code changes, notice that the first author of the second book has no middle name element in the source XML document. With the changes we've made to TryGetMember and TrySetMember, however, this isn't a problem at all. Look at the code that assigns the middle name value of "Lisa" to that author below.

var xml = "<books pubdate='2009-06-15'>" +
 "<book price='45.99' title='Open Heart Surgery for Dummies'>" +
  "<id isbn10='4389880339'/>" +
  "<authors>" +
   "<author>" +
    "<name>" +
     "<first>Mortimer</first>" +
     "<middle>Q.</middle>" +
     "<last>Snerdly</last>" +
    "</name>" +
    "<email address='mort@surgery.com'/>" +
   "</author>" +
  "</authors>" +
 "</book>" +
 "<book price='32.75' title='Skydiving on a Budget'>" +
  "<id isbn='2129034454'/>" +
  "<authors>" +
   "<author>" +
    "<name>" +
     "<first>Trudy</first>" +
     "<last>Freefall</last>" +
    "</name>" +
    "<email address='tfreefall@jump.com'/>" +
   "</author>" +
   "<author>" +
    "<name>" +
     "<first>Bernard</first>" +
     "<middle>M.</middle>" +
     "<last>Fallson</last>" +
    "</name>" +
    "<email address='bernie@airborne.com'/>" +
   "</author>" +
  "</authors>" +
 "</book>" +
"</books>";

dynamic dx = new DynamicXml(xml);
dx.book[1].authors.author[0].name.middle.Value = "Lisa";

foreach (dynamic b in dx.book)
{
    Console.WriteLine("----- Begin Book -----");
    Console.WriteLine("Price='{0}'", b.price.Value);
    Console.WriteLine("Title='{0}'", b.title.Value);
    Console.WriteLine("AuthorCount='{0}'", b.authors.author.Count);
    foreach (dynamic a in b.authors.author)
    {
        Console.WriteLine("   ---- Begin Author ----");
        Console.WriteLine("   EmailAddress='{0}'", a.email.address.Value);
        Console.WriteLine("   FirstName='{0}'", a.name.first.Value);
        Console.WriteLine("   MiddleName='{0}'", a.name.middle.Value);
        Console.WriteLine("   LastName='{0}'", a.name.last.Value);
        Console.WriteLine("   ----- End Author -----");
    }
    Console.WriteLine("------ End Book ------");
}

When information about the first author of the second book is dumped to the console, we see that it contains the middle name that was assigned in the fluent mutation of the XML document:

---- Begin Author ----
EmailAddress='tfreefall@jump.com'
FirstName='Trudy'
MiddleName='Lisa'
LastName='Freefall'
----- End Author -----

Nice and easy, right? That's enough for this installment. In the next article in this series, I'll add some error handling code and deal with "the XML attribute problem" as it will come to be known. Enjoy.


Tags: ,
Categories: C# | CapTech
Posted by kevin on Monday, June 15, 2009 6:06 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Ordering the SQL UNIQUEIDENTIFIER Type Numerically Correct for Reporting

As a follow-up to my last post on How SQL Server Sorts the UNIQUEIDENTIFIER Type, I thought it would be useful to have a function that would reorder the bytes of UNIQUEIDENTIFIERS whenever I need to show them in numerically correct order. Here's the User-Defined Function (UDF) I wrote to do this:

-- =============================================
-- Author:      W. Kevin Hazzard
-- Create date: 14 June 2009
-- Description: Reorder the bytes of a
--              UNIQUEIDENTIFIER to show it as
--              a numerically correct string.
-- =============================================
CREATE FUNCTION [dbo].[NumericallyCorrectUid]
(
    @uid UNIQUEIDENTIFIER
)
RETURNS NCHAR(36)
AS
BEGIN
    DECLARE @result NCHAR(36)
    SET @result = CONVERT(NCHAR(36), @uid)
    SET @result =
        SUBSTRING(@result, 25, 8)
        + N'-'
        + RIGHT(@result, 4)
        + SUBSTRING(@result, 19, 6)
        + SUBSTRING(@result, 17, 2)
        + SUBSTRING(@result, 15, 2)
        + N'-'
        + SUBSTRING(@result, 12, 2)
        + SUBSTRING(@result, 10, 2)
        + SUBSTRING(@result, 7, 2)
        + SUBSTRING(@result, 5, 2)
        + SUBSTRING(@result, 3, 2)
        + LEFT(@result, 2)
    RETURN @result
END
GO

Invoking the UDF is easy. Here's a little script that demonstrates how to do it:

DECLARE @uid UNIQUEIDENTIFIER
SET @uid = N'EBC23DE8-DC16-4A8B-8E11-6B1509B0DAED'
PRINT @uid

DECLARE @correctUid NCHAR(36)
SELECT @correctUid = [<your DB name here>].[dbo].[NumericallyCorrectUid] (@uid)
PRINT @correctUid

This outputs the following text in the Messages window of SQL Server Management Studio:

EBC23DE8-DC16-4A8B-8E11-6B1509B0DAED
6B1509B0-DAED-8E11-8B4A-16DCE83DC2EB

This matches the octet ordering that I showed in the previous blog post. Of course, if you attempt to create a new UNIQUEIDENTIFER in SQL using the reordered string, the new value will not be equal to the orginal. So be careful to use the reordered string only for reporting or whenever you need to see the UNIQUEIDENTIFIER values in numerically correct order. Enjoy.


Tags:
Posted by kevin on Sunday, June 14, 2009 11:51 AM
Permalink | Comments (0) | Post RSSRSS comment feed

How SQL Server Sorts the UNIQUEIDENTIFIER Type

When you read sorted UNIQUEIDENTIFIER values in the query results from Microsoft SQL Server, it's not immediately clear how they may be ordered. Alberto Ferrari wrote a blog post about this subject a while ago. However, I didn't find that Alberto's article highlighted the answer to my fundamental questions about UNIQUEIDENTIFIER sorting. Numbering the octets in the UNIQUEIDENTIFIER from left to right as 0..9 then A..F, what is the Most Significant Byte (MSB) to Least Significant Byte (LSB) ordering of the type from SQL Server's perspective?

You can really think of a UNIQUEIDENTIFIER like a really big integer: 128 bits or 16 bytes wide. However, when you look at the 32 hexadecimal digits of a UNIQUEIDENTIFIER expressed as a hyphenated string, it's not clear that SQL is treating this type like a number that we would read from left to right. For example, look at the following two UNIQUEIDENTIFIERs generated by SQL Server's NEWID() function:

  • EBC23DE8-DC16-4A8B-8E11-6B1509B0DAED
  • 4F899E16-9D3E-4EA6-8A32-749A3FCAD865

Do these look like large integers? Maybe if you took the hyphens out. If they were numbers, which of them would be the larger one? Reading left to right, anyone with a cursory understanding of hexadecimal notation might assume that the first value beginning with EB is larger than the one beginning with 4F. But that's not correct from SQL Server's perspective. The second one is the larger UNIQUEIDENTIFIER to SQL Server. To prove this, run the following query in SQL Server Management Studio:

WITH [UIDs] AS ( --                        0 1 2 3  4 5  6 7  8 9  A B C D E F
          SELECT [ID] = '0', [UID] = CAST('01000000-0000-0000-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '1', [UID] = CAST('00010000-0000-0000-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '2', [UID] = CAST('00000100-0000-0000-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '3', [UID] = CAST('00000001-0000-0000-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '4', [UID] = CAST('00000000-0100-0000-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '5', [UID] = CAST('00000000-0001-0000-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '6', [UID] = CAST('00000000-0000-0100-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '7', [UID] = CAST('00000000-0000-0001-0000-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '8', [UID] = CAST('00000000-0000-0000-0100-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = '9', [UID] = CAST('00000000-0000-0000-0001-000000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = 'A', [UID] = CAST('00000000-0000-0000-0000-010000000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = 'B', [UID] = CAST('00000000-0000-0000-0000-000100000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = 'C', [UID] = CAST('00000000-0000-0000-0000-000001000000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = 'D', [UID] = CAST('00000000-0000-0000-0000-000000010000' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = 'E', [UID] = CAST('00000000-0000-0000-0000-000000000100' AS UNIQUEIDENTIFIER)
    UNION SELECT [ID] = 'F', [UID] = CAST('00000000-0000-0000-0000-000000000001' AS UNIQUEIDENTIFIER)
)
SELECT [ID], [UID] FROM [UIDs] ORDER BY [UID] DESC

This query is based on the one that Alberto Ferrari showed in his blog. But this one goes after the answer that I'm interested in a bit more directly. The query creates a rowset that associates each distinct octet in UNIQUEIDENTIFIERs with an order identifier, 0..9 then A..F. Then, by ordering the results of the query by the the UNIQUEIDENTIFIER values, we should be able to tell which octets are more significant numerically than the others according to SQL Server. Here's what the results look like:

A 00000000-0000-0000-0000-010000000000
B 00000000-0000-0000-0000-000100000000
C 00000000-0000-0000-0000-000001000000
D 00000000-0000-0000-0000-000000010000
E 00000000-0000-0000-0000-000000000100
F 00000000-0000-0000-0000-000000000001
8 00000000-0000-0000-0100-000000000000
9 00000000-0000-0000-0001-000000000000
7 00000000-0000-0001-0000-000000000000
6 00000000-0000-0100-0000-000000000000
5 00000000-0001-0000-0000-000000000000
4 00000000-0100-0000-0000-000000000000
3 00000001-0000-0000-0000-000000000000
2 00000100-0000-0000-0000-000000000000
1 00010000-0000-0000-0000-000000000000
0 01000000-0000-0000-0000-000000000000

Do you see the pattern? Reading the IDs in the left column from top to bottom, we can see that the most significant octet is in the A position and the least significant one is at position 0. The pattern that represents the most significant to the least significant bytes reads as ABCDEF8976543210 which is not exactly what you might expect. Looking back at the new UNIQUEIDENTIFIER values shown above, now we know why EBC23DE8-DC16-4A8B-8E11-6B1509B0DAED is considered to be less than 4F899E16-9D3E-4EA6-8A32-749A3FCAD865 numerically by SQL Server. The 6B octet at position A in the first UNIQUEIDENTIFER is less than the 74 octet at the same position in the second value. In fact, if we were to reorder the all of the bytes in those two UNIQUEIDENTIFIERs left to right according to the way that SQL Server really "sees" them numerically, they would need to undergo these transformations:

  • EBC23DE8-DC16-4A8B-8E11-6B1509B0DAED would be seen as 6B1509B0DAED-8E11-8B4A-16DC-E83DC2EB
  • 4F899E16-9D3E-4EA6-8A32-749A3FCAD865 would be seen as 749A3FCAD865-8A32-A6E4-3E9D-169E894F

So, now we can read SQL Server UNIQUEIDENTIFIERs numerically. That will come in handy one day so tuck it into the back of your brain. Enjoy.


Tags:
Categories: CapTech | SQL Server 2008
Posted by kevin on Friday, June 12, 2009 10:03 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Fluent XML Parsing Using C#'s Dynamic Type Part 1

Parsing XML documents using a fluent interface is a very compelling idea. Given some simple XML that contains information about books and their authors (see the end of this article for a sample), I'd like to be able to parse it with something like this:

// for brevity, not all of the XML is shown here - use your imagination
string xml = "<books><book><authors>...<authors></book>...</books>";

// create a dynamic XML parser that enables a fluent interface
dynamic dx = new DynamicXml( xml );

// show the last name of the 1st author of the 3rd book
Console.WriteLine( dx.book[2].authors.author[0].name.last );

Being able to use the dot and [] operators to traverse an XML document makes a lot of sense. But how could we write a class that makes this possible for any XML document, no matter what schema it has? The dynamic type in C# opens up some great possibilities in this case. All you need is a class that will handle the member access (dot operator) and indexer access ([] operation) at runtime. Using dynamic typing in C#, these things can be late-bound, so if a class like the one called DynamicXML in this example existed to do the actual XML parsing, it could make XML handling much simpler and more intuitive. For reference purposes, the full XML sample that we'll be working with is shown at the end of this article.

The source code for my DynamicXml class follows. Now, be warned, I've deliberately left all of the error handling code out of this version. In a subsequent article, I'll add some robustness to the DynamicXml class along with some other dynamic goodies. Scroll down to get a complete analysis of what this class does.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Dynamic;
using System.Xml.Linq;
using System.Collections;

public class DynamicXml : DynamicObject, IEnumerable
{
    private readonly List<XElement> _elements;

    public DynamicXml( string text )
    {
        var doc = XDocument.Parse( text );
        _elements = new List<XElement> { doc.Root };
    }

    protected DynamicXml( XElement element )
    {
        _elements = new List<XElement> { element };
    }

    protected DynamicXml( IEnumerable<XElement> elements )
    {
        _elements = new List<XElement>( elements );
    }

    public override bool TryGetMember(
        GetMemberBinder binder, out object result )
    {
        result = null;
        if (binder.Name == "Value")
            result = _elements[0].Value;
        else if (binder.Name == "Count")
            result = _elements.Count;
        else
        {
            var attr = _elements[0].Attribute(
                XName.Get(binder.Name ) );
            if (attr != null)
                result = attr;
            else
            {
                var items = _elements.Descendants(
                    XName.Get(binder.Name ) );
                if (items == null || items.Count() == 0)
                    return false;
                result = new DynamicXml( items );
            }
        }
        return true;
    }

    public override bool TryGetIndex( GetIndexBinder binder,
        object[] indexes, out object result )
    {
        int ndx = (int)indexes[0];
        result = new DynamicXml( _elements[ndx] );
        return true;
    }

    public IEnumerator GetEnumerator()
    {
        foreach (var element in _elements)
            yield return new DynamicXml( element );
    }
}

OK, let's analyze the DynamicXml class section by section. First of all, notice the inclusion of the new System.Dynamic namespace. This is where the base class called DynamicObject comes from. The DynamicObject class wraps up a lot of the messy details that you would have to take care of if you were writing an implementation of the IDynamicMetaObjectProvider interface. This is an interface that the runtime binder looks for when applying special treatment to dynamically typed objects. Since the DynamicObject class provides an implementation of that interface, using it as a base class for our DynamicXml class does most of the work for us.

Now scan down into the class and notice the TryGetMember and TryGetIndex overrides in the DynamicXml class. The DynamicObject base class provides virtual methods for the various Dynamic Language Runtime (DLR) "verbs" that we want to implement. The DLR uses these verbs to define the border between languages with the common operations that we need to communicate. For example, here are some of the operations that the DLR defines:

  • InvokeMember - call a method
  • GetMember - call the accessor for a property
  • SetMember - call the mutator for a property
  • CreateInstance - this one's pretty self-explanatory; think C#'s new operator
  • GetIndex - when treating the object like a collection, get the element at a specific index
  • SetIndex - set the element at a specific index

Remember that I said earlier that if you wanted a fluent interface for parsing an XML document, you would need to handle the member access (using the dot operator) and index access (using C#'s [ and ] subscripting syntax). Well, these two overrides, TryGetMember and TryGetIndex provide just the implementations we're interested in. So, when the runtime binder accesses members and indexes on a DynamicXml object, it will be routed to these methods. Let's start with the TryGetMember method.

public override bool TryGetMember(
    GetMemberBinder binder, out object result )
{
    result = null;
    if (binder.Name == "Value")
        result = _elements[0].Value;
    else if (binder.Name == "Count")
        result = _elements.Count;
    else
    {
        var attr = _elements[0].Attribute(
            XName.Get( binder.Name ));
        if (attr != null)
            result = attr;
        else
        {
            var items = _elements.Descendants(
                XName.Get( binder.Name ) );
            if (items == null || items.Count() == 0)
                return false;
            result = new DynamicXml( items );
        }
    }
    return true;
}

In a sense, the DynamicXml class is just a facade for a List<XElement> as you can see in the class's declaration. That list is managed in a field called _elements. The TryGetMember override processes requests to access the XElement objects in _elements in a certain order. First, it looks for requests to the Value and Count members. The Count member comes straight off of the _elements list. But the Value member is assumed to be the Value of the first XElement in the list. This is because sometimes, we want the fluent interface to be dealing with a single XML element and other times we want it to be expressing array-like access using the [ and ] symbols. Next, the TryGetMember function gives preference to attributes that may exist in the XML. This is just a design choice. We could have chosen to process child elements before the attributes of the current one instead. If an XML attribute is found by the name that the runtime binder is seeking, it will be returned.

This is an interesting point that you should stop to reflect on. When a dynamic object returns a non-dynamic object, the result is still considered dynamic because the runtime binder is controlling the execution. One way to think of the runtime binder is that it's like late compilation. Even if a statically typed object like an XAttribute is returned, accesses into that object are handled by the runtime binder. Since the XAttribute is not a dynamic type, the C#-specific binder would be used to find and invoke it's Value property, most likely through some type of reflection. So, it's OK to return non-dynamic objects in a dynamic "pipeline". You can even switch back and forth if you desire. The first object in the dynamic chain could return a non-dynamic object, which could return a dynamic object that, through the next invocation, returns a non-dynamic object, etc. The point is that once you start using the dynamic runtime binder, you'll keep using is until the call chain is complete. You should think long and hard about the performance impact that might have on your applications. Runtime binding is slower than the static, compile-time binding that you are accustomed to. There are things we can do to make runtime binding faster but that's a story for another day.

To finish up with describing how TryGetMember works, the XML Descendents of the current element are queried by the name presented by the runtime binder in it's Name property. The resulting iterator is used to create a new instance of the DynamicXml type which is returned from the member access. The reason we must always treat the result as a list is that we can't tell from the source XML if the member being sought is supposed to be a single element or a collection. If we had an XML Schema Definition for the source document, perhaps we could make an optimization for the single instance cases. But this code works OK. Now on to the much simpler TryGetIndex implementation.

public override bool TryGetIndex( GetIndexBinder binder,
    object[] indexes, out object result )
{
    int ndx = (int)indexes[0];
    result = new DynamicXml( _elements[ndx] );
    return true;
}

Now, let's look at TryGetIndex override. It's very simple by comparison to TryGetMember. It expects the indexing type to be a single dimension integer. So it performs that cast then passes the index to the _elements list to create (you guessed it) another DynamicXml object. In this case, a special constructor does the work of converting that single element into a list for reasons described above.

public IEnumerator GetEnumerator()
{
    foreach (var element in _elements)
        yield return new DynamicXml( element );
}

The last important thing to understand is the implementation of IEnumerable. In those cases when the DynamicXml instance is acting like a collection of elements, we would like to be able to enumerate over them. However, internally, the DynamicXml manages XElements which are not, by definition, dynamic. During the iteration of XML in our fluent interface, we want to be able to continue being fluent. To do that, the iterator has to return not XElement objects but DynamicXml objects. So, the enumerator yields each XElement by instantiating a DynamicXml wrapper around it.

You may be asking why I didn't implement strongly-typed enumeration using IEnumerable<DynamicXml> instead. The reason for that is simple. In a dynamic processing context, types get thrown out the window, so to speak. We could implement strong typing but it wouldn't usually matter because iteration that yields DynamicXml types is probably already using the dynamic runtime binder anyhow. For the XML document below, here's a snippet of C# code that parses the entire document using our dynamic, fluent interface.

// the variable xml contains the string text of an XML document
dynamic dx = new DynamicXml(xml);
Console.WriteLine("PublicationDate='{0}'", dx.pubdate.Value);
Console.WriteLine("BookCount='{0}'", dx.book.Count);
foreach (dynamic b in dx.book)
{
    Console.WriteLine("----- Begin Book -----");
    Console.WriteLine("Price='{0}'", b.price.Value);
    Console.WriteLine("Title='{0}'", b.title.Value);
    Console.WriteLine("AuthorCount='{0}'", b.authors.author.Count);
    foreach (dynamic a in b.authors.author)
    {
        Console.WriteLine("   ---- Begin Author ----");
        Console.WriteLine("   EmailAddress='{0}'", a.email.address.Value);
        Console.WriteLine("   FirstName='{0}'", a.name.first.Value);
        Console.WriteLine("   MiddleName='{0}'", a.name.middle.Value);
        Console.WriteLine("   LastName='{0}'", a.name.last.Value);
        Console.WriteLine("   ----- End Author -----");
    }
    Console.WriteLine("------ End Book ------");
}

This code parses the XML fluently and produces the following output from the sample XML below:

PublicationDate='2009-05-20'
BookCount='3'
----- Begin Book -----
Price='45.99'
Title='Open Heart Surgery for Dummies'
AuthorCount='1'
   ---- Begin Author ----
   EmailAddress='mort@surgery.com'
   FirstName='Mortimer'
   MiddleName='Q.'
   LastName='Snerdly'
   ----- End Author -----
------ End Book ------
----- Begin Book -----
Price='32.75'
Title='Skydiving on a Budget'
AuthorCount='2'
   ---- Begin Author ----
   EmailAddress='tfreefall@jump.com'
   FirstName='Trudy'
   MiddleName='L.'
   LastName='Freefall'
   ----- End Author -----
   ---- Begin Author ----
   EmailAddress='bernie@airborne.com'
   FirstName='Bernard'
   MiddleName='M.'
   LastName='Fallson'
   ----- End Author -----
------ End Book ------
----- Begin Book -----
Price='22.40'
Title='How to Dismantle a Bomb'
AuthorCount='1'
   ---- Begin Author ----
   EmailAddress='bono@u2.com'
   FirstName='Bono'
   MiddleName=''
   LastName='Vox'
   ----- End Author -----
------ End Book ------


 <books pubdate="2009-05-20">
  <book price="45.99" title="Open Heart Surgery for Dummies">
    <id isbn10="4389880339"/>
    <authors>
      <author>
        <name>
          <first>Mortimer</first>
          <middle>Q.</middle>
          <last>Snerdly</last>
        </name>
        <email address="mort@surgery.com"/>
      </author>
    </authors>
  </book>
  <book price="32.75" title="Skydiving on a Budget">
    <id isbn="2129034454"/>
    <authors>
      <author>
        <name>
          <first>Trudy</first>
          <middle>L.</middle>
          <last>Freefall</last>
        </name>
        <email address="tfreefall@jump.com"/>
      </author>
      <author>
        <name>
          <first>Bernard</first>
          <middle>M.</middle>
          <last>Fallson</last>
        </name>
        <email address="bernie@airborne.com"/>
      </author>
    </authors>
  </book>
  <book price="22.40" title="How to Dismantle a Bomb">
    <authors>
      <author>
        <name>
          <first>Bono</first>
          <middle/>
          <last>Vox</last>
        </name>
        <email address="bono@u2.com"/>
      </author>
    </authors>
  </book>
</books>

 


Tags: ,
Categories: C# | CapTech
Posted by kevin on Friday, May 22, 2009 8:00 AM
Permalink | Comments (0) | Post RSSRSS comment feed

C#'s Dynamic Type is NOT Just an Object

Consider the following C# 4 code that creates a null dynamic field and a null object field, then attempts to invoke GetType() through each:

using System;

public class Program
{
    private dynamic i;
    private object j;
    public static void Main()
    {
        var app = new Program();
        try { Console.WriteLine(app.i.GetType()); }
        catch (Exception e)
        {
            Console.WriteLine("{0} says:\r\n\t{1}",
                e.GetType(), e.Message);
        }
        try { Console.WriteLine(app.j.GetType()); }
        catch (Exception e)
        {
            Console.WriteLine("{0} says:\r\n\t{1}",
                e.GetType(), e.Message);
        }
        Console.ReadLine();
    }
}

The console output of this small program is the following text:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException says:
        Cannot perform runtime binding on a null reference
System.NullReferenceException says:
        Object reference not set to an instance of an object.

Why the different treatment between objects and dynamics? After all, we hear all the time that the new dynamic type in C# 4 is really just an object with special runtime behaviors ascribed to it. But the difference in the exception types makes it clear that dynamic types are not plain, old object references. The IL for this code makes it very clear what's going on. I've included the disassembled IL for Main generated by the ILDASM tool below. You'll see that the dynamic field is really a CallSite object. The CallSite class does a lot of interesting things which I'll be blogging about now that the VS2010 Beta 1 is publicly available.

Even if you don't understand what the following code is doing, find the first try block in the code and compare it to the second one. You can see in the second try block that the access to the plain, old object field is very straightforward, just a couple of lines of code. Since the object reference is initialized to null, when the GetType() method is invoked through it, a NullReferenceException is thrown. Standard stuff since .NET 1.0. But in the first try block, where the dynamic field is used to invoke GetType(), the call is dispatched through a compile-time constructed CallSite. So, the CallSite reference is not null which is why we don't get a NullReferenceException. Instead, the CallSite attempts to bind to a real object to dispatch the call and finds that there is nothing there. Hence, the RuntimeBinderException. I think it's important to know that dynamics are not just objects with special runtime behaviors attached to them. I know the following IL code is long and ugly but do this: search in the following text for the word GetType in double quotes. Look at how that string is being passed to the runtime binder in the dynamic case. This is very much like using eval() in JavaScript to inject strings of code into the browser at runtime. C# 4 truly is a dynamic language now.

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       283 (0x11b)
  .maxstack  12
  .locals init ([0] class Program app,
           [1] class [mscorlib]System.Exception e,
           [2] class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo[] CS$0$0000)
  IL_0000:  nop
  IL_0001:  newobj     instance void Program::.ctor()
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  nop
    IL_0008:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,object>> Program/'<Main>o__SiteContainer0'::'<>p__Site1'
    IL_000d:  brtrue.s   IL_004e
    IL_000f:  ldc.i4.0

<snip/>

    IL_006c:  brtrue.s   IL_00a2
    IL_006e:  ldc.i4.0
    IL_006f:  ldstr      "GetType"
    IL_0074:  ldtoken    Program
    IL_0079:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
    IL_007e:  ldnull
    IL_007f:  ldc.i4.1
    IL_0080:  newarr     [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo

<snip/>

    IL_00df:  leave.s    IL_00e1
  }  // end handler
  IL_00e1:  nop
  .try
  {
    IL_00e2:  nop
    IL_00e3:  ldloc.0
    IL_00e4:  ldfld      object Program::j
    IL_00e9:  callvirt   instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
    IL_00ee:  call       void [mscorlib]System.Console::WriteLine(object)

<snip/>

  IL_0119:  pop
  IL_011a:  ret
} // end of method Program::Main


Tags:
Categories: C#
Posted by kevin on Thursday, May 21, 2009 7:16 AM
Permalink | Comments (7) | Post RSSRSS comment feed

Service Toggler Source Code

I'm very active in the User Group community so I do a lot of presentations. I wrote a quick and dirty application called ToggleService which lets me start or stop a Windows Service in a visual way. The picture above shows three screen shots side by side. On the left, you see my application as it queries the service called SQL Server (KATMAI) in the stopped state as indicated by the red light bulb. After clicking the Start button, the state transitions which shows the middle screen with the yellow light bulb. After a few seconds the service goes into the started state as indicated by the green light bulb on the right. I wrote this application to give my User Group attendees some visual feedback whenever I needed to start or stop a service during a presentation. It's very effective for that. So effective, in fact, that many people have asked me for the source code.

One important note: when you create a shortcut for this application, you must pass the long or short name of the service to ToggleService.exe on the command line. You can see the long service names in the Services Control Panel applet. In the case of the screen shot above, I found "SQL Server (KATMAI)" as the long name and passed it to the ToggleService.exe application on the command line. To find the short name of a service, you can use the command line service controller like this:

sc \\machineName GetKeyName "SQL Server (KATMAI)"

Of course, you must substitute your own machine name and the long name of the service that your querying for. This will produce output something like this:

C:\>sc \\machineName GetKeyName "SQL Server (KATMAI)"
[SC] GetServiceKeyName SUCCESS
Name = MSSQL$KATMAI

So, to toggle the SQL Server instance on my computer in which I'm interested, I could pass either of the following arguments to ToggleService.exe:

  • "SQL Server (KATMAI)"
  • MSSQL$KATMAI

You might observe at this point that the SC.EXE utility which I used to discover the short name of my service could have been used to start and stop the service during my presentations. Yes, that's true. But the little GUI I built is more colorful and exciting. You have to sell the sizzle and the steak, right? Anyway, the C# source code attached below requires Visual Studio 2008. There's nothing special about it but since so many people have asked for it, I thought I'd oblige. Enjoy!

Source code for Kevin Hazzard's ToggleService Utility (26.73 kb)


Tags:
Categories: C# | Fun | General | Presentation Skills
Posted by kevin on Sunday, May 17, 2009 10:05 PM
Permalink | Comments (1) | Post RSSRSS comment feed

JavaScript Object Notation (JSON) in .NET Part 4

Welcome to Part 4 of a multi-part series on JavaScript Object Notation (JSON) support in the Microsoft .NET Framework. In this article, we'll focus on the JavaScriptConverter class from the System.Web.Script.Serialization namespace. You can find the other parts of this series at these locations:

  • Part 1 - An exploration of the DataContractJsonSerializer class
  • Part 2 - An exploration of the JavaScriptSerializer class
  • Part 3 - JSON serialization from WCF (including a REST primer)
  • Part 4 - Using the JavaScriptConverter class to customize JSON serialization

Welcome back. We've been exploring the differences in .NET's two competing JSON serialization classes for a while now. This time, let's dig into ways that we can customize the JavaScriptSerializer to solve some difficult problems. In some circumstances, the services provided by the JavaScriptSerializer for dehydrating and rehydrating of POCOs just isn't sufficient. As discussed in Part 2 of this series, the JavaScriptSerializer has the interesting capability of handling plain .NET classes that aren't marked up with serialization-related metadata in any way. Most of the competing serialization and deserialization classes in the .NET Framework Class Library require some kind of meadata, typically in the form of attributes, to assist the serializer in doing it's job. And there's good reason for this. Sometimes, simply iterating over the properties and fields of an object doesn't provide enough information to properly put it into a format that's suitable for storage or for transmission. For example, look at the following class definition which uses two properties to expose a single DateTime object in different formats:

public class Redundant
{
    private DateTime _ts = DateTime.Now;

    public Redundant()
    {
        _ts = DateTime.Now;
    }

    public Redundant( DateTime ts )
    {
        _ts = ts;
    }

    public string AsRFC1123
    {
        // return the date in RFC 1123 format
        get { return _ts.ToString( "R" ); }
    }

    public string AsSortable
    {
        // return the date in a sortable format
        get { return _ts.ToString( "s" ); }
    }
}

When an instance of this class is serialized to JSON using the JavaScriptSerializer, it may look something like this:

{"AsRFC1123":"Sun, 17 May 2009 01:00:00 GMT","AsSortable":"2009-05-17T01:00:00"}

As you can see, the serializer decided to include both string properties, AsRFC1123 and AsSortable which is redundant. There's no need to include the DateTime information twice. However, the JavaScriptSerializer can't know what should and should not be serialized because the definition of the Redundant class has no markup to give it clues about what should be included. The JavaScriptSerializer doesn't depend on attributes as some other .NET serializers do. Instead, if you want to customize the serialization process when using the JavaScriptSerializer, you must provide an instance of a class derived from JavaScriptConverter. For the Redundant class, the following converter can be used to fix the problem:

private class RedundantConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        // register the Redundant type
        get { return new[] { typeof( Redundant ) }; }
    }

    public override IDictionary<string, object> Serialize(
        object obj, JavaScriptSerializer serializer )
    {
        // convert the object obj into a dictionary
        // of name value pairs
        var r = obj as Redundant;
        if (r == null) return null;
        var map = new Dictionary<string, object>();
        map["ts"] = r.AsSortable;
        return map;
    }

    public override object Deserialize(
        IDictionary<string, object> map,
        Type type, JavaScriptSerializer serializer )
    {
        // read the name value pairs in the
        // dictionary and rehydrate an instance
        DateTime ts;
        if (DateTime.TryParse( map["ts"].ToString(), out ts ))
            return new Redundant( ts );
        return null;
    }
}

First of all, notice that there are 3 members from the abstract base class that need to be overridden. These are:

  • IEnumerable<Type> SupportedTypes { get; }
  • IDictionary<string, object> Serialize( object obj, JavaScriptSerializer serializer );
  • object Deserialize( IDictionary<string, object> map, Type type, JavaScriptSerializer serializer );
The SupportedTypes property tell the serializer which types the converter supports. In this case, only the Redundant class is handled. The Serialize method accepts an instance of the invoking serializer and the object to be converted into JSON. However, the converter doesn't actually produce JSON output. Instead, the Serialize method on the converter must return a dictionary that maps strings, the names of the members, to objects, the actual objects that will be included. In the RedundantConverter class, you can see that were only including one property to be serialized named "ts". Remember, the whole point of attaching custom serialization is because the AsRFC1123 and AsSortable are redundant. We don't need both of them. And since, we'll only be including one of them (AsSortable), we took the opportunity to shorten the name to "ts". This will make the resulting JSON more compact which is almost always a good idea. The Deserialize method works in reverse, accepting a dictionary of name value pairs and constructing a new Redundant object from it. In this case, the Type parameter of the Deserialize method isn't used because this converter only assists with the Redundant type. However, if multiple types were converted by this class, you could include a switch statement to instantiate the appropriate type based on the Type parameter. Here's a bit of code that registers a RedundantConverter and tests the serialization and deserialization processes:

private static void JavaScriptConverterTests()
{
    var r = new Redundant();
    var jser = new JavaScriptSerializer();
    var rs = jser.Serialize( r );
    Console.WriteLine( "Redundant serialized with" +
        "out conversion support: '{0}'", rs );
    jser.RegisterConverters(
        new JavaScriptConverter[]
        {
            new RedundantConverter()
        } );
    rs = jser.Serialize( r );
    Console.WriteLine( "Redundant serialized with " +
        "conversion support: '{0}'", rs );
    r = jser.Deserialize<Redundant>( rs );
    Console.WriteLine("Redundant deserialized with " +
        "conversion support: AsRFC1123 = '{0}', " +
        "AsSortable = '{1}'", r.AsRFC1123,
        r.AsSortable );
}

The output of this code will look something like this:

Redundant serialized without conversion support:
"{"AsRFC1123":"Sun, 17 May 2009 01:00:00 GMT",
"AsSortable":"2009-05-17T01:06:21"}"

Redundant serialized with conversion support:
"{"ts":"2009-05-17T01:00:00"}"

Redundant deserialized with conversion support:
AsRFC1123 = "Sun, 17 May 2009 01:00:00 GMT",
AsSortable = "2009-05-17T01:00:00"

In closing, let me make one more key observation. Serialization requires that you can get the property values from an object. Deserialization requires that you can set the property values of an object. But notice that the Redundant class has no mutators (set handlers) on its properties. However, since we're doing custom conversion using the RedundantConverter class, that doesn't matter. The converter's Deserialize method simply uses a custom constructor to inject the DateTime value rather than using properties to do it. Yet another really cool thing that the JavaScriptSerializer can do that baffles the average competing serializer class.

That's all for now. Join me next time as we look at how to consume JSON-encoded content in a Silverlight control. Enjoy!


Categories: Architecture | C# | CapTech
Posted by kevin on Saturday, May 16, 2009 9:30 PM
Permalink | Comments (0) | Post RSSRSS comment feed

JavaScript Object Notation (JSON) in .NET Part 3

Welcome to Part 3 of a multi-part series on JavaScript Object Notation (JSON) support in the Microsoft .NET Framework. In this article, we'll focus on performing JSON serialization from a RESTful WCF web service. You can find the other parts of this series at these locations:

  • Part 1 - An exploration of the DataContractJsonSerializer class
  • Part 2 - An exploration of the JavaScriptSerializer class
  • Part 3 - JSON serialization from WCF (including a REST primer)
  • Part 4 - Using the JavaScriptConverter class to customize JSON serialization

Welcome back. In Part 1 of this series, we looked at using the DataContractJsonSerializer to dehydrate and rehydrate .NET classes to and from JavaScript Object Notation (JSON), respectively. In Part 2, we looked at the once rogue JavaScriptSerializer class which has the unique capability of being able to serialize Plain Old CLR Objects (POCO) that aren't marked as [Serializable] or [DataContract]. In this article, we'll focus on something a bit less academic: building a RESTful web service with Windows Communication Foundation (WCF) that delivers JSON encoded objects to its clients.

A Representational State Transfer (REST) Primer

Let's do a little rundown of what Representational State Transfer (REST) means. Like any architectural pattern, REST has some tenets or guidelines for describing what it hopes to accomplish and, in some sense, how it prefers for the work to be done. The REST principles1 for application development are:

  1. Application state and functionality are abstracted into resources
  2. Every resource is uniquely addressable using a universal syntax for use in hypermedia links
  3. All resources share a uniform interface for the transfer of state between client and resource, consisting of:
    • A constrained set of well-defined operations
    • A constrained set of content types, optionally supporting code on demand
  4. A protocol which is client-server, stateless, cacheable and layered

We don't need to cover all of these but there are a couple of high points to take note of. Most people interpret the phrase universal syntax in the second principle to mean that URLs are to be used to address application resources. And that's usually true. Here's the resource identifier for my Twitter.com timeline, for example:

    http://twitter.com/statuses/user_timeline/KevinHazzard.xml

If you click that link, you'll get an XML document that contains the state of my status updates to Twitter.com. The term for this kind of output is Plain Old XML or POX for short. If you change the extension of the resource identifier from xml to json in the URL shown above, what do you think you'll get? That's right. You'll see my Twitter.com timeline in JSON format. Pretty cool, huh? You can learn more about the RESTful Twitter Application Programming Interface (API) if you're interested.

The key word in that second principle is uniquely. What it means is that the resource identifier for the application state of my user timeline on Twitter.com must be different from all the other resource identifiers. Perhaps it's stating the obvious but from an addressing standpoint, REST tends to refer to application state and functionality like a file system. Bits of application state and the functions that an application performs are like a set of files. If you open a file by a well-known name, you'll get the functionality or state that's inside the file. This, of course, helps to define what the first and third REST principles mean, too. In the RESTful URL above, the well-defined operation is not KevinHazzard.xml. That's an argument or parameter, if you will. The operation is user_timeline and, reading left to right, you might guess that it's inside a module called statuses. It doesn't mean that the Ruby code that Twitter.com uses to implement the service is organized that way. But the resources in that class have a constraint that they use to provide a set of uniquely addressable resources.

The sub-bullets of the third REST principle are really interesting to me. One of the complaints about the Simple Object Access Protocol (SOAP) that some web services use is that it's much too rigid to be useful for web application development. Web developers complain that they don't have a Software Development Life Cycle (SDLC) that allows them to digest Web Service Description Language (WSDL) contracts, generate proxy classes and re-compile their code to use the well-defined operations and content types that a web service might provide. But I see through the compaints and the dissatisfaction with SOAP and the SDLC it engenders. The heart of the complaints really have more to do with the fact that great tools for building SOAP clients are rare. Case in point: over the years, I've demonstrated various ways to call SOAP services from environments that don't have great web service support built in. In an article I wrote about invoking SOAP web service from a dynamic language like Windows PowerShell, I demonstrated that WSDL contracts can be consumed at runtime to create and call proxies to SOAP services on the fly. To do that, I had to write a class called WSDLHelper that performs dynamic code generation. Not simple stuff but it works beautifully, making access to SOAP-based services just as easy as calling RESTful services from PowerShell or Python, for example. So, it's not that SOAP is bad, per se. But the tools to make SOAP client development aren't all that great, even in some .NET contexts.

Those sub-bullets of the third REST principle speak to the desire to constrain and define the operations and the data types that flow to and from the service. Without some contraints, the experience of using a RESTful service would be chaotic and unpredictable. Services like Twitter.com have very detailed definitions for their RESTful resources outlined in the Twitter API. It defines the resources (operation contracts), the parameters, the authentication mechanism and the output schema (data contracts) for each resource. Well, that's no different than what SOAP and WSDL are attempting to describe. The fundamental difference, though, is that SOAP and WSDL have rigid and quite rich XML schema definitions for all of that, not just the output of each resource. So, when people say that they dislike SOAP because it's too complex or bulky, look through the veil and understand that they really only dislike parsing WSDL, generating proxies, recompiling code, etc. It's OK to dislike those things, but now that you've read my blog, you understand that if better SOAP client tools existed on more platforms, it would often be preferred due to the richness and type safety that it can lend to the design process.

RESTful WCF

OK, enough about REST principles. Let's look at what it takes to expose a RESTful service in WCF. There are a handful of simple steps you can follow to do this. Assuming that you're going to be using Internet Information Server (IIS) to expose your service, follow these steps:

  1. Add a reference to System.ServiceModel.Web to your web application. This assembly includes the implementations of the WebServiceHostFactory and the WebGetAttribute that you'll be using in the next steps.
  2. In your Web.config file, modify an existing endpoint or add a new endpoint that uses the webHttpBinding binding type. This binding tells WCF that we're going to use HTTP URLs to parse resource identifiers and parameters. It also makes it possible to use RESTful response formats like POX or JSON instead of generating SOAP envelopes to go back to the client.
  3. In the SVC file for the WCF service, modify the <@ ServiceHost> element to include the attribute Factory="System.ServiceModel.Activation.WebServiceHostFactory". This factory class provides instances of the WebServiceHost class to handle the parsing of incoming RESTful URLs.
  4. The last thing you need to do is mark each [OperationContract] that you want to act as a REST resource with the [WebGetAttribute] or the [WebInvokeAttribute]. This is where we'll provide a template that maps incoming URLs to specific operations. These attributes also allow us to map parameters from the URLs to each operation's parameters.

Here's some example code and configuration for my ThingySearchService. Let's start with the [DataContract] and the [ServiceContract]:

using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;

[DataContract]
public class Thingy
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public int ID { get; set; }
    [DataMember]
    public int Age { get; set; }
}

[ServiceContract(Namespace = "gotnet.biz:JsonPlay")]
public interface IThingySearchService
{
    [OperationContract]
    [WebGet(UriTemplate = "FindThingy?age={age}&name={name}")]
    Thingy FindThingy(int age, string name);
}

First of all, notice that the [DataContract] attribute is explicitly applied to the Thingy class and that each property is marked with a [DataMember] attribute. The serializers used by WCF to render POX and JSON require this. You could alternatively mark the Thingy class with the [Serializable] attribute but as we saw in Part 1 of this series, the DataContractJsonSerializer often does a better job when the [DataContract] attribute is used instead. The UriTemplate of the [WebGet] attribute tells the WebHostFactory that when URLs referencing the FindThingy resource identifier are encountered, they should be routed here to the FindThingy operation. In addition, the UriTemplate instructs the WebHostFactory how to map the parameters in the URL to the underlying method's parameters. For my ThingySearchService, the following URL:

    http://localhost:51976/ThingySearch.svc/FindThingy?name=Kevin&age=44

might render this XML:


<Thingy xmlns="http://schemas.datacontract.org/2004/07/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

  <Age>44</Age>

  <ID>1682</ID>

  <Name>Kevin</Name>

</Thingy>

Considering the title of this article, you may be wondering why I've gone to so much trouble to produce POX from my RESTful service instead of JSON. Of course, the answer is that there's a nice story to tell here. To switch from a POX response format to a JSON format, you only need to modify the [WebGet] attribute on your [OperationContract] methods, adding a ResponseFormat parameter.

[ServiceContract(Namespace = "gotnet.biz:JsonPlay")]
public interface IThingySearchService
{
    [OperationContract]
    [WebGet(UriTemplate = "FindThingy?age={age}&name={name}",
        ResponseFormat = WebMessageFormat.Json)]
    Thingy FindThingy(int age, string name);
}

Now, when I invoke my ThingySearchService, I get a JSON-encoded string containing the text '{"Age":44,"ID":1682,"Name":"Kevin"}' which can be cleanly and quickly deserialized into an object on a variety of browsers and platforms. That was a roundabout way of showing you how to build REST/JSON web services with WCF. Hopefully you found the background information helpful. In the next segment, I'll be looking into how you can exercise finer control over the JSON serialization process.

Footnotes:
1
From http://en.wikipedia.org/wiki/REST

 


Categories: Architecture | C# | CapTech
Posted by kevin on Friday, May 08, 2009 7:00 AM
Permalink | Comments (0) | Post RSSRSS comment feed