Getting Started with the WCF REST Starter Kit Preview 2 HttpClient

Ingredients: Visual Studio 2008 SP1 (C#), WCF REST Starter Kit Preview 2

In Preview 1 of the WCF REST Starter Kit, Microsoft provided many useful tools for building RESTful services using WCF.  Missing from those bits was a clean way to call REST services from the client.  In Preview 2, which was released on March 13th, this has been made up for with the HttpClient class and an add-in for the Visual Studio IDE called Paste XML as Types.

The following getting-started tutorial will demonstrate how to use the HttpClient class to call a simple RESTful service (in fact, we will use the default implementation generated by the POX service template).  If you haven’t downloaded and installed the WCF REST Starter Kit, yet, you can get Preview 2 here. You can read more about the Starter Kit on Ron Jacobs’ site.

The sample solution will include two projects, one for the client and one for the service. 

1. Start by creating a Console Application project and solution called RESTfulClient.

2. Add a new project to the RESTfulClient solution using the Http Plain XML WCF Service project template that was installed when you installed the Starter Kit.  Call your new project POXService. 

The most obvious value-added features of the WCF REST Starter Kit are the various new project templates that are installed to make writing RESTful services easier.  Besides the Http Plain XML WCF Service template, we also get the ATOM Publishing Protocol WCF Service, the ATOM Feed WCF Service, REST Collection WCF Service, REST Singleton WCF Service and good ol’ WCF Service Application.

PoxService 

For this recipe, we will just use the default service as it is. 

[WebHelp(Comment = “Sample description for GetData”)]

[WebGet(UriTemplate = “GetData?param1={i}&param2={s}”)]

[OperationContract]

public SampleResponseBody GetData(int i, string s)

{

 

   return new SampleResponseBody()

   {

     Value = String.Format(“Sample GetData response:”   {0}’, ‘{1}'”, i, s)

   };

}

For the most part, this is a pretty straightforward WCF Service Method.  There are some interesting additional elements, however, which are required to make the service REST-y.

(In a major break with convention, you will notice that the default service created by this template is called Service rather than Service1.  I, for one, welcome this change from our new insect overlords.)

The WebGet attribute, for instance, allows us to turn our service method into a REST resource accessed using the GET method.  The UriTemplate attribute parameter specifies the partial Uri for our resource, in this case GetData.  We also specify in the UriTemplate how parameters can be passed to our resource.  In this case, we will be using a query string to pass two parameters, param1 and param2.

By default, the template provides a Help resource for our service, accessed by going to http://localhost:<port>/Service.svc/Help .  It will automatically include a description of the structure of our service.  The WebHelp attribute allows us to add further notes about the GetData resource to the Help resource.

You will also notice that the GetData service method returns a SampleResponseBody object.  This is intended to make it explicit in our design that we are not making RPC’s.  Instead, we are receiving and returning messages (or documents, if you prefer).  In this case, the message we return is simply the serialized version of SimpleResponseBody, which is a custom type that is specified in the service.svc.cs file and which does not inherit from any other type.

public class SampleResponseBody
{
    public string Value { get; set; }
}

3. Right click on the PoxService project and select Debug | Start New Instance to see what our RESTful service looks like.  To see what the service does, you can browse to http://localhost:<port>/Service.svc/Help .  To see what the schema for our GetData resouce looks like, go to http://localhost:<port>/Service.svc/help/GetData/response/schema .  Finally, if you want to go ahead and call the GetData service, browse to http://localhost:<port>/Service.svc/GetData .

(In the rest of this tutorial, I will simply use  port 1300, with the understanding that you can specify your own port in the code.  By default, Visual Studio will randomly pick a port for you.  If you want to specify a particular port, however, you can go into the project properties of the PoxService project and select a specific port in the project properties Web tab.)

<SampleResponseBody xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Value>Sample GetData response: '0', ''</Value> 
</SampleResponseBody>

4. Go to the RESTfulClient project and add a new class called SampleResponseBody.  We are going to create a type for deserializing our SampleResponseBody XML element.  We could write out the class by hand, and prior to Preview 2 we probably would have had to.  It is no longer necessary, however.  If you copy the XML returned from browsing our resource (you may need to use View Source in your browser to get a clean representation) at http://localhost:1300/Service.svc/GetData you can simply paste this into our SampleResponseBody.cs file by going to the Visual Studio Edit menu and selecting Paste XML to Types.  To get all the necessary types in one blow, you can also go to http://localhost:1300/Service.svc/Help and use Paste XML to Types.  As a third alternative, just copy the XML above and try Paste XML to Types in your SampleResponseBody class.  However you decide to do it, you are now in a position to translate XML into CLR types.

Your generated class should look like this:

[System.CodeDom.Compiler.GeneratedCodeAttribute(“System.Xml”, “2.0.50727.3053”)]

[System.Diagnostics.DebuggerStepThroughAttribute()]

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]

[System.Xml.Serialization.XmlRootAttribute(Namespace = “”, IsNullable = false)]

public partial class SampleResponseBody

{

 

        private string valueField;

 

        /// <remarks/>

        public string Value

        {

            get

            {

                return this.valueField;

            }

            set

            {

                this.valueField = value;

            }

        }

}

 

5.  Next, we need to add the Starter Kit assemblies to our console application.  The default location for these assemblies is C:\Program Files\Microsoft WCF REST\WCF REST Starter Kit Preview 2\Assemblies .  The two assemblies we need for the client are Microsoft.Http.dll and Microsoft.Http.Extensions.dll .  (I happen to like to copy CodePlex bits like these into a folder in the My Documents\Visual Studio 2008 directory, to make it relatively easier to track drop versions).

6. We will now finally add some code to call call our GetData resource using the HttpClient class.  The following code will simply prompt the user to hit {Enter} to call the resource.  It will then return the deserialized message from the resource and prompt the user to hit {Enter} again.  Add the following using references to your Program.cs file:

using Microsoft.Http;

using System.Xml.Serialization;

  Now place the following code in the Main() method of Program.cs:

static void Main(string[] args)

{

    Console.WriteLine(“Press {enter} to call service:”);

    Console.ReadLine();

 

    var client = new HttpClient(http://localhost:1300/Service.svc/);

    HttpResponseMessage response = client.Get(“GetData”);

 

    var b = response.Content.ReadAsXmlSerializable<SampleResponseBody>();

 

    Console.WriteLine(b.Value);

    Console.ReadLine();

}

Both the Get request and the deserialization are simple.  We pass a base address for our service to the HttpClient constructor.  We then call the HttpClient’s Get method and pass the path to the resource we want (in true REST idiom, PUT, DELETE and POST are some additional methods on HttpClient).

The deserialization, in turn, only requires one line of code.  We call the Content property of the HttpResponseMessage instance returned by Get() to retrieve an HttpContent instance, then call its generic ReadAsXmlSerializable method to deserialize the XML message into our SampleResponseBody type.

While you could previously do this using WCF and deserialization, or even the HttpWebRequest and HttpWebResponse types and an XML parser, this is significantly easier.

 

console1

 

7. If you recall, the signature of the GetData service method actually takes two parameters, an integer and a string.  When translated into a REST resource, the parameters are passed in a query string.  To complete this example, we might want to go ahead and pass these parameters to our GetData resource.  To do so, replace the code above with the following:

static void Main(string[] args)

{

    Console.WriteLine(“Enter a number:”);

    int myInt;

    Int32.TryParse(Console.ReadLine(), out myInt);

 

    Console.WriteLine(“Enter a string:”);

    var myString = Console.ReadLine();

 

    var q = new HttpQueryString();

    q.Add(“param1”, myInt.ToString());

    q.Add(“param2”, myString);

 

    var client = new HttpClient(“http://localhost:1300/Service.svc/”);

    HttpResponseMessage response = client.Get(new Uri(client.BaseAddress + “GetData”), q);

    var b = response.Content.ReadAsXmlSerializable<SampleResponseBody>();

 

    Console.WriteLine(b.Value);

    Console.WriteLine(“Press {enter} to end.”);

    Console.ReadLine();

}

The first block asks for a number and we verify that a number was indeed submitted.  The next block requests a string.

The third block creates an HttpQueryString instance using our console inputs.

The important code is in the fourth block.  You will notice that we use a different overload for the Get method this time.  It turns out that the only overload that accepts a query string requires a Uri for its first parameter rather than a partial Uri string.  To keep things simple, I’ve simply concatenated “GetData” with the BaseAddress we previously passed in the constructor (this does not overwrite the BaseAddress, in case you were wondering).  We could have also simply performed a string concatenation like this, of course:

HttpResponseMessage response =

client.Get(string.Format(“GetData?param1={0}&param2={1}”,myInt.ToString(), myString));

but using the HttpQueryString type strikes me as being somewhat cleaner. 

If you run the console app now, it should look something like this:

console2

 

And that’s how we do RESTful WCF as of Friday, March 13th, 2009. 

To see how we used to do it prior to March 13th, please see this excellent blog post by Pedram Rezai from April of last year.

 

 



			

All rational people will agree …

squareOfOposition

In the Critique of Pure Reason, Immanuel Kant argues that moral actions are the actions of an autonomous will, and that an autonomous will is a will that is determined by reason alone.  Moral actions, additionally, follow the form of being universalizable, hence Kant finds in rationality a confirmation of the Golden Rule: when you do unto others as you would have them do unto you, you are behaving in a manner that can be universalized for all mankind.

In the years following Kant’s death, the notion that all rational people, when they are being rational, will consistently agree with certain propositions has fallen somewhat into disfavor.  This has reached the point that Habermas, perhaps one of the last post-modern defenders of some form of Kantian morality, argues that while it was presumptuous for Kant to make claims about what rationality looks like, we should still work towards some sort of ideal speech community which removes all biases and personal ambitions from the process of communication; this would de facto be the closest thing we can get to our ideal of pure reason, at which point we let them tell us what all rational people ought to believe.

And so you will not often see the phrase ‘all rational people agree’ in print much, these days, though back-in-the-day it was a commonplace.  Still, old habits die hard, and in its place we often find the phrase ‘most people agree’ in its place, with the implication that the “most people” we are talking about are the “rational people.”

I was recently trying to find a good article on Dependency Injection for a colleague and came across this one on MSDN, which unfortunately begins:

“Few would disagree that striving for a loosely coupled design is a bad thing.”

I assume that the author originally intended to say “Most would agree that striving for a loosely coupled design is a good thing.”   He then attempted to negate the statement for emphasis, but managed to over-negate, and failed to see that “few would disagree” is the apposite of “many would agree”, rather than its opposite.

In fact someone mentioned this to the author on his personal blog, but the author averred that this was just a Canadianism and not actually a mistake.

Be that as it may, it recalls a problem with logical quantifiers and natural language.  In the classic square of opposition (which sounds like a perverse political system but is simply a diagram that explains the complex relationship between universal propositions and existential ones) we are reminded that while universal affirmative propositions are contrary to universal negations, they are not contradictory.

If an A proposition, for instance ‘All rational people agree that X’, is true, then the contrary E proposition, ‘No rational people agree that X’ must necessarily be false, and vice-versa.  However, these are not contradictory propositions since both can actually be false.

The contradiction of A is the existential proposition (O), ‘Some rational people don’t agree that X’, just as the contradiction of E is I, ‘Some rational people agree that X.’  If A is false, then O is necessarily true; if O is false, then A is true; and either A or O must be true.

What cannot be easily resolved into logical formalism are the grammatical quantifiers ‘many’ and ‘few’.   Are ‘many’ and ‘few’ contradictory or merely contrary (or, God forbid, even subcontrary)?

What we can all agree on is the fact that english idioms are sometimes difficult to work with, and that this is particularly true when we attempt to formulate complex relationships between quantifiers.  Take, for instance, Abraham Lincoln’s famous epigram (which he possibly never uttered):

You can fool all of the people some of the time, and you can fool some of the people all of the time, but you can’t fool all of the people all the time.

I actually have trouble understanding the logic of this argument, and take exception with the first and second premises for the same reason that I take exception with statements about what all rational people agree on.  However I find myself so in agreement with the conclusion, as most people do, that I tend to overlook the manner in which we arrive at it.

Or take this one, from Tolkien’s novel:

I don’t know half of you half as well as I should like; and I like less than half of you half as well as you deserve.

It simply cannot be formalized into first-order logic.  Yet, remarkably, we manage to understand it — or at least most of us do.

In the movie Shrek the Third, there is this exchange, which plays on the difficulties of universal negation (O propositions brought to you by IMDB):

Prince Charming: You! You can’t lie! So tell me puppet… where… is… Shrek?
Pinocchio: Uh. Hmm, well, uh, I don’t know where he’s not
Prince Charming: You’re telling me you don’t know where Shrek is?
Pinocchio: It wouldn’t be inaccurate to assume that I couldn’t exactly not say that it is or isn’t almost partially incorrect.
Prince Charming: So you do know where he is!
Pinocchio: On the contrary. I’m possibly more or less not definitely rejecting the idea that in no way with any amount of uncertainty that I undeniably
Prince Charming: Stop it!
Pinocchio: …do or do not know where he shouldn’t probably be, if that indeed wasn’t where he isn’t. Even if he wasn’t at where I knew he was
[Pigs and Gingerbread Man begin singing]
Pinocchio: That’d mean I’d really have to know where he wasn’t.

In California, for safety reasons, the following law is apparently on the books:

The law says that nothing “shall be so designed and installed that it cannot, even in cases of failure, impede or prevent emergency use of such exit.”

H. L. Mencken provides several canonical examples of double negation in his book The American Language in order to demonstrate that it was once more common and better accepted, especially when English was closer to it’s inflected roots.  Thus Chaucer writes in The Knight’s Tale:

He nevere yet no vileynye ne sayde
In al his lyf unto no maner wight.

Shakespeare was no sloucher, neither, and Mencken cites several examples:

In “Richard III” one finds “I never was nor never will be”; in “Measure for Measure,” “harp not on that nor do not banish treason,” and in “Romeo and Juliet,” “thou expectedst not, nor I looked not for.”

At the same time, Shakespeare was also a genius at presenting universal negation in a manner fit to please Hegel when the Prince of Denmark soliloquizes:

To be, or not to be

while in King Lear,  in turn, the Bard’s use of universal affirmation is so fitting that any reasonable person would acknowledge it:

All the world’s a stage,
And all the men and women merely players:
They have their exits and their entrances;

RESTful WCF at Atlanta Code Camp

gullivers_travels

This past Saturday was the Atlanta Code Camp.  I want to be make a point of thanking Cliff Jacobson, Dan Attis, Doug Ware, Glen Gordon, Jeff Ammons and all the other organizers who made this a brilliant event.

My company, Magenic Technologies, presented at seven of the sessions this year. 

Sergey Barskiy, who was a developer on the CSLA-Lite team, presented on Building Silverlight Business Applications using CSLA.NET for Silverlight.

Whitney Weaver, another of our principal consultants and a master of all things data, spoke on What’s my data doing while I sleep? Tracking data changes in SQL Server 2008.

Colin Whitlatch presented an Introduction to ASP.NET MVC, and is planning to extend his presentation over the next few weeks on his blog, where he will be digging deep into ASP.NET MVC and helping others to do the same.

Jason Rainwater needs a blog, because he is currently one of the best WPF experts in Atlanta and there aren’t enough venues at this point for him to show off everything he knows.  He did two presentations this year: WPF Custom Controls and WPF DataBinding.

I presented on REST-ful WCF (the hyphen is a personal grammatical quirk rather than any attempt to make a philosophical point) and Mocking with Rhino Mocks and TypeMock: A Head-to-head Comparison.  I also got to make a short app-dev appearance in Tejas Patel’s Use of data mining controls with ASP.NET presentation.

As promised to the attendees, I’m making the code samples and slide-decks available.  Please excuse the lack of organization in the code — it’s pretty much just what I was writing while I was on-stage, but should be helpful if anyone is looking for samples.  All the code uses Visual Studio 2008.  The mocking samples will require that you have the appropriate dll’s for Rhino Mocks, which is free,  and TypeMock Isolator, which has a 30-day trial.

I am indebted to Pedram Rezaei for getting me started on the WCF-to-Flikr sample.

The Rest-ful WCF slide-deck and code can be downloaded here.

The Mocking powerpoint and samples are available here.

On Culture

My wife and I performed a small experiment this weekend when we took our three children to the symphony.  According to Steven D. Levitt and Stephen J. Dubner’s book, Freakonomics, children who are taken to concerts and art museums are not statistically advantaged by this activity.  However, in an interesting twist on the theological debate between justification by faith and justification by works, the authors claim that children who are parented by the sort of people who take their progeny to cultural events and fill their homes with books are indeed statistically advantaged.  Taking this to mean that good intentions are at least of equal value to good works (and what more can you ask of the parents of three children), we exercised our good intentions at the ASO’s performance with Jennifer Koh.

Sasha, the oldest (10), found the whole performance to be a waste of time.  Paul (8) and Sophia (6) were quite taken with Wagner’s Liebestod from Tristan and Isolde.  They found Jennifer Higdon’s The Singing Rooms to be considerably more challenging, however, as did their father. 

Ms. Koh’s performance was magnificent, of course, but the center of attraction for us was the Stradivarius on which she played.  I’ve never heard one live before.  Paul kept asking why it was so special and all I could think to say was that the ex-General Dupont is almost three hundred years old.  This duly impressed my son.  What speaks more on culture’s behalf, after all, than it’s gray-haired hoariness.

Perhaps it is an indication of my low-tastes, but as I watched this performance I kept thinking about how much I enjoyed the last performance I had seen at Atlanta Symphony Hall, Cirque de la Symphonie.  The music at that concert tended towards the romantic, from Saint-Saëns to Ravel.  While the orchestra performed on their instruments, the acrobats plied their art on their bodies by defying gravity in the air as well as defying basic physiology through acts of contortion.  Two acts stood out especially. 

Jaroslaw Marciniak and Dariusz Wronski entered the stage bald, in loin-cloths, and painted gold from head to toe.  They proceeded to lift, pin and balance off of each other in what I took to be an extended demonstration of Euclid’s 47th proposition, with each brief suspension being a prelude to the final revelation. 

Even more impressive was Elena Tsarkova’s contortion and balancing act.  All of it was remarkable, but at one point she stood on her head with her legs extended upward.  She then spread her legs out to be almost perfectly perpendicular to the rest of her body.  At this point something uncanny happened, but so quickly that I had to ask my wife if she had just seen something.  We couldn’t quite put words to what we had witnessed, and the best I could come up with was “ululation”.  There was an ululation in her legs which looked like the small wave some people can make with their shoulders.  It was breathtaking.

Following the Higdon performance came the intermission.  We took advantage of this natural break to sneak out and hunt for a decent milkshake in Atlanta.  The kids had earned it.  They behaved extremely well at the symphony.

Not a User Error: Moving my DasBlog directory

If your rss feed reader just went crazy over my site, I apologize.  I recently moved my blog from the application root to a subdirectory in order to allow other .NET applications to run properly in other subdirectories.

In order to make the imaginativeuniversal site still work with searches that expect to find content at the old location, I had to create an HttpHandler to redirect page requests to the “/blog” subdirectory, including requests for the rss feed.  This had some unintended results, such as republishing all the old rss entries.

This was a migration of a DasBlog application to another directory.  Should anyone be interested, this is how I wrote the HttpHandler CategoryHandler to redirect all requests to the root to my “/blog” subdirectory:

using System;

using System.Web;

using System.Web.UI;

 

namespace IUHandlers

{

    public class CategoryHandler : IHttpHandler

    {

 

        public bool IsReusable

        {

            get { return true; }

        }

 

        public void ProcessRequest(HttpContext context)

        {

            string path = context.Request.Path;

            string syndicationPath = “/SyndicationService.asmx”;

            if (path.IndexOf(“/blog”) == -1)

            {

 

                int lastSlash = path.LastIndexOf(‘/’);

                string pre = path.Substring(0, lastSlash);

                string post = path.Substring(lastSlash);

                if (path.IndexOf(syndicationPath

                    ,StringComparison.CurrentCultureIgnoreCase) > -1)

                {

                    post = syndicationPath + post;

                }

                context.Response.Redirect(“~/blog” + post);

            }

        }

    }

}

I compiled my handler and placed it in the bin folder at the root of my site.  I then added a web.config file to the root with this setting:

<httpHandlers>

      <add verb=GET path=*.asmx type=IUHandlers.CategoryHandler, IUHandlers/>

      <add verb=GET path=*.aspx type=IUHandlers.CategoryHandler, IUHandlers/>

This allows me to run other ASP.NET applications beneath the root directory of my site as long as I remember to add the following two settings to each of their web.config files:

    <httpHandlers>

      <remove verb=GET path=*.asmx/>

      <remove verb=GET path=*.aspx/>

I’m not sure if it’s the most elegant solution, but it seemed to do the job.

Haecceity

porphyrianTree

Out of the Medieval intellectual battles between Realists and Nominalists, one of the more interesting fruits to fall was Duns Scotus’s notion of Haecceity (this-ness), which in modern philosophy is often reformulated as a person’s essence.  Possibly against a straw-man, Scotus argued that those who sought after the principle of Quiddity (what-ness) were misguided.  The truly interesting question is not how quiddity is possible, but rather how the individuation of universals is possible.  In other words, rather than look into how we know that Socrates is a man, we should examine how the concept of ‘man’ can be broken up in such a way that gives us a Socrates.

Another way of looking at this is in terms of Porphyry’s tree.  Each genus can be divided by a differentia into species.  For instance a Substance can be either be extended or not.  If it is, then it is a a Body.  A Body can be animate or not and if so it is an Animal.  An Animal, if rational, is in turn a Human Being.  But what is the differentia that produces an individual like Plato or Socrates?

For Scotus, this differentia is a person’s haecceity.   An interesting marginal note to a person’s haecceity is that we cannot have a adequate word for a person’s this-ness.  Words fail.  The only clear way to indicate haecceity is by extending one’s finger and pointing.  Saying “this guy” tells us nothing unless we accompany the words with a gesture to represent ‘this guy’s’ haecceity.

My haecceity for the week includes unexpectedly finding out that I passed a Microsoft certification exam.  I had taken Designing and Developing Enterprise Applications using Microsoft .NET Framework 3.5 (exam 565 for short) back in November and had forgotten about it until I received notice a week ago that I had actually passed it.

Then last Thursday I did an internal presentation for Magenic on the new Prism V2 framework.  This was rather fun, thanks to my colleagues Sergey Barskiy, Colin Whitlatch, Tim Price-Williams and Wells Caughey, who helped me start taking the technology apart.

On Friday I received a request to do a brief presentation for the MS Pro’s user group.  I took the short notice as license to do something a bit off beat and ended up presenting on “The Medieval Problem of Universals and Object-Oriented Programming.”  The audience was remarkably gracious about the whole thing.   For me it was a perfect evening which started with lunch at the bar of Pappadeux with Wally McClure, the host of the ASP.NET podcast, over martinis and oysters and ended with presenting on, all things considered, a slightly mad and rather dry topic — the kind I learned to love in grad school.

The 3rd of March, furthermore, marks one year since the wonderful Carole Cuthbertson formally offered me a job with Magenic Technologies.  It is without a doubt the best job I’ve ever had.

Finally, what has two thumbs and a birthday today?

This guy.

Playing with the Kindle 2’s Web Browser

small_browser

I have been spending the day trying to upload PDF’s from my safaribooksonline account to my Kindle, so far without much success.  Mobipocket Creator, which is recommended for converting various file formats to the Mobi format used by the Kindle, seems to get mixed up over the images.  I am currently trying to see if Amazon.com’s converter handles them any better.

On the other hand, I’ve found that the new http://m.safaribooksonline.com site works fairly well on the Kindle’s simplified browser (though not perfectly).  I can access my bookshelf and browse through my books.

The Basic Web browser seems very well suited for twittering, though. You can access your twitter account on the Kindle by going through http://m.twitter.com

To access the Basic Web browser on the Kindle, click on the Menu button from your home page.  Then select Experimental.  From the Experimental page, you will be able to start the Basic Web browser, which lets you search google, search Wikipedia, or simply browse to a url.

Also, contrary to my expectations, the Text-to-Speech feature on the Kindle 2 is actually rather good.  It even attempts to modify intonation based on the sentence structure.  Still not up to Morgan Freeman standards, however.

The Lees and Scum of Bygone Men

 

chinese_book

The following is a parable about the difference between theory and practice, which Michael Oakeshott frames as the difference between technical and practical knowledge, found as a footnote in Michael Oakeshott’s essay Rationalism In Politics.  I find that it has some bearing, which I will discuss in the near future, to certain Internet debates about pedagogy and software programming:

Duke Huan of Ch’i was reading a book at the upper end of the hall; the wheelwright was making a wheel at the lower end.  Putting aside his mallet and chisel, he called to the Duke and asked him what book he was reading.  ‘One that records the words of the Sages,’ answered the Duke.  ‘Are those Sages alive?’ asked the wheelwright.  ‘Oh, no,’ said the Duke, ‘they are dead.’  ‘In that case,’ said the wheelwright, ‘what you are reading can be nothing but the lees and scum of bygone men.’  ‘How dare you, a wheelwright, find fault with the book I am reading.  If you can explain your statement, I will let it pass.  If not, you shall die.’  ‘Speaking as a wheelwright,’ he replied, ‘I look at the matter in this way; when I am making a wheel, if my stroke is too slow, then it bites deep but is not steady; if my stroke is too fast, then it is steady, but it does not go deep.  The right pace, neither slow nor fast, cannot get into the hand unless it comes from the heart.  It is a thing that cannot be put into rules; there is an art in it that I cannot explain to my son.  That is why it is impossible for me to let him take over my work, and here I am at the age of seventy still making wheels.  In my opinion it must have been the same with the men of old.  All that was worth handing on, died with them; the rest, they put in their books.  That is why I said that what you were reading was the lees and scum of bygone men.'”

Chuang Tzu

Finding the correct metaphor for text-to-speech

medspeech

A recent release from the Associated Press concerning the Authors Guild’s concerns with the Kindle 2’s text-to-speech feature left many computer programmers guffawing, but it occurs to me that for those not familiar with text-to-speech technology, the humorous implications may not be self-evident, so I will attempt to parse it:

“NEW YORK (AP) — The guild that represents authors is urging writers to be wary of a text-to-speech feature on Amazon.com Inc.’s updated Kindle electronic reading device.

 

“In a memo sent to members Thursday, the guild says the Kindle 2’s “Read to Me” feature “presents a significant challenge to the publishing industry.”

 

“The Kindle can read text in a somewhat stilted electronic voice. But the Authors Guild says the quality figures to “improve rapidly.” And the guild worries that could undermine the market for audio books.”

The quality of text-to-speech depends on the library of phonemes available on the reading device and the algorithms used to put them all together.  A simple example is when you call the operator and an automated voice reads back a phone number to you with a completely unnatural intonation, and you realize that the pronunciation of each number has been clipped and then taped back together without any sort of context.  That is a case, moreover, where the relationship between vocalization and semantics is one-to-one.  The semantic meaning of the number “1” is always mapped to the sound of someone pronouncing the word “one”.   In the case of speech-to-text, no one has been sitting with the OED and carefully pronouncing every word for a similar one-to-one mapping. Instead, the software program on the reading device must use an algorithm to guess at the set of phonemes that are intended by a collection of letters and generate the sounds it associates with those phonemes. 

 

The problem of intonation is still there, along with the additional issue of the peculiarities of English spelling.  If have a GPS system in your car, then you are familiar with the results.  Bear in mind that your GPS system, in turn, is bungling up what is actually a very particularized vocabulary.  The books that the Kindle’s “Read to Me” feature will be dealing with have more in common with Borges’s labyrinth than Rand McNally’s road atlas.

 

While text-to-speech technology will indeed improve over time, it won’t be improving in the Kindle 2, which comes with one software bundle that reads in just one way.  I worked on a text-to-speech program a while back (if you have Vista, you can download it here) that combines an Eliza engine with the Vista operating system’s text-to-speech functionality.  One of the things I immediately wanted to do was to be able to switch out voices, and what I quickly found out was that I couldn’t get any new voices.  Vista came with a feminine voice with an American accent, and that was about it unless one wanted to use a feminine voice with a Pidgin-English accent that is included with the Chinese speech pack.  The only masculine voice Microsoft provided was available for Windows XP, and it wasn’t forward compatible. 

 

It simply isn’t easy to switch out voices, much less switch out speech engines on a given platform, and seeing that we aren’t paying for a software package when we buy the Kindle but rather only the device (with much less power than a Microsoft operation system), it can be said with some confidence that the Kindle 2 is never going to be able to read like Morgan Freeman.

 

The Kindle 2’s text-to-speech capabilities, or lack of it, is not going to undermine the market for audio books any more than public lectures by Stephen Hawking will undermine sales of his books.  They are simply different things.

“It is telling authors and publishers to consider asking Amazon to disable the audio function on e-books it licenses.”

This is what is commonly referred to as the business requirement from hell.  It assumes that something is easy out of a serious misunderstanding of how a given technology actually works.  Text-to-speech technology is not based on anything inherent to the books Amazon is trying to peddle.  It isn’t, for what this is worth, even associated with metadata about the books Amazon is trying to peddle.  Instead, it is a free-roaming program that will attempt to read any text you feed it.  Rather than a CD that is sold with the book, it has a greater similarity to a homunculus living inside your computer and reading everything out loud to you. 

 

The proposal from the Authors Guild assumes that something must be taken off of the e-books in order to disable the text-to-speech feature.  In fact, instructions not to read those certain e-books must be added to the e-book metadata, and each Kindle 2 homunculus must in turn be taught to look for those instructions and act accordingly, in order to fulfill this requirement.  This is a non-trivial rewrite of the underlying Kindle software as well as of the thousands of e-book images that Amazon will be selling — nor can the files already living on people’s devices be recalled to add the additional metadata.

“Amazon spokesman Drew Herdener said the company has the proper license for the text-to-speech function, which comes from Nuance Communications Inc.”

This is just a legalese on Amazon’s part that intentionally misunderstands the Authors Guild’s concerns as well as the legal issues involved.  The Authors Guild isn’t accusing Amazon of not having rights to the text-to-speech software.  They are asking whether using text-to-speech on their works doesn’t violate pre-existing law. 

 

The answer to that, in turn, concerns metaphors, as many legal matters ultimately do.  What metaphor does text-to-speech fall under?  Is it like a CD of a reading of a book, which generates additional income from an author’s labor?  Or is it like hiring Morgan Freeman to read Dianetics to you?  In which case, beyond the price of the physical book, Mr. Freeman should certainly be paid, but the Church of Scientology should not.

Second prize is a set of steak knives

 

According to rumor, Alec Baldwin ad-libbed this scene for the movie adaptation of David Mamet’s Glengarry Glen Ross, although I’ve also heard that Mamet created the monologue especially for Baldwin’s character, Blake, who does not appear in the original Pulitzer Prize winning play.  A transcription of the monologue can be found here

Blake strikes me as the ur-Father of Freud’s Civilization and Its Discontents, speaking to the id-driven sales force.  In good times, Blake comes across as a parody of all bad managers with his A-B-C rules — he is Stephen Covey’s evil twin.   In a bad business climate, however, he is the bearer of profound Hobbesean truths, and one feels obliged to internalize him and let him whisper in the back of one’s mind, for his is the voice that drives industry.