Exploring IE9’s Enhanced DOM Capabilities

For IE9 Platform Preview 4, we significantly re-architected how the Chakra JavaScript engine integrates into IE. This re-architecture, described in Dean’s post, subtly changes the programming model of the DOM for IE9 standards mode, making it consistent with new ECMAScript 5 capabilities, more interoperable with other browsers and aligned with emerging standards (WebIDL).

In this post I want to dive into the details of some of these programming model changes. You can take advantage of these enhanced DOM capabilities in the latest platform preview build. To highlight these changes, I’ll reference the Enhanced DOM Capabilities demo page that we released with the fourth Platform Preview.

All 24 puzzle pieces assembled into the image of the IE logo. This is a screenshot of IE9 running the Enhanced DOM capabilities demo at the IE Test Drive web page: http://ie.microsoft.com/testdrive/

That demo tests 24 capabilities that span 4 general categories:

  • DOM object inheritance from native JavaScript objects
  • JavaScript functional harmony with DOM objects
  • Interoperable programming features
  • New ECMAScript 5 support applied to DOM objects

The first two are closely related, so I’ll discuss them together:

DOM object inheritance from native JavaScript objects and JavaScript functional harmony with DOM objects.

Prior to IE9, the JavaScript engine was connected to the DOM via classic COM bindings. These legacy bindings allowed for only primitive object and function representations of the DOM to the JavaScript engine. Consequently, many basic JavaScript features that developers expected to be available to all objects and functions (including DOM objects like Window, Document, NodeList, etc.) were only available to native JavaScript objects (Array, Number, etc.).

The ECMAScript standard specifies basic operations that should work uniformly on all JavaScript objects, but allows “host objects” to deviate from those standard specifications. IE’s old JavaScript engine treated DOM objects as “host objects” which meant that basic JavaScript operations such as property access could behave oddly. While allowed by ECMAScript, inconsistent behavior between DOM objects and JavaScript objects created differences web developers had to account for.

For example, one common puzzler for many web developers was why IE DOM functions were reported as “object” to the typeof JavaScript operator rather than "function" (this capability is specifically checked in the demo as piece #10).

In IE9’s Standards Mode, we build our DOM as native JavaScript objects and functions rather than as “host objects,” thus enabling the features that web developers expect from native objects.

Interoperable programming features

The third group of capabilities showcase unique IE programming model behaviors that web developers commonly stumbled over. Because these behaviors were unique to the IE programming model, web developers found that their code didn't work the same across different browsers.

As part of our new integration architecture, we removed many of the inconsistencies that kept the same script from working the same way across browsers. The programming model changes may cause sites that have conditional code written for IE to behave differently in IE9 than it did before. Therefore, it is worthwhile describing these changes in more depth.

Functions now enumerated

In IE8 and before, enumerating a DOM object did not include any of that DOM object’s member functions. IE9 now enumerates any property on a DOM object that has its “enumerable” property descriptor value set to ‘true’. (In other words, enumeration can be programmatically altered.) Functions are now enumerated by default to be consistent with other browsers.

Removed implicit function invocation

DOM functions in previous versions of IE were quite special. Not only did they claim to be typeof “object”, but they also retained a static ‘this’ value which referred to the object to which they belonged. Consequently, it was possible to cache a reference to a DOM function, and invoke it without explicitly passing the ‘this’ value:

// Works in IE8 and earlier versions
// Doesn't work in IE9 or other browsers

var cachedGetElementById = document.getElementById;
cachedGetElementById('value');

In IE9, this now throws an exception, as it does in other browsers. Code that formerly depended on this IE behavior may use the “.call” workaround:

// Works in IE8/IE9 and other browsers
// Doesn't work in IE7 and earlier versions;

var cachedGetElementById = document.getElementById;
cachedGetElementById.call(document, 'value');

ECMAScript 5 provides a “bind” method for functions which allows them to take on the programming characteristics formerly supported by IE:

// Works natively in IE9 because of ECMAScript 5's 'bind' API
var cachedGetElementById = document.getElementById.bind(document);
cachedGetElementById('value');

Support for DOM exceptions and ‘const’ properties

The IE9 enhanced DOM now includes W3C-specified DOM exception objects and standardized error codes that web developers can use to determine (generally) the nature of a DOM API failure. These codes are commonly compared against well-defined 'const' properties to aid in code readability:


catch(ex) {
   if (ex.code == DOMException.INDEX_SIZE_ERR)
      …
}

The enhanced DOM provides the pre-defined 'const' properties as well as the architecture to throw and catch DOM exceptions.

Consistent toString behavior

With Chakra and the DOM fully integrated, the DOM does not have its own implementation of toString (a function that converts any object into a string form). While the old DOM’s toString implementation was similar to the JavaScript built-in version, it was not the same and often returned inconsistent or puzzling results. IE9 DOM objects now inherit and use the JavaScript built-in toString for more uniform results.

Separation of property and attribute storage

In the previous architecture, DOM objects had their own property storage. This property storage was the same as the storage location for attributes (those found in the HTML markup). With IE9's new architecture, an element’s attribute storage is now separate from the dynamic properties assigned to an element's script object. To illustrate this separation, consider the following example markup:

<div id="myId" class="c" user-defined-attribute="test">

In the above example, “id”, “class”, and “user-defined-attribute” are attributes. The div element's JavaScript object also exposes similar properties:

// Get the JavaScript object representing the body
var divOb = document.getElementById(‘myId’);
divOb.id;        // "myId"
divOb.className; // "c"

These JavaScript properties retrieve the values stored in an element’s attribute list. For example, “id” retrieves the value of the “id” attribute. “className” retrieves the value of the “class” attribute.

In previous versions of IE, any dynamically-added properties would “magically” appear in the element’s attribute list and vice-versa due to the shared storage location. This could lead to unexpected results:

<div id="myId" class="c" user-defined-attribute="test">

var divOb = document.getElementById("myId");
// The next statement unexpectedly adds "userProperty" as
// an attribute to the element.

divOb.userProperty = "test"

// How many attributes?
alert("Total attributes = " + divOb.attributes.length);

IE9 and other browsers alert three total attributes ("id", "class", and "user-defined-attribute"), whereas previous versions of IE alert 4, adding "userProperty" to the list. The reverse example is more common—code that expects user-defined attributes to appear as dynamic properties:

<div id="myId" class="c" user-defined-attribute="test" userAttribute="test">

var divOb = document.getElementById("myId");
// Get the "userAttribute" and "user-defined-attribute" value
// (only worked in IE8 and previous versions)
var value1 = divOb.userAttribute;
var value2 = divOb["user-defined-attribute"];

We’ve seen a lot of code that expects this legacy IE behavior. The interoperable way to retrieve unknown attributes is to use “getAttribute,”

var value1 = divOb.getAttribute("userAttribute");
var value2 = divOb.getAttribute("user-defined-attribute");

and dynamic properties should not be queried through the attributes collection.

New ECMAScript 5 capabilities

In the last group of capability tests, new functionality provided by Chakra’s implementation of ECMAScript 5 is applied to the DOM. One of the primary goals for the enhanced DOM in IE9 was to provide a representation of the DOM that made logical sense within the context of the ECMAScript 5 language semantics. This was made much easier because one of the primary goals of ECMAScript 5 is to better support the functionality needed by DOM objects! In our implementation, we represented the DOM using as many native ECMAScript 5 language features as possible, including extensive use of accessor (getter/setter) properties.

This native integration allows all of the new ECMAScript5 features to work equally well with native objects as with DOM objects.

The enhanced DOM capabilities demo shows only 24 samples of what is possible when the DOM is fully integrated with an ECMAScript 5-capable JavaScript engine like Chakra. We are very excited about this support in IE9 and want to help get better interoperability for ECMAScript language bindings across browsers. An important step is standardizing these binding within the W3C, and we’re happy to contribute to that effort.

W3C web standards have always supplied a language binding for ECMAScript implementations as a way to translate the standard IDL (Interface Definition Language) into JavaScript objects. However, these bindings lacked sufficient detail to create much more than a simple “host object” binding (a binding without consideration of the full spectrum of ECMAScript language features). While other browsers have a much more comprehensive language binding than simply “host objects,” integration inconsistencies remain. These inconsistencies can really frustrate JavaScript framework developers who wish to write abstraction layers and features on top of the basic language support. The need for consistency led to a proposed standard called WebIDL (Web Interface Definition Language). The WebIDL specification describes in much more precise detail, how to translate a given W3C spec written using WebIDL into JavaScript objects.

In a follow-up post, I will describe in more detail how we used WebIDL to inform and guide the development of the IE9 enhanced DOM.

Please testdrive the IE9 enhanced DOM. We look forward to your comments and feedback.

Travis Leithead
IE Program Manager

Author news: Vittorio Bertocci on MSDN Channel 9

627185cvr.indd Check out MSDN Channel 9 for a 40-minute video of Programming Windows Identity Foundation author Vittorio Bertocci talking about his book.

 

From MSDN Channel 9:

In this episode:  

    In this episode of The Knowledge Chamber, I meet with Vittorio Bertocci (who just finished a new book, Programming Windows Identity Foundation) to learn more about the basic features and capabilities of Windows Identity Foundation and see how easy it is for websites and applications to get out of the credential management game and “outsource” their authentication to another provider.

370ish DRM-free Microsoft Press ebooks now available

In February it was 200ish, in April it was 325ish, and now it’s around 370 Microsoft Press ebook bundles available. Take a look. When you see an e icon in the Ebook column, the title is available is four different electronic formats.

Here are more details:

  • iPhone – Grab the EPUB and read it in the Stanza App or the mobile version of Bookworm.
  • Android – Read the .apk or .EPUB on your favorite reader.
  • Kindle – Get the Mobipocket file and load it onto your Kindle.
  • Sony Reader – EPUBs work well on your Sony Reader.
  • Computer – Get either the EPUB or PDF.
  • Other Mobile Devices – Explore the EPUB with the mobile version of Bookworm.

Enjoy!

Silverlight Blog Commenting Fixed

Ugh. Much to our chagrin, we discovered that the commenting functionality on this blog wasn't working. We just made some tweaks and commenting on this blog is working once again!


New Structured Diagrams Whitepaper for Visio 2010

Microsoft has published a new technical article on MSDN about the Structured Diagram capabilities of Visio 2010.  Structured Diagrams help you organize the contents of your diagrams using intuitive, logical relationships between shapes.  These capabilities are exposed as the Containers, Lists, and Callouts features in Visio 2010.

Structured-diagram shape relationships

The article covers these topics:

  • Overview of the Containers, Lists, and Callouts features from an end-user perspective
  • Details for creating or customizing your own Structured Diagram shapes
  • Overview of the Structured Diagram API with code examples

Readers of the Visio Insights blog will be familiar with much of the article, since it is based on a number of previous posts.  However, some of the details on Lists are new.  For reference, here are the related Visio Insights posts:

Please let us know if you have any feedback on Visio 2010, Visio Services, or suggestions for blog posts you would like to see.

Visual Reports – Where Did My Field Go?

One of the more common questions I get around Visual Reports is “I selected a field (% complete, duration, some text custom field, etc.) to add to my report and it doesn’t show up in Excel – why isn’t it there?”. The field probably is there, it just is in a different spot.

Visual Reports are built off a data structure called a cube. Cubes have 3 kinds of data types – dimensions, measures, and properties.

 Dimensions are anything you can pivot the data on –ex. tasks, resources, time dimensions, any custom field with a lookup table.

Measures are anything the rollup can be calculated on –  ex. work, cost, actual work.

Properties are everything else, they are just associated with tasks or resources and provide supporting information – ex. % complete, duration, text fields. Percent complete is a good example of a property since it is a number so it seems like it could be rolled up but unfortunately two 50% complete tasks do not equal a 100% complete summary.

If you can’t find your field, it is probably a property. To add those to a pivotTable in Excel you can’t go through the PivotTable field list that you are used to. You have to first add the resources or task dimension to the report. Then right-click a resource/task, select “Show Properties in Report”, and select your field.

image

That will give you this:

image

So to recap:

image

Note that you have to be using Excel 2007 or later to display properties. For more information on Visual Reports, check out this help article.

Compression for Speed and Cost Savings

SQL Azure doesn’t currently support page level or row level compression like the enterprise edition of SQL Server 2008. However, you can implement your own column level compression in your data access layer to take advantage of the performance and cost savings of compression. I will discuss how to do this and provide some example code in this blog post.

Column level compression is the concept of compressing your data before you write it to the database, and decompressing it when you it from the database. For example, instead of having varchar(max) column of text you have a varbinary(max) of compressed text that is holding on average 80% less data.

The Right Scenario

Only in certain scenarios does column level compression work well. When compressing columns consider that:

  • Large text columns are the best to compress; they gain you the most savings. The gain from compression must exceed the costs of creating the compression dictionary (a result of using deflate compression); this only happens when there is a large amount of data that repeats itself. This technique will benefit not only text but large xml and binary data as well depending on the content. For example, you don’t want to compress images blobs – they are usually already compressed.
  • Don’t compress columns that appear in the WHERE clause of your queries. With this technique you can’t query on the compressed text without decompressing it. You also won’t be able to query or access these fields through SSMS or load data directly using BCP.exe
  • Compress columns that can be cached on the application side, to avoid multiple reads; this avoids the costs of decompressing the text.

For example scenario that would work well is a web based product catalogues where you compress the product description and where you don’t need to search within the description and it doesn’t change very often.

The Benefits

Compression can reduce the amount of data you are storing, creating potential cost savings. It can also potentially help you stay below the maximum 50 Gigabyte database size for SQL Azure and avoid the development costs of partitioning.

In certain scenarios compression can result in speed improvements for queries that are preforming full table scans on the clustered index. When dealing with large-value data types, if the data in the column is less than 8,000 bytes it will be stored in the page with the rest of the column data. If you can reduce the 8000 bytes, more rows can be paged at one time, giving you performance gains on full table scans of the table.

Table Modification

Compressed data should be stored in varbinary(max) columns. If you are compressing a nvarchar(max) column, you will need to create an additional column to compress you data into. You can do this with an ALTER TABLE command. Once you have the text compressed, you delete the nvarchar(max) column. Here is a little example Transact-SQL that adds a column to SQL Azure:

ALTER TABLE Images ADD PageUriCompressed varbinary(max) NOT NULL DEFAULT(0x0)

The Data Layer

Fortunately, .NET CLR 2.0 has some great compression built into the System.IO.Compression namespace with the GZipStream class. The first thing I need to do is create a throw-away console application that I will use once to compress all the existing rows into the new column, here is what it looks like:

do
{
    using (SqlConnection sqlConnection =
        new SqlConnection(
            ConfigurationManager.ConnectionStrings["SQLAzure"].ConnectionString))
    {
        String pageUri;
        Int64 Id;

        // Open the connection
        sqlConnection.Open();

        // Pull One Row At A Time To Prevent Long Running
        // Transactions
        SqlCommand sqlCommand = new SqlCommand(
            "SELECT TOP 1 ID, PageUri FROM [Images] WHERE PageUriCompressed = 0x0",
            sqlConnection);

        using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
        {
            // WWB: Exit Do Loop When There Is No More Rows
            if (!sqlDataReader.Read())
                break;

            pageUri = (String)sqlDataReader["PageUri"];
            Id = (Int64)sqlDataReader["ID"];
        }

        Console.Write(".");

        // Compress Into the Memory Stream
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (GZipStream gzipStream = new GZipStream(memoryStream,
                CompressionMode.Compress, true))
            {
                // Unicode == nvarchar
                Byte[] encodedPageUri = Encoding.Unicode.GetBytes(pageUri);
                gzipStream.Write(encodedPageUri, 0, encodedPageUri.Length);
            }

            // Now Everything is compressed into the memoryStream
            // Reset to Zero Because We Are Going To Read It
            memoryStream.Position = 0;

            // WWB: Stream for Writing
            using (SqlStream sqlStream = new SqlStream(sqlConnection,
                "dbo",
                "Images",
                "PageUriCompressed",
                "ID",
                SqlDbType.BigInt, Id))
            {
                using (BinaryReader binaryReader = new BinaryReader(memoryStream))
                {
                    using (BinaryWriter binaryWriter = new BinaryWriter(sqlStream))
                    {
                        Int32 read;
                        Byte[] buffer = new Byte[1024];
                        do
                        {
                            read = binaryReader.Read(buffer, 0, 1024);
                            if (read > 0)
                                binaryWriter.Write(buffer, 0, read);

                        } while (read > 0);
                    }
                }
            }
        }
    }
} while (true);

Console.WriteLine("");

This code uses the SqlStream class that was introduced in this blog post.It also tries to make good use of the local memory and not consume too much if the string being compressed is really big. However, this results in a very “chatty” application that creates a lot of connections to SQL Azure and runs slower than I would like.

Evaluation

My next step is to evaluate if the compressed really helped me. I do this because it can be hard to evaluate what the benefits compression will have until you have compressed your real world data. To do this I use the DATALENGTH field in Transact-SQL to sum up the two columns, i.e. before and after compression. My query looks like this:

SELECT COUNT(1), SUM(DATALENGTH(PageUri)), SUM(DATALENGTH(PageUriCompressed))
FROM Images

The results look like this:

clip_image001

I can see that compressed is actually going to reduce the size of my database in this case. In some scenarios compression makes the data bigger, usually when the data dictionary exceeds the gains from compression. As a rule of thumb, to have effective compression on text you need to have multiple repeating phrases, which happen with longer text blocks

Code

Now that the column is compressed you need to be able to read the compressed data and write uncompressed data to the column compressed. Here is a little bit of example code to help you do that:

protected static String Read(Int64 id)
{
    using (SqlConnection sqlConnection =
        new SqlConnection(
            ConfigurationManager.ConnectionStrings["SQLAzure"].ConnectionString))
    {
        sqlConnection.Open();

        SqlCommand sqlCommand = new SqlCommand(
            "SELECT PageUriCompressed FROM [Images] WHERE ID = @Id",
                sqlConnection);

        sqlCommand.Parameters.AddWithValue("@Id", id);

        using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
        {
            sqlDataReader.Read();

            Byte[] compressedPageUri = 
                (Byte[])sqlDataReader["PageUriCompressed"];

            using (MemoryStream memoryStream = 
                new MemoryStream(compressedPageUri))
            {
                using (GZipStream gzipStream = new GZipStream(memoryStream, 
                    CompressionMode.Decompress))
                {
                    using (StreamReader streamReader =
                        new StreamReader(gzipStream, Encoding.Unicode))
                    {
                        return (streamReader.ReadToEnd());
                    }
                }
            }
        }
    }
}

For writing:

protected static void Write(Int64 id, String pageUri)
{
    using (SqlConnection sqlConnection =
        new SqlConnection(
            ConfigurationManager.ConnectionStrings["SQLAzure"].ConnectionString))
    {
        // Open the connection
        sqlConnection.Open();

        // Compress Into the Memory Stream
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (GZipStream gzipStream = new GZipStream(memoryStream,
                CompressionMode.Compress, true))
            {
                // Unicode == nvarchar
                Byte[] encodedPageUri = Encoding.Unicode.GetBytes(pageUri);
                gzipStream.Write(encodedPageUri, 0, encodedPageUri.Length);
            }

            // Now Everything is compressed into the memoryStream
            // Reset to Zero Because We Are Going To Read It
            memoryStream.Position = 0;

            // WWB: Stream for Writing
            using (SqlStream sqlStream = new SqlStream(sqlConnection,
                "dbo",
                "Images",
                "PageUriCompressed",
                "ID",
                SqlDbType.BigInt, id))
            {
                using (BinaryReader binaryReader = new BinaryReader(memoryStream))
                {
                    using (BinaryWriter binaryWriter = new BinaryWriter(sqlStream))
                    {
                        Int32 read;
                        Byte[] buffer = new Byte[1024];
                        do
                        {
                            read = binaryReader.Read(buffer, 0, 1024);
                            if (read > 0)
                                binaryWriter.Write(buffer, 0, read);

                        } while (read > 0);
                    }
                }
            }
        }
    }
}

SQL Compression

For a comparison, the compression built into an on-premise SQL Server is transparent to the application and benefits much wider range of types like decimal and bigint all the way to larger types because it scopes to the row to the page. In other words it can use the repetition dictionary in compression across all the columns in the page. You can read more about SQL Server 2008 compression here.

Summary

Do you have a better way to accomplish the same thing? Post it in the comments below. Do you have questions, concerns, comments? Post them below and we will try to address them.

Implementing a workflow service for inbound LOB operations

Consider the following scenario – I want to write a workflow that gets instantiated when certain changes happen in LOB (say a new row is added to a table) and then does some processing with the altered data. In the current release of Microsoft BizTalk Server, Add Adapter Service Reference (AASR) generates LOB activities only for outbound operations. For inbound operations (polling, notification, etc), AASR only generates the contract and configuration information along with a dummy service implementation. This blog explains how to create such a workflow service and host it in IIS.

I will use a Typed Polling scenario for WCF SQL adapter to illustrate the steps involved for a one-way operation.

Generate service - Create a new “WCF Workflow Service Application”. Run AASR and select the appropriate inbound operation. You can delete the dummy service implementation since that’s no longer required. Let’s assume the generated contract looks like

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="
http://schemas.microsoft.com/Sql/2008/05/", ConfigurationName="TypedPolling_Foo")]
public interface TypedPolling_Foo {    
        [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="TypedPolling")]
        void TypedPolling(TypedPolling request);
}

Configure the activities - Since this operation is one-way, we will delete the “SendResponse” activity and also remove the co-relation handle from the “Receive” activity (in the properties for the “Receive” activity, select CorrelationInitializers and delete the handle) and optionally from the “Variables” as well. Apply the following configuration to the activity (obtained from the above contract)

  • OperationName – TypedPolling
  • ServiceContractName – {http://schemas.microsoft.com/Sql/2008/05/}TypedPolling_Foo
  • Action – TypedPolling
  • Check CanCreateInstance

 

 

  • Content – Select “Message"
    • Message data – create a variable of type TypedPolling and specify that
    • Message type – TypedPolling

 

 

 

If the operation is two-way, i.e. needs to return a response, SAP RFC call for example, there are some differences. You shouldn’t remove the “SendResponse” activity and the correlation handle. The configuration of the “Receive” part stays the same as described above. For the “SendResponse” part, apply the following configuration.

  • Action – Set this to the ReplyAction in the OperationContractAttribute.
  • Content – Select “Message” and set the “Message type” to the return type and “Message data” to a variable of that type

 

 

Process the input - The workflow can now use the variable (Message data) to get the contents of the poll and do whatever processing it needs to do with that data

Update the config - Modify the “service” name in the configuration file to the name of the service, as specified in the xamlx file.

    <system.serviceModel>
      …
      <services>
        <service name="Service1">
          <endpoint address="mssql://localhost//mytestdb?InboundId=Foo" …

Deploy the service - At this point the service is ready to be hosted.  You can use VS 2010 to deploy it to IIS. From the project properties --> Web, select the “Use Local IIS Web Server”, specify a URL, create a virtual directory and then build the project. However, since the service endpoint is using a custom binding which IIS does not understand, we will need to “Auto-Start” it. This is a new feature in IIS 7.5 and is explained here. While the blog explains it in the context of Service Bus Endpoints, it applies to this scenario as well.

 

Sandeep Prabhu,
BizTalk Server Team

 

The Future of Silverlight

There's been a lot of discussion lately around web standards and HTML 5 in particular. People have been asking us how Silverlight fits into a future world where the <video> tag is available to developers. It's a fair question—and I'll provide a detailed answer—but I think it's predicated upon an oversimplification of the role of standards that I'd like to clear up first. I'd also like to delineate why premium media experiences and "apps" are better with Silverlight and reveal how Silverlight is going beyond the browser to the desktop and devices.

Standards and Innovation

It's not commonly known, perhaps, that Microsoft is involved in over 400 standards engagements with over 150 standards-setting organizations worldwide. One of the standards we've been involved in for years is HTML and we remain committed to it and to web standards in general. It's not just idle talk, Microsoft has many investments based on or around HTML such as SharePoint, Internet Explorer, and ASP.NET. We believe HTML 5 will become ubiquitous just like HTML 4.01 is today.

Standardize - Innovate

But standards are only half of the story when we think of the advancement of our industry. Broadly-implemented standards are like paved roads.  They help the industry move forward together.  But before you can pave a road, someone needs to blaze a trail. This is innovation. Innovation and standards are symbiotic—innovations build on top of other standards so that they don't have to "reinvent the wheel" for each piece of the puzzle. They can focus on innovating on the specific problem that needs to be solved. Innovations complement or extend existing standards. Widely accepted innovations eventually become standards. The trails get paved.

In the past, this has happened several times as browsers implemented new features that later became standards. Right now, HTML is adopting as standards the innovations that came from plug-ins like Flash and Silverlight. This is necessary because some of these features are so pervasive on the web that they are seen by users as fundamentally expected capabilities. And so the baseline of the web becomes a little higher than it was before. But user expectations are always rising even faster—there are always more problems we can solve and further possibilities needing to be unlocked through innovation.

This is where Silverlight comes in. On the web, the purpose of Silverlight has never been to replace HTML; it's to do the things that HTML (and other technologies) couldn't in a way that was easy for developers to tap into. Microsoft remains committed to using Silverlight to extend the web by enabling scenarios that HTML doesn't cover. From simple “islands of richness” in HTML pages to full desktop-like applications in the browser and beyond, Silverlight enables applications that deliver the kinds of rich experiences users want. We group these into three broad categories: premium media experiences, consumer apps and games, and business/enterprise apps.

Premium Media Experiences

Examples include:

  • Teleconferencing with webcam/microphone
  • Video on demand applications with full DVR functionality and content protection like Netflix
  • Flagship online media events like the Olympics as covered by NBC, CTV, NRK, and France Télévisions
  • Stream Silverlight video to desktops, browsers, and iPhone/iPad with IIS Smooth Streaming

Even though these experiences are focused on media, they are true applications that merge multiple channels of media with overlays and provide users with full control over what, when, and how they experience the content. The media features of Silverlight are far beyond what HTML 5 will provide and work consistently in users' current and future browsers. Key differentiators in these scenarios include:

  • High Definition (HD) H.264 and VC-1 video
  • Content protection including DRM
  • Stereoscopic 3D video
  • Multicast
  • Live broadcast support
  • (Adaptive) Smooth Streaming
  • Information overlays / Picture-in-picture
  • Analytics support with the Silverlight Analytics Framework

Consumer Apps and Games

The bar is continually rising for what consumers expect from their experiences with applications and devices. Whether it's a productivity app or a game, they want experiences that look, feel, and work great. Silverlight makes it possible for designers and developers to give the people what they want with:

  • Fully-customizable controls with styles and skins
  • The best designer – developer workflow through our tools and shared projects
  • Fluid motion via bitmap caching and effects
  • Perspective 3D
  • Responsive UI with .NET and multithreading

Business/Enterprise Apps

As consumers get used to richer, better experiences with software and devices, they're bringing those expectations to work. Business apps today need a platform that can meet and exceed these expectations. But the typical business app is built for internal users and must be built quickly and without the aid of professional designers. To these ends, Silverlight includes the following features to help make rich applications affordable:

  • Full set of 60+ pre-built controls, fully stylable
  • Productive app design and development tools
  • Powerful performance with .NET and C#
  • Powerful, interactive data visualizations through charting controls and Silverlight PivotViewer
  • Flexible data support: Databinding, binary XML, LINQ, and Local Storage
  • Virtualized printing
  • COM automation (including Microsoft Office connectivity), group policy management

Other Considerations

For simpler scenarios that don't require some of the advanced capabilities mentioned above, Silverlight and HTML both meet the requirements. However, when looking at both the present and future state of platform technologies, there are some other factors to take into consideration, such as performance, consistency and timing.

Performance

The responsiveness of applications and the ability for a modern application to perform sophisticated calculations quickly are fundamental elements that determine whether a user's experience is positive or not. Silverlight has specific features that help here, from the performance of the CLR, to hardware acceleration of video playback, to user-responsiveness through multithreading. In many situations today, Silverlight is the fastest runtime on the web.

Bubblemark

Consistency

Microsoft is working on donating test suites to help improve consistency between implementations of HTML 5 and CSS3 but these technologies have traditionally had a lot of issues with variation between browsers. HTML 5 and CSS 3 are going to make this worse for a while as the specs are new and increase the surface area of features that may be implemented differently. In contrast, since we develop all implementations of Silverlight, we can ensure that it renders the same everywhere.

Browser Inconsistencies

Timing

In about half the time HTML 5 has been under design, we've created Silverlight and shipped four major versions of it. And it's still unclear exactly when HTML 5 and its related specs will be complete with full test suites. For HTML 5 to be really targetable, the spec has to stabilize, browsers have to all implement the specs in the same way, and over a billion people have to install a new browser or buy a new device or machine. That's going to take a while. And by the time HTML 5 is broadly targetable, Silverlight will have evolved significantly. Meanwhile, Silverlight is here now and works in all popular browsers and OS's.

Silverlight - HTML 5 Timeline

Beyond the Browser

In this discussion of the future of Silverlight, there's a critical point that is sometimes overlooked as Silverlight is still often referred to—even by Microsoft—as a browser plug-in. The web is evolving and Silverlight is evolving, too. Although applications running inside a web browser remain a focus for us, two years ago we began showing how Silverlight is much more than a browser technology.

Silverlight Outside the Browser

There are three areas of investment for Silverlight outside the browser: the desktop, the mobile device, and the living room. Powerful desktop applications can be created with Silverlight today. These applications don't require a separate download—any desktop user with Silverlight installed has these capabilities. These apps can be discovered and downloaded in the browser but are standalone applications that are painless to install and delete. Silverlight now also runs on mobile devices and is the main development platform for the new Windows Phone 7 devices. Developers that learned Silverlight instantly became mobile developers. Lastly, at NAB and the Silverlight 4 launch this year we showed how Silverlight can be used as a powerful, rich platform for living room devices as well.

Expect to see more from Silverlight in these areas especially in our focus scenarios of high-quality media experiences, consumer apps and games, and business apps.

When you invest in learning Silverlight, you get the ability to do any kind of development from business to entertainment across screens from browser to mobile to living room, for fun, profit, or both. And best of all, you can start today and target the 600,000,000 desktops and devices that have Silverlight installed.

If you haven't already, start here to download all the tools you need to start building Silverlight apps right now.

For more information on this topic, you can watch a video with more details here.

Brad Becker, Director of Product Management, Developer Platforms


Follow-up paper from FMS, Inc. on a popular topic: SQL Azure and Access

Two recent papers written by Luke Chung of FMS, Inc. about SQL Azure and Access have created a lot of interest on his blog, as well as a few linked forum discussions. In response, Luke has written a follow-up paper about deploying an Access database once it’s linked to SQL Azure. He has also revised his original paper about linking to SQL Azure to clarify that you only need to install the SQL Server 2008 R2 Management Services program (SSMS) and not SQL Server itself.

Thanks again, Luke!

Luke Chung, President and Founder of FMS, Inc., has written and presented a wide range of topics related to Access over the years. In addition to their many Access related products, FMS offers a wealth of great Access papers, tips, and video on their site.