
Wednesday, February 20, 2008
I've saw a few people trip over the Fill property of Silverlight objects in JavaScript last week. Let's use the following XAML snippet as an example:
<Canvas>
<Rectangle x:Name ="_box1" Canvas.Left="10" Canvas.Top="10"
Width="100" Height="100" Fill="Red" />
<Rectangle x:Name ="_box2" Canvas.Left="120" Canvas.Top="10"
Width="100" Height="100" Fill="Red" />
</Canvas>
Given the way the Fill attributes look (Fill="Red"), you'd be tempted to think the following code would work:
var box1 = silverlightControl.content.findName('_box1');
var box2 = silverlightControl.content.findName('_box2');
box1.Fill = "Green";
box2.Fill = box1.Fill; // this will create an error
But, that last line of code will create a runtime error:

The infamous AG_E_RUNTIME_SETVALUE error! The error says we are trying to put a square object into a round hole. What is the Fill property expecting? Aren't we just copying a simple string reference around? The debugger's immediate window can give us a few hints as to what is happening:
The first dump shows us that the Fill property doesn't reference a simple string. The second dump tells us we are actually dealing with a SolidColorBrush object. Hmmm – what happened to "Red"? Even more mysterious - the third dump (the brush's Color property) is a negative number.
Magical Colors
The MSDN docs for Color describe some of the type conversion magic operating behind the scenes. Essentially, you can set a Color property (or the Fill property of a SolidColorBrush) using a well known name ("Green"), a hex string ('#FF00FF00'), or an ScRGB string ('sc#1,0,1,0'). Silverlight will take care of converting the incoming value into the proper internal representation. So, setting a Color property is easy. What's difficult is getting a meaningful value out of the Color property. Take note of this remark in the MSDN docs:
The runtime scripting value of an existing Color is potentially stored differently on different browsers and platforms. You can compare color values obtained from scripting between existing instances, or set one Color property with the value of another existing Color, but directly comparing these values to named color strings, hex strings, or ScRGB strings that were used to specify the color initially is not supported.
This means we can avoid the runtime error with the following code …
box1.Fill = 'BlanchedAlmond';
box2.Fill.Color = box1.Fill.Color;
… but we need to be careful with code like the following. The makeHexColor function will compute the correct hex string for Color properties on IE7 (like '#ff00ff00' for a green color, which we saw yielded -65536 in the debugger), but according to the docs this code might break in FireFox or on a Mac, because the internal representation of colors might be different.
box1.Fill = 'Green';
box2.Fill.Color = makeHexColor(box1.Fill.Color);
// ...
function makeHexColor(color)
{
var result = "";
for (var i = 0; i < 8; i++) {
result = (color & 0xF).toString(16) + result;
color >>= 4;
}
return "#" + result;
}
 |
Tuesday, November 13, 2007
The current Silverlight 1.1 alpha will eat exceptions.
I’m not sure if the final version will behave similarly, but if you are working with the alpha don’t let this behavior surprise you.
For example, consider the following event handlers that listen to a shape’s mouse events:
void _box_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
throw new NotImplementedException();
}
void _box_MouseLeftButtonUp(object sender, MouseEventArgs e)
{
_box.Width += 5;
}
The left mouse button goes down and … nothing happens. There is no indication of an error.
Later, when the left mouse button goes up … the shape will grow in size. Silverlight is still running with the attitude of a Broadway director. Despite the setback - the show must go on.
If you have some mysterious behavior and are not catching exceptions inside event handlers, a good start might be to go into the Visual Studio Exceptions dialog (Debug -> Exceptions) and configure the debugger to break as soon as code throws an exception (the default setting is to only break on a user unhandled exception). This might help locate the problem.
There is one area where an unhandled exception will stop the show. Consider the following user control:
public class ColorfulSlider : Control
{
public ColorfulSlider()
{
// code ...
throw new InvalidOperationException("something went wrong...");
}
}
If we place this faulty user control into a Page.xaml file that loads with the plugin – Silverlight will tell us there is a parser error. The error message tends to make one look inside the .xaml file for malformed XML. The real problem is that Silverlight can’t instantiate the object requested in XAML because the default constructor throws an exception.
 |
Sunday, October 14, 2007
The New ASP.NET Framework
ScottGu gave a demo of the new MVC framework for ASP.NET at the ALT.NET Conference. Here are some notes and thoughts I had after watching ScottHanselman's recording.
The framework should go live in the spring of 2008. The framework is not a replacement for ASP.NET WebForms, but provides an alternative paradigm for building web applications. The new framework still works inside of the ASP.NET runtime - meaning all of the wonderful infrastructure pieces like the configuration system, provider model, SQL cache invalidation, health monitoring, and master pages continue to exist. Like the ASP.NET AJAX extensions – it sounds like we'll only need a new assembly to start the party.
Being an "MVC framework", the software features the Model View Controller pattern. MVC and its many permutations have been (and continue to be) principal patterns in many application frameworks and development environments. There were several mentions of Rails (both the Mono and Ruby types), and at least one reference to Django (the Django book is a good read to get into the framework's mindset).
The framework will provide:
- Mechanisms to enforce a clean separation of concerns
- An API designed for testability
- A pluggable and extensible technology stack
Separation of Concerns
ASP.NET WebForms map an incoming URL to a single .aspx file. Although one can use an HttpModule or VirtualPathProvider to change this behavior, the majority of ASP.NET web applications use this default behavior. In practice, this approach tends to produce code-behind files with intermingled presentation, data access, and business logic. This approach also tightly couples URLs to the physical arrangement of .aspx files in the file system.
The new MVC framework offers a loose coupling between incoming URLs and the view that will ultimately render HTML. ScottGu describes a flexible and pluggable URL dispatching engine that can handle clean and procedural URLs like:
http://OdeToCode.com/articles/show/450
or
http://www.pluralsight.com/classes/register/appliedsilverlight
The URL dispatching engine examines incoming URLs, routes each request to an instance of a controller class, and invokes a method on the controller (the action).
Controllers
Controllers in the new framework support test first and controller first development styles. In other words, you can implement a controller sans any views, and fully test the controller's ability to utilize application logic and services to respond to a request.
The framework provides a low-level interface definition you can implement to claim absolute power over controller policy, but also provides a hierarchy of concrete controller classes to build upon.
When the controller is ready, it can call RenderView(string viewName, object viewData) to generate the appropriate user interface response. Thanks to generics, this boundary can also be strongly typed.
Views
Views render HTML, but views are not web forms - there is no page lifecycle, postbacks, or viewstate in this framework.
In general, views are simple templates. Templates are concerned only with presentation. To enforce a separation of concerns, many template engines do not allow a template to change the value of a variable or call into application logic, but the ASP.NET framework will allow code blocks and data-binding. The view never references a controller, and the controller never references a view - so testability and a separation of concerns prevail.
Designed For Testability
One of the current difficulties in writing unit tests for code running inside an ASP.NET environment is the pervasiveness of sealed classes like HttpContext.The MVC framework features an interface based API with IHttpContext, IResponse, IRequest, etc.
There is a mock view engine and, I believe, mock implementations of IHttpContext and the like to make testing easier.
At the beginning of the discussion Scott mentioned that the framework will include inversion of control containers, although I don't recall this feature appearing in the presentation.
A Pluggable Architecture
It sounds as if every major service in the MVC framework is pluggable – the view engine (throw in Brail), the dependency injection framework (throw in Structure Map), the URL dispatcher, the controllers, and more.
Look For the CTP Soon
The new framework appears to marry mature paradigms from outside the world of ASP.NET with the high performance and robust infrastructure of the ASP.NET runtime. Look for a CTP by the end of the year.
 |
Wednesday, October 10, 2007
Moving from a Silverlight 1.0 JavaScript mindset to a Silverlight 1.1 C# mindset isn't terribly difficult, but there are little traps here and there. For example, to download and display an image, you need to create and configure a Downloader object.
In JavaScript:
var downloader = this.control.createObject("downloader");
downloader.addEventListener("completed",
Silverlight.createDelegate(this, this._onDownloaderComplete));
downloader.open("GET", "YodaDog.jpg");
downloader.send();
In C#:
Downloader download = new Downloader();
download.Completed += new EventHandler(download_Completed);
download.Open("GET", new Uri("YodaDog.jpg", UriKind.Relative));
download.Send();
The obvious differences are the wiring of events and construction of the Downloader object. However, the basic patterns in the code are true to their environments and easy to remember. It's the little things that bite you, for instance the Uri passed into the downloader. If the C# version looked like this:
download.Open("GET", new Uri("YodaDog.jpg"));
… then it still compiles and looks like its JavaScript counterpart, but unfortunately doesn't work. We have to explicitly tell the Uri constructor we are passing a relative URI.
The code for getting the downloaded image into an Image control is almost identical.
JavaScript:
_onDownloaderComplete: function(sender, eventArgs)
{
this._mainImage.SetSource(sender, "");
}
C#:
void download_Completed(object sender, EventArgs e)
{
this._mainImage.SetSource((Downloader)sender, "");
}
Presto! Yoda dog appears:
But what if we want to take Yoda dog off the screen? The following JavaScript works:
Edit - Oops! The wrong code was pasted here, but is now fixed.
onMouseButtonUp: function(sender, eventArgs)
{
this._mainImage.source = null;
},
But the equivalent C# code will leave Yoda dog on the screen*.
void Page_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
this._mainImage.Source = null;
}
Instead, an empty URI is needed:
void Page_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
this._mainImage.Source = new Uri("", UriKind.Relative);
}
Of course, the XAML remains the same in both environments.
* Just look at the expression on the dog's face. You know what she is thinking? She's thinking: "Tonight, my owner's favorite shoes become a shredded pile of wet leather…".
 |
Wednesday, October 03, 2007
ScottGu announced that Microsoft is releasing the source code for the .NET Libraries. The cheering from developers won’t subside for some time. Reflector is a great tool for peering into assemblies, but nothing beats breakpoints and an Immediate Window for seeing what is happening in managed code.
Developers will now be able to reference the implementation of production quality components. Using Windows Workflow as an example, a developer can use the base activity library and WF service implementations as a guide when extending WF.
Looking at the design time implementation of various components in the presentation frameworks will also, I think, be a great advantage.
Is there a drawback? Sure - I can imagine some people wrapping themselves around a tree trying to find a bug in an underlying framework when they really need to be looking at their own code. I know this, because I’ve been guilty of this behavior myself. :)
|