Silverlight 2.0 + OOXML = TextGlow

Let us all bask in television's warm glowing warming glow. Over the last couple of months I have had the opportunity to work on an exciting project called TextGlow.

TextGlow is a Silverlight 2.0 application for viewing Word 2007 documents on the Internet. With TextGlow it is possible to instantly view a document within a web page, with no Microsoft Office applications installed. Since Silverlight is cross platform the user doesn't even have to be running Windows!

How it Works

See those blue and silver guys, Maggie? They're the Dallas Cowboys. They're Daddy's favorite team, and he wants them to lose by at least three points. The first step to TextGlow displaying a document is going out and downloading it. TextGlow is a Silverlight application and runs completely client side, and that means it needs a local copy to work with. This process happens automatically using the new WebClient class in Silverlight 2.0. Like you would expect from a class called WebClient it provides simple web request, but what makes WebClient great are the download progress events it provides. Making a progress bar to show the status of a download is a snap.

Next the various files inside the document are extracted. An OOXML document (docx) is actually just a zip file containing XML and other resource files, such as any images that might appear in the document. Fortunately Silverlight has built in zip file support using the Application.GetResourceStream method.

I bent my Wookie.Now that TextGlow has the OOXML it parses the XML and builds an object model of the document. To parse the XML I used LINQ to XML, which is new in Silverlight 2.0. After an initial learning curve (mainly suppressing the memory of many years of working with horrible DOM APIs [;)]), I found LINQ to XML to be wonderful to work with. I blogged about a couple of the cool features I discovered while working with LINQ to XML along the way.

Using the object model of the document TextGlow then creates WPF controls to display the content. Writing custom Silverlight WPF controls to render the content was definitely the hardest aspect of the project. When I started work on it with the Silverlight 1.1 Alpha there were no layout controls like StackPanel or Grid. Everything was absolutely position and I had to write my own flow layout controls. Paragraphs and complex flowing text was also surprisingly difficult to get right in Silverlight. Fortunatly Silverlight 2.0 includes controls like these and makes writing an application like TextGlow much easier.

The final step in display a document is simply WPF plying its magic and rendering the WPF controls. The user now has the Word 2007 document render on their screen using nothing but the power of Silverlight.

Thanks to...

TextGlow has be a great application to work on and it was awesome being able to design and build my own idea.

Thanks to Nas for mocking up the UI. If the UI was left up to me TextGlow would make Notepad look good [;)]

Big thanks to Chris Auld for providing a launch pad for the idea and then providing regular injections of enthusiasm into the project.

 

If you're interested in seeing more of TextGlow, visit www.textglow.com

kick it on DotNetKicks.com

Update:

TextGlow Open Sourced

Json.NET 2.0 Beta 2

I am really happy with how Json.NET 2.0 and LINQ to JSON is turning out. This release offers big improvements both in the syntax for writing JSON and querying JSON. I have also finally put in some real effort into fixing up some the niggling issues from previous versions of Json.NET.

Creating JSON Improvements

One of the suggestions I received from the first 2.0 beta was creating JSON objects from anonymous objects.

With LINQ to JSON it is now possible to do this:

JObject o = JObject.FromObject(new
{
  channel = new 
  {
    title = "James Newton-King",
    link = "http://james.newtonking.com",
    description = "James Newton-King's blog.",
    item =
        from p in posts
        orderby p.Title
        select new
        {
          title = p.Title,
          description = p.Description,
          link = p.Link,
          category = p.Categories
        }
  }
});

Pretty neat. Using regular .NET objects is also possible.

The way it works is FromObject is just a wrapper over the JsonSerializer class and reuses its logic. The difference compared to regular serialization is that the serializer is writing to a JsonTokenWriter instead of a JsonTextWriter. These classes are both new in this release and inherit from the now abstract JsonWriter.

I think it is really cool the way LINQ to JSON, JsonWriter and JsonSerializer dovetail together here. Once JsonWriter had been split apart and I could plug in different JsonWriters into JsonSerializer depending upon what output I wanted, adding this feature took no time at all [:)]

Querying JSON Improvements

I felt the querying API in beta 1 was too wordy and explicit. Beta 2's is more concise and it should hopefully be easier to use.

Before:

var categories =
  from c in rss.PropertyValue<JObject>("channel")
              .PropertyValue<JArray>("item")
              .Children<JObject>()
              .PropertyValues<JArray>("category")
              .Children<string>()
  group c by c into g
  orderby g.Count() descending
  select new { Category = g.Key, Count = g.Count() }; 

After:

var categories =
  from c in rss["channel"]["item"].Children()["category"].Values<string>()
  group c by c into g
  orderby g.Count() descending
  select new { Category = g.Key, Count = g.Count() };

I am still putting some thought into this area but I think it is a definite improvement.

Deserializing Anonymous Types

It is now possible to deserialize directly to an anonymous type with the new DeserializeAnonymousType method. A new method was required because the only way I found to get access to type information about an anonymous type is to have is as an argument.

public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
{
  return DeserializeObject<T>(value);
}

If there is a better way let me know!

Dates

Dates in JSON are hard.

The first issue is that there is no literal syntax for dates in the JSON spec. You either have to invent your own or break from the spec and use the JavaScript Date constructor, e.g. new Date(976918263055).

Historically Json.NET defaulted to using the JS Date constructor but in this release the default format has changed to using the approach taken by Microsoft. The "\/Date(1198908717056+1200)\/" format is conformant with the JSON spec, allows timezone information to be included with the DateTime and will make Json.NET more compatible with Microsoft's JSON APIs. Developers that want to continue to use the JavaScript Date constructor format of Json.NET 1.x, a JavaScriptDateTimeConverter has been added.

The second issue with dates in JSON (and also in .NET it turns out!) are timezones. I have never written an application that needed to worry about timezones before and I have learn't a lot of the past couple of days [:)]

Previously Json.NET was returning local ticks when it really should have been using UTC ticks. That has now been corrected.

Other miscellaneous Date changes in this release are another new date converter, IsoDateTimeConverter, which reads to and from the ISO 8601 standard (1997-07-16T19:20:30+01:00) and support for reading, writing and serializing the new DateTimeOffset struct.

Changes

All changes since the last release:

  • New feature - Added FromObject to JObject, JArray for creating LINQ to JSON objects from regular .NET objects.
  • New feature - Added support for deserializing to an anonymous type with the DeserializeAnonymousType method.
  • New feature - Support for reading, writing and serializing the new DateTimeOffset type.
  • New feature - Added IsoDateTimeConverter class. Converts DateTimes and DateTimeOffsets to and from the ISO 8601 format.
  • New feature - Added JavaScriptDateTimeConverter class. Converts DateTimes and DateTimeOffsets to and from a JavaScript date constructor.
  • New feature - XmlNodeConverter handles serializing and deserializing JavaScript constructors.
  • New feature - Ability to force XmlNodeConverter to write a value in an array. Logic is controlled by an attribute in the XML, json:Array="true".
  • New feature - JsonSerializer supports serializing to and from LINQ to JSON objects.
  • New feature - Added Depth property to JsonReader.
  • New feature - Added JsonTextReader/JsonNodeReader and JsonTextWriter/JsonNodeWriter.
  • Change - More concise LINQ to JSON querying API.
  • Change - JsonReader and JsonWriter are now abstract.
  • Change - Dates are now serialized in a JSON complient manner, similar to ASP.NET's JavaScriptSerializer or WCF's DataContractJsonSerializer.
  • Change - JsonSerializer will serialize null rather than throwing an exception.
  • Change - The WriteTo method on LINQ to JSON objects now support JsonConverters.
  • Fix - JsonTextReader correctly parses NaN, PositiveInfinity and NegativeInfinity constants.
  • Fix - JsonSerializer properly serializes IEnumerable objects.
  • Removed - AspNetAjaxDateTimeConverter. Format is no longer used by ASP.NET AJAX.
  • Removed - JavaScriptObject, JavaScriptArray, JavaScriptConstructor. Replaced by LINQ to JSON objects.

Json.NET CodePlex Project

Json.NET 2.0 Beta 2 Download - Json.NET source code and binaries

kick it on DotNetKicks.com

My Homer is not a communist. He may be a liar, a pig, an idiot, a communist, but he is not a porn star.

LINQ to JSON beta

Oh no, Beta! I like LINQ. A lot. For the past few months I have been fortunate to work on a .NET 3.5 project and I have been making heavily use of LINQ to XML. While using XLINQ it occurred to me that a similar API for working with JSON objects, which share a lot of similarities with XML, would be useful in many situations.

This beta is a very rough early preview of LINQ to JSON. It was literally written in a weekend [:)] The aim is to get feedback and ideas on how the API could be improved.

What is LINQ to JSON

LINQ to JSON isn't a LINQ provider but rather an API for working with JSON objects. The API has been designed with LINQ in mind to enable the quick creation and querying of JSON objects.

LINQ to JSON is an addition to Json.NET. It sits under the Newtonsoft.Json.Linq namespace.

Creating JSON

Creating JSON using LINQ to JSON can be done in a much more declarative manner than was previously possible.

List<Post> posts = GetPosts();
 
JObject rss = 
  new JObject(
    new JProperty("channel",
      new JObject(
        new JProperty("title", "James Newton-King"),
        new JProperty("link", "http://james.newtonking.com"),
        new JProperty("description", "James Newton-King's blog."),
        new JProperty("item",
          new JArray(
            from p in posts
            orderby p.Title
            select new JObject(
              new JProperty("title", p.Title),
              new JProperty("description", p.Description),
              new JProperty("link", p.Link),
              new JProperty("category",
                new JArray(
                  from c in p.Categories
                  select new JValue(c)))))))));
 
Console.WriteLine(rss.ToString());
 
//{
//  "channel": {
//    "title": "James Newton-King",
//    "link": "http://james.newtonking.com",
//    "description": "James Newton-King's blog.",
//    "item": [
//      {
//        "title": "Json.NET 1.3 + New license + Now on CodePlex",
//        "description": "Annoucing the release of Json.NET 1.3, the MIT license and the source being available on CodePlex",
//        "link": "http://james.newtonking.com/projects/json-net.aspx",
//        "category": [
//          "Json.NET",
//          "CodePlex"
//        ]
//      },
//      {
//        "title": "LINQ to JSON beta",
//        "description": "Annoucing LINQ to JSON",
//        "link": "http://james.newtonking.com/projects/json-net.aspx",
//        "category": [
//          "Json.NET",
//          "LINQ"
//        ]
//      }
//    ]
//  }
//}

Querying JSON

LINQ to JSON is designed with LINQ querying in mind. These examples use the RSS JSON object created previously.

Getting the post titles:

var postTitles =
  from p in rss.PropertyValue<JObject>("channel")
              .PropertyValue<JArray>("item")
              .Children<JObject>()
  select p.PropertyValue<string>("title");
 
foreach (var item in postTitles)
{
  Console.WriteLine(item);
}
 
//LINQ to JSON beta
//Json.NET 1.3 + New license + Now on CodePlex

Getting all the feed categories and a count of how often they are used:

var categories =
  from c in rss.PropertyValue<JObject>("channel")
              .PropertyValue<JArray>("item")
              .Children<JObject>()
              .PropertyValues<JArray>("category")
              .Children<string>()
  group c by c into g
  orderby g.Count() descending
  select new { Category = g.Key, Count = g.Count() };
 
foreach (var c in categories)
{
  Console.WriteLine(c.Category + " - Count: " + c.Count);
}
 
//Json.NET - Count: 2
//LINQ - Count: 1
//CodePlex - Count: 1

Feel free to make suggestions and leave comments. I am still experimenting with different ways of working with JSON objects and their values.

Json.NET CodePlex Project

LINQ to JSON - Json.NET 2.0 Beta - Json.NET source code and binaries

 

kick it on DotNetKicks.com