http://www.nikhilk.net/Category.aspx?id=1
Contains all posts from my weblog.
Last checked about 3 hours ago.
3 people have subscribed to this feed.
post frequency (last month)
PostRank™
From Nikhil Kothari's Weblog, 1 month ago,
0 comments
FxCop is a great tool to help ensure consistency of .NET code and to help push quality upstream in the development process by reinforcing design guidelines and flagging some potential issues that can be detected through static analysis of your assemblies. Last week, the FxCop team released v1.36 of the standalone tool.
The design guidelines are documented and explained in the Framework Design Guidelines book, which also has a section dedicated to FxCop. The interesting thing is a good chunk of the guidelines also apply to Ajax, as they're first and foremost targeted at the general task of creating usable APIs and frameworks. I'd highly recommend familiarizing yourself with them if you're writing .NET code.
This announcement spurred me into demonstrating the integration of this essential .NET tool into the Ajax development process. One of the key value propositions of Script# is enabling you to leverage existing .NET tooling in the context of building script-based applications and components. FxCop is a key scenario in that regard.
I just released v0.5.1.0 of script# which is a minor increment that includes a few bug fixes, the ability to define overloads and methods with optional parameters, and for those using Script# against the Microsoft Ajax library, the corresponding c# assembly has been updated to account for the addition of history APIs in .NET 3.5 SP1. Additionally, I've taken the chance to tweak the project templates and installer ever so slightly to allow you to much more easily use FxCop.
Here is a quick walkthrough, assuming you've installed this latest version of Script# and FxCop. I'll create a super-simple app for the purposes of demonstration that fetches a list of bookmarks via an XMLHttp request (it is Ajax after all) and display the results in an HTML list. Undoubtedly, you'll have a more interesting code-base for FxCop to analyze.
In Visual Studio, create a new Script# ClassLibrary.
Lets add some code. Replace the contents of Class1.cs with the following c# code:
using System;
using System.DHTML;
namespace Bookmarking {
[Record]
publicsealedclass Bookmark {
publicstring title;
publicstring url;
}
publicclass Bookmarks {
publicstaticvoid LoadBookmarks(DOMElement list) {
string bookmarkService = "Bookmarks.ashx/GetList";
XMLHttpRequest request = new XMLHttpRequest();
request.Open("GET", bookmarkService);
request.Onreadystatechange = delegate() {
if ((request.ReadyState == 4) && (request.Status == 200)) {
Bookmark[] bookmarks =
(Bookmark[])Script.Eval(request.ResponseText);
foreach (Bookmark b in bookmarks) {
AnchorElement anchor = (AnchorElement)Document.CreateElement("a");
anchor.Href = b.url;
anchor.InnerHTML = b.title;
DOMElement listElement = Document.CreateElement("li");
listElement.AppendChild(anchor);
list.AppendChild(listElement);
}
}
};
request.Send(null);
}
}
}
For the sake of completeness in this post, here is the debug flavor of the generated script (the release flavor is minimized and condensed):
Type.createNamespace('Bookmarking'); Bookmarking.Bookmarks = function Bookmarking_Bookmarks() { } Bookmarking.Bookmarks.loadBookmarks = function Bookmarking_Bookmarks$loadBookmarks(list) { var bookmarkService = 'Bookmarks.ashx/GetList'; var request = new XMLHttpRequest(); request.open('GET', bookmarkService); request.onreadystatechange = Delegate.create(null, function() { if ((request.readyState === 4) && (request.status === 200)) { var bookmarks = eval(request.responseText); var $enum1 = bookmarks.getEnumerator(); while ($enum1.moveNext()) { var b = $enum1.get_current(); var anchor = document.createElement('a'); anchor.href = b.url; anchor.innerHTML = b.title; var listElement = document.createElement('li'); listElement.appendChild(anchor); list.appendChild(listElement); } } }); request.send(null); } Bookmarking.Bookmarks.createClass('Bookmarking.Bookmarks');
In addition, an assembly was generated by the regular c# compiler. If you open up the project folder in Explorer, you'll see a Project.FxCop file in the Properties subfolder. Double-click that, and FxCop should open up. The project has been already set up to analyze the resulting assembly.
You'll see the warning around our use of Script.Eval. For our scenario using Script.Eval to generate an eval expression in script is a legitimate use of the functionality to deserialize the list of bookmarks from the XMLHttp response, so we want to suppress this warning. Lets go back to the c# code, and add a source exclusion. There are also some other warnings suggesting our class should be static (which I'll fix), and on public fields on our Bookmark class (which I'll suppress, given the Bookmark class represents a JSON object returned from the service).
using System;
usingSystem.Diagnostics.CodeAnalysis;using System.DHTML;
namespace Bookmarking {
[Record]
publicsealedclass Bookmark {
[SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]publicstring title;
[SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields")]publicstring url;
}
publicstaticclass Bookmarks {
[SuppressMessage("Script.General", "SS0001:ScriptAvoidEval", Justification = "Using Script.Eval to perform JSON deserialization")]publicstaticvoid LoadBookmarks(DOMElement list) {
...
}
}
}
If you compile this and re-run the tool, you'll see the warnings goes away. Your code now documents the suppression along with the justification in a standard manner. If Script.Eval did not make sense (because of its perf overhead), you now know about a potential issue, and a possibly better way to go about implementing your code, should that be warranted.
I think the real power comes with creating custom FxCop rules that go beyond the default set of design guidelines and cater to script-specific scenarios. The Script.Eval check is a custom rule that is the first rule I have implemented.
Other initial ideas for basic rules might be to flag use of browser-specific or non-standard script APIs, or creating deep class hierarchies that are costly in script. I'd love to hear from if they have other ideas of APIs or patterns to flags, or design guidelines to look for and enforce via custom rules.
From Nikhil Kothari's Weblog, 2 months ago,
0 comments
My recent Silverlight-related blog posts have shared a common theme: creating declarative views - whether it is declaratively attaching behaviors such as auto-complete, or declaratively hooking up views to their associated view models, or declaratively authoring themes and loading them. This post is the next installment in that overall series - declarative effects and transitions.
XAML and Silverlight provide some building blocks like storyboards and now visual state manager that enable some powerful mechanisms for adding visual pizzaz to your application's user interface. However, I sometimes find they are too general and low-level a solution, requiring one to go into custom template mode all too often, whether it is to define storyboards, or new states and transitions - more often than not, I just want a simple pre-packaged effect that I can attach to an element and associate with some user interaction. Furthermore, the current lack of event triggers requires code to be added to views to begin and stop those storyboards or switch from one visual state to another. Think powerpoint - the prepackaged animation effects with some basic triggers go a long way.
That sort of problem space, and approach inspired me to see what can be done in Silverlight today, resulting in the addition of a Glitz namespace in my Silverlight.FX work. (The name is no coincidence. For those that remember our Ajax framework's early days, back when it was called Atlas, I had written a Glitz script animation framework there, and then wrote one for Script# - this Silverlight work started its life when I recompiled my Script# code as actual managed code rather than into JavaScript!)
On the top is a set of screen-shots of a simple application that consumes some of these effects. You have to click it to run it live to actually see the effects! The application basically fetches the current weather and the forecast for the supplied zip code (and yes, it seems summer has decided to take a break here in the northwest). All the core logic is implemented in a view model that is decoupled from the view, and is easily tested. It is responsible for talking to the data layer, which is responsible for invoking a web service and unpacking the JSON data returned from the service. The view is completely declarative and is about 130 lines of XAML. It uses behaviors (for things like filtering zip code input to numbers), actions to hook into the view model, and of course effects and transitions for some subtle bits of glitz.
I'll share a couple of snippets of the XAML, just to get the general programming model across.
First is the Load button that not only instructs the view model to load weather for the supplied zip code, but also plays a transition to go from the initial screen to the next.
<
fxui:Button
Content
="Load"
fxui:ButtonEvents.Click="$model.LookupWeather(zipCodeTextBox.Text)"><fxglitz:Effects.ClickEffect><fxglitz:SlideTransitionMode="Left"TargetName="layoutGrid"Duration="00:00:1.25"Reversible="False"Easing="ElasticInOut"/></fxglitz:Effects.ClickEffect></fxui:Button>
Second, is an effect attached to the logical mouse hover event (which implies playing the effect in forward direction on mouse enter, and playing the same effect in reverse direction in response to the mouse out event) on the vertical forecast bars in the 3rd screen above.
<
Border
Background
="#20000000"
>
<
fxglitz:Effects.HoverEffect
>
<
fxglitz:ColorFillEffect
FillColor
="#80000000"
Duration
="00:00:0.5"
Easing
="QuadraticInOut"
/>
</
fxglitz:Effects.HoverEffect
>
...
</Border>
You can download the framework, and the associated samples here. Very soon I will be putting this up on my projects site for folks to track in a bit more organized way than following just the blog posts.
Glitz: Effects and Transitions
An effect is basically a behavior that can be attached to an element and triggered upon some event. Each effect encapsulates two animations - a forward animation and a reverse animation that it alternates between. Effects can be told to play in forward only mode, reverse only mode, or automatically reverse after completing their forward animation.
Effects are extensible. Some of the effects I have built into the framework include: Resize, Move, Spin, Fade, Highlight, ColorFill, Shake, and Pulsate. Effects are composable. CompositeEffect can play a set of child effects in parallel or in sequence.
Transitions derive from Effect, and can be attached to a panel that contain two child elements. The transition basically uses animations to hide the top element to reveal the bottom element. Like effects, transitions have forward and reverse behavior that allow them to revert back to the top element. So far the framework has four transitions built in: CrossFade, Blinds, Slide, and Flip.
Effects and transitions are both attached to UI elements as behaviors. The Effects class exposes various attached properties such as ClickEffect, HoverEffect, FocusEffect, LoadEffect, and TimedEffect. As the names suggest effects and transitions can be hooked up to mouse clicks, mouse hovers, keyboard focus, load events and timer tick events.
Effects and transitions build on a procedural animation framework that makes it very simple to write new and interesting behaviors and computed animations. The animation framework itself can be used independently of the effects layer. It provides the ability to implement unbounded (by time) animations, as well as duration-bound animations. The duration bound animations can easily tap into a set of easing functions commonly thought of as tweening options, that allow animations to accelerate on start (ease in), decelerate on end (ease out), as well as easily provide the perception of elastic rubber bands or bounce behaviors.
Effect and Transition Gallery
If you download the code, you'll see a number of effect and transition classes in the Silverlight.FX.UserInterface.Glitz namespace. Most of those can be seen in action in the screen shot below (again click to run).
For example, here is the complete XAML for the Highlight effect:
<
Grid
>
<
Grid.RowDefinitions
>...</Grid.RowDefinitions><fxglitz:Effects.ClickEffect><fxglitz:HighlightEffectTargetName="highlightImage"HighlightColor="Yellow"Duration="00:00:01"/></fxglitz:Effects.ClickEffect><Borderx:Name="highlightImage"><ImageSource="/Silverlight.png"/></Border><TextBlockGrid.Row="1">Highlight</TextBlock></Grid>
For a transition example, here is the complete XAML for the Flip effect:
<
Grid
>
<
Grid.RowDefinitions
>...</Grid.RowDefinitions><fxglitz:Effects.ClickEffect><fxglitz:FlipTransitionTargetName="flipContainer"Duration="00:00:1"Easing="QuadraticInOut"/></fxglitz:Effects.ClickEffect><Gridx:Name="flipContainer"><ImageSource="/MS.net.png"/><ImageSource="/Silverlight.png"/></Grid><TextBlockStyle="{StaticResource staticText}"Grid.Row="1">Flip</TextBlock></Grid>
What other interesting effects and transitions would you love to see? Or better yet, try building one and using the underlying procedural animation framework, and share the experience.
Adding Effects and Transitions to Controls?
One thing I haven't shown in the samples, but I've just begun prototyping is higher-level controls that have a property of type Effect. To share one scenario, imagine a List control that has ShowEffect and HideEffect properties - it plays the effect assigned to ShowEffect on any item that is added to the list, and plays the effect assigned to HideEffect on any item that is removed from the list. This will allow creating a web 2.0 style list user interface (ala JQuery/scriptaculous) completely declaratively using pre-packaged animation effects.
From Nikhil Kothari's Weblog, 2 months ago,
0 comments
Yesterday, I received my copy of "Advanced ASP.NET Ajax Server Controls". I had a chance to get an early peek at the content when Adam and Joel asked me to write the foreword for their book.
One thing I liked about this book is that this is one of the few that dive deep into the framework, its architecture and extensibility, and address the power-user/developer scenarios.
If you're building applications in Ajax today, and want to take that to the next level, you'll want to look into the platform deeper beyond the out-of-the-box features i.e. its extensibility. You'll specifically want to build reusable components and controls, on both the server and on the client. Check out this book on more details like "the client script framework", "the script application object", "localization" and "the control toolkit" amongst many other relevant topics.
From Nikhil Kothari's Weblog, 3 months ago,
0 comments
From Nikhil Kothari's Weblog, 3 months ago,
0 comments
If you're developing a web site, especially a public facing site, search and indexability are probably high on your list of requirements and priorities. Yesterday, searchability of rich internet applications got extra attention with Adobe's announcement that it is providing technology to search engines to improve indexability of swf/flash-based applications.
This is particularly interesting to me as I think getting the right SEO behavior for RIAs is based on looking at end-to-end solutions that involve complementary server-side techniques (guess that is not totally unexpected from someone like me who has been working on asp.net). I've also been presenting on Search and RIA and enabling indexability for Silverlight and Ajax apps for a couple of years at various conferences... links to those below.
There has always been a question mark around indexability of RIAs, whether they're built in Flash, or Silverlight, or even Ajax. The fundamental problem is that static indexing of a RIA is likely to turn up only the user interface of the application, and not the interesting and meaningful data fetched by application logic and presented dynamically to the user. Indexing an application binary or script is akin to having desktop search index winword.exe instead of your documents... not very useful. Most folks are now seeing indexing something like a raw swf binary as less and less useful, as applications become more and more dynamic.
The two key things around improving SEO (besides various general techniques like URL canonicalization, friendly URLs and search-engine friendly URL rewriting) are ensuring indexability and facilitating relevance. Indexability is created through addressing the what content is visible to the crawler, as well as where the crawler should look. Relevance is primarily addressed through creating deep linkable content and interesting content (so folks actually link to it).
The Adobe/Google announcement takes indexing one a step further beyond indexing static binary content, by attempting to simulate human behavior and interacting with the application to extract textual content and links from the application. I can see how automated clicks and the like might allow the crawler to cause an application to execute some partial logic, but a lot of application interaction is driven off of actual meaningful text input (eg. keywords in a search input box) where meaningful often depends on the specific application in question. The announcement does not go into any details... somewhat strange, I think, so there is naturally some guessing going on. The comment stream also contains a good mix of folks questioning whether the approach will even work? (for example here and here)
It is interesting to see the buzz - it is good to see search engines at least begin to think beyond indexing static HTML. Technically speaking, this sort of approach to indexability lends itself to Silverlight apps as well pretty easily. First a Silverlight application packaged in a xap file is easily cracked open without a special SDK - it is simply a zip file after all. Any static textual xaml content is easily parsed by virtue of being XML. Second it is easy to embed and extract metadata via an additional file within the zip archive. Third, the Silverlight DOM itself can be easily walked and inspected programmatically to detect all text, links and images that are being visualized by the control. Finally, it is possible to automate the application thanks to the extensible API that Silverlight offers for enabling accessibility and screen reader capabilties. Additionally, Silverlight apps can also support deep linking which is also important for facilitating relevance. Essentially, Silverlight provides simple APIs to allow the app to easily consume the URL it was loaded from, and use information on the URL query string to load and display appropriate data.
All that said, it will be interesting to see how well this approach pans out, as there are a number of challenges in simulating a user realistically, especially without any hints provided by the application developer. In the mean time, this is as good as any a time to share my slide deck on building indexable Silverlight applications that I used in my presentation at SMX, a search conference that took place last month here in Seattle.
The deck above illustrates the pattern for supplying alternate content with sample markup. At a high-level, the approach can be summarized as combining client-side logic with server-side rendering and sitemaps to address the "what" and "where" of indexability. The specific implementation of the pattern is interesting in how it achieves alternate content without requiring the developer to implement two applications and do double work.
I especially like the pattern because it works today, across search engines, applies to Silverlight/Flash apps as well as Ajax apps, and has a number of side-benefits around networking optimization and graceful degradation in script-less environments as listed in the deck above. Its always nice to pick a single pattern that can help solve multiple problems that Web developers encounter regularly. I first blogged about this approach back in 2007 right after MIX07. I had a chance to present it once more at MIX08, and you can actually check out the presentation and demo in the session video (skip ahead about 42 minutes into the talk for the part on indexability).
Any questions on the approach? Feel free to ask below. Also, I am curious what are your thoughts on the alternate content approach, or on the overall subject of search for RIAs?
From Nikhil Kothari's Weblog, 3 months ago,
0 comments
In my last post, I posted an implementation of the ViewModel or M-V-VM pattern for use in Silverlight applications. This pattern allows you to decouple your view presentation logic and data from the view, thereby facilitating independent development/design of your app as well as easier unit testing of your application code. I will highly recommend you check out that post for the more detailed description and intro sample if you haven't already done so, as this post will build further on that.
Now that I've done some additional exploration, and prototyping, I think the syntax used to define the glue between the View and the ViewModel as first presented was a bit suboptimal, and could be re-done to be much more intuitive. Read on to find out more.
Amazon Search Sample
In that post, I had a simple Amazon Search app to demonstrate the view model pattern. Focusing on the search aspect of the scenario, here are the relevant snippets of code and XAML forming the view model and the view respectively:
public
class SearchViewModel : Model {
...
publicvoid Search(string keyword) {
...
}
}
<vm:Viewxmlns="..."xmlns:x="..."xmlns:vm="clr-namespace:Silverlight.FX.ViewModel;assembly=Silverlight.FX"xmlns:app="clr-namespace:AmazonSearch.Views"><vm:View.Model><app:SearchViewModel/></vm:View.Model>
...
<ButtonContent="Search"IsEnabled="{Binding CanSearch}"><vm:ButtonEvents.Click><vm:InvokeMethodMethodName="Search"><vm:ElementParameterElementName="searchTextBox"ElementProperty="Text"/></vm:InvokeMethod></vm:ButtonEvents.Click></Button>
...
</vm:View>
Action behaviors were used to implement the glue that allows a View to invoke some operation defined on the View Model in response to an event. As you can see in the example above, an InvokeMethod action has been associated with the Button's Click event and it is set up to invoke the Search method on the ViewModel passing in the Text in the specified TextBox.
InvokeMethod Shortcomings in Associating View to ViewModel
The first issue with this approach is that it isn't super-friendly. The XAML to define a list of parameters gets verbose very quickly. Secondly it doesn't allow for a number of scenarios, around passing in arbitrary data into the view model. I noted in the post that I might want to do something like this instead:
<
Button
Content
="Search"
Click
="{Action InvokeMethod Search(searchTextBox.Text)}"
IsEnabled
="{Binding CanSearch}"
/>
I got to thinking about this after writing and re-reading the post myself, and what occurred to me is that this is quite a slippery slope, eventually leading to a full expression language. Not wanting to create such a thing, I started reflecting on what could be repurposed.
I realized the Dynamic Language Runtime (DLR) would be a perfect fit. It is just the right designer-friendly glue that can be used to call into the bulk of the logic that is itself developed using statically compiled code that exists in the view model and the rest of the app. I could scope the use of the script down to a minimum by hosting the DLR to execute just script expressions. The DLR would also give me the benefit of using something like JavaScript, and potentially on any another scripting engine created to run on the DLR.
DLR-based InvokeScript
So I got to work, and created an InvokeScript action (leveraging the extensibility of actions), and got this working:
<
Button
Content
="Search"
IsEnabled
="{Binding CanSearch}"
>
<
vm:ButtonEvents.Click
>
<
vm:InvokeScript
Script
="$model.Search(searchTextBox.Text)"
/>
</
vm:ButtonEvents.Click
>
</
Button
>
The verbose XAML for defining parameters was gone, and I didn't have to create my own mini-language. However this is still too much XAML for me. With a bit more work, I was able to get the following syntax to work:
<
Button
Content
="Search"
vm:ButtonEvents.Click="$model.Search(searchTextBox.Text)"
/>
The InvokeScript does its work by hosting the DLR. As a DLR host the InvokeScript action is able to resolve things like $model to the current ViewModel instance. It also resolves "searchTextBox" when the script engine hits that. To do so, it first looks to see if it's a property of the Button (which it isn't, so it continues to search). Next it looks to see if it can find it in the visual tree using FindName or in the resources dictionary via a recursive FindResource (and it does find it in the tree). The bottom line is the script expression is simple and intuitive. And the DLR host does all the work through an intuitive set of rules, rather than have those be spelt out in a verbose form in XAML.This has me pretty satisfied.
As an aside, the script expression can also reference a variable named $event that represents the current event. This is useful if there is some interesting data in the event argument that you want to send across to the ViewModel operation (eg. mouse coordinates in a mouse event) or some property on the event argument you want to set by using the return value of the operation itself (eg. Canceled on a CancelEventArgs).
Essentially the InvokeScript action creates a little data flow pipe as shown below that flows event information and pieces of data from the View into the operation in the ViewModel. The pipe is also able to flow back the return value from the operation for use in the View, even though it hasn't been depicted here.
You might be wondering how the script engine is instantiated. This gives me a chance to introduce my framework's derived Application type that is used in App.xaml - XApplication. Amongst various other pieces of functionality, XApplication provides the semantics of being a global service container. The application developer can write this markup in App.xaml to declaratively define the instance of a ScriptService that will be used in their application. At runtime, the InvokeScript action looks for the current XApplication instance, and queries for the ScriptService service and uses the ScriptEngine that the service is responsible for instantiating and managing based on the specified language.
<
fxa:XApplication
xmlns
="..."
xmlns:x
="..."
xmlns:fxa
="clr-namespace:Silverlight.FX.Applications;assembly=Silverlight.FX"
>
<
fxa:XApplication.Services
>
<
fxa:ScriptService
ScriptLanguage
="JavaScript"
/>
</
fxa:XApplication.Services
>
</
fxa:XApplication
>
Note that you'll need to package the DLR assemblies (Microsoft.Scripting.*.dll) and the language specific ones (such as Microsoft.Jscript.*.dll for JavaScript) into your application's xap package. These are part of the Silverlight 2 SDK. Just add a reference to those dlls in your application project in Visual Studio and the XAP packager will do the right thing to include them in as part of the build process.
Code and Summary
As usual you can download the all of the code, sample, and framework to play with this to your heart's content. Do you think the use of DLR here helps signficantly simplify the view model pattern?
From Nikhil Kothari's Weblog, 3 months ago,
0 comments
The MVC pattern is quite widespread, and lots has been written about it. Clearly, it is a popular addition to ASP.NET. MVC works especially well for request/response style web apps as well as in navigation-based client apps.
The ViewModel pattern, or more accurately said, the Model-View-ViewModel (M-V-VM) pattern on the other hand hasn't been discussed a whole lot as a formal pattern. However, it is a really nice pattern that is very well suited to client apps that generally feature interactive or dynamic user interfaces that are data-bound and implemented declaratively, for example, most Silverlight apps.
Introduction to ViewModel
This is a very brief description of the pattern, and how it is both similar and dissimilar from the code-behind pattern that is in vogue.
You've probably been doing something quite close all along. I am sure you've written some piece of UI that is associated with some code-behind that is responsible for loading in data, and implementing logic to handle user input and interaction in the form of event handlers. The figure on the right illustrates the mechanics of the code-behind pattern. One of the big problems with code-behind is that it mixes your logic with presentation and couples it deeply, which gets in the way of testability. Another problem is that it leads to co-mingling of designer-centric parts of the app with developer-focused parts of the app. Often times these implications may be ok for quick-and-dirty prototyping but would be nice to avoid for real apps.
The ViewModel pattern attempts to address these problems by encouraging separation of logic from the presentation. The data being presented is implemented as properties on the ViewModel, that the View consumes via data-binding. Secondly, most of the backing logic and operations are implemented as methods on the ViewModel that the view invokes via commanding. The key constraint is that the ViewModel is not dependent on View concepts such as choice of controls. The figure on the left illustrates this pattern. It is not a fundamentally different world, but rather something closer to a rearrangement and refactoring of the same pieces.
Some folks might argue that all of code-behind is to be removed. I tend to think that some may remain, specifically, to facilitate view-to-view interactions that cannot be expressed declaratively in XAML easily, hence the sliver of code-behind in the view.
This is simply one amongst many patterns that encourage discipline over what code goes where, how it is related to other code etc. The goal here is to think about how to get both long-term benefits from practicing discipline, as well as make it suitable for those smaller apps and quick-and-dirty experimental apps, by making this pattern emerge naturally from tooling guidance. I won't cover tooling today; perhaps another blog post on this down the road.
ViewModel In Action
Enough theory! Onto a running app... I've built a simple Amazon Search application using the ViewModel pattern, and the Silverlight.FX framework I've built to support it on top of Silverlight 2. You can play with it here, as well as download the entire solution containing code for the sample, associated sampling of unit tests, and the framework it builds upon.
Implementing ViewModel via Action Behaviors
Both John Gossman and Dan Crevier have blogged about this pattern in the context of WPF, where their approach builds on data-binding and commanding. Silverlight supports a subset of data-binding features, but doesn't currently provide a commanding mechanism. Instead of commanding, I'll build the glue between the view and the operations defined in the view model via Actions (as you'll see in a moment) that are then hooked up via my behaviors framework.
Lets take a brief look at the implementation. I won't cover all the details, as you have the code and can step through as deeply as you'd prefer. On the right is my application's project structure.
I have my data model defined in the Data namespace. The Product class is an entity that has properties like Title, ImageUrl, ASIN etc. The Catalog class provides data access logic built by consuming the Amazon ECS REST APIs and the WebClient object that supports cross-domain networking. This code is pretty straightforward and commonplace. The catalog class implements the ICatalog interface. This has been defined so that the data access functionality can be mocked in a straightforward way for unit testing (more on that at the end).
The ViewModel is where it starts to get interesting. Being a developer, I'll start with that. It is defined in SearchView.model.cs as follows:
public
class SearchViewModel : Model {
private IEnumerable<Product> _products;
privatestring _keyword;
privatebool _searching;
publicbool CanSearch {
get {
return !IsSearching;
}
}
publicbool IsSearching {
get { return _searching; }
private set {
_searching = value;
RaisePropertyChanged("IsSearching", "CanSearch");
}
}
public IEnumerable<Product> Products {
get { return _products; }
private set { _products = value; RaisePropertyChanged("Products"); }
}
publicvoid Search(string keyword) {
_keyword = keyword;
Searching = true;
Catalog catalog = new Catalog();
catalog.SelectProducts(keyword, OnCatalogProductsSelected);
}
privatevoid OnCatalogProductsSelected(string keyword, Ienumerable<Products> products) {
if (keyword != _keyword) { return; }
Products = catalog.Products;
Searching = false;
}
}
The first thing to notice is that this class is completely independent from the UI. As such it can be tested quite easily. It simply represents a list of products, and the ability to perform a search that populates that list of products. It does this by consuming the data model.
This class derives from a class called Model from my framework, which supplies a default implementation of INotifyPropertyChange. The Model class also does some other nice things like cache PropertyChangedEventArg instances, and make sure change events are raised on the appropriate thread.
The next thing to implement is the view. Here you might imagine its is something that is worked upon predominantly and independently by a designer in Blend. The designer is free to choose the controls, lay them out, add animations and other subtle visual polish. As the UI comes together it might then be declaratively bound to the properties and methods that the developer has made available in the view model.
<
vm:View
xmlns
="..."
xmlns:x
="..."
xmlns:vm
="clr-namespace:Silverlight.FX.ViewModel;assembly=Silverlight.FX"
xmlns:app
="clr-namespace:AmazonSearch.Views"
>
<
vm:View.Model
>
<
app:SearchViewModel
/>
</
vm:View.Model
>
<
Grid
>
<
TextBox
x:Name
="searchTextBox"
/>
<
Button
Content
="Search"
IsEnabled
="{Binding CanSearch}"
>
<
vm:ButtonEvents.Click
>
<
vm:InvokeMethod
MethodName
="Search"
>
<
vm:ElementParameter
ElementName
="searchTextBox"
ElementProperty
="Text"
/>
</
vm:InvokeMethod
>
</
vm:ButtonEvents.Click
>
</
Button
>
<
ItemsControl
ItemsSource
="{Binding Products}"
>
<
ItemsControl.ItemTemplate
>
<
DataTemplate
><
app:ProductView
/></
DataTemplate
>
</
ItemsControl.ItemTemplate
>
</
ItemsControl
>
</
Grid
>
</
vm:View
>
The view is implemented by deriving from View, which is in turn derived from UserControl. This is just for convenience. It adds the concrete notion of an associated Model that is assigned to the DataContext property so it is inherited by the contained controls.
The ItemsControl is bound to the list of products via vanilla data-binding already present in Silverlight.
The equivalent of commands are implemented using Actions. Actions are simply behaviors that can be attached to an element, via an attached property that provides event trigger semantics. In the sample, the ViewModel exposes a CanSearch property and a Search method that provide commanding-like semantics in a simple manner. The search button's IsEnabled property is bound to CanSearch, and its Click event is bound to the Search method.
I am not completely thrilled with the syntax, but this is perhaps the best that is doable, until the ability to define markup extensions becomes available in some future Silverlight version, and I might eventually be able to declare something like this instead:
<
Button
Content
="Search"
Click
="{Action InvokeMethod Search(searchTextBox.Text)}"
IsEnabled
="{Binding CanSearch}"
/>
Actions are actually quite expressive since they are extensible and can encapsulate stock behaviors (the equivalent of stock commands). In the framework I have actions that work against storyboards (eg. PlayStoryboard), set properties etc. Here is another example of an action to perform the navigation whenever a search result is clicked.
<
Image
Source
="{Binding ImageUrl}"
>
<
vm:MouseEvents.MouseLeftButtonDown
>
<
vm:Navigate
NavigateUrl
="{Binding ItemUrl}"
Target
="Amazon"
/>
</
vm:MouseEvents.MouseLeftButtonDown
>
</
Image
>
Unit Testing the View Model
One of the benefits of separation of concerns is easier testing of a greater portion of the application's code and functionality. Specifically, as the ViewModel is itself independent of the user interface, I should be able to easily unit test it.
Here I am going to leverage the Silverlight Unit Testing Framework to author tests for my ViewModel and then run them. This is also the place where I am going to leverage the fact that I defined an ICatalog interface earlier to represent my data access layer. For the unit tests, I am going to create a mock catalog implementation, that doesn't rely on making calls to the Amazon service.
Here is one of my mock catalog implementations that returns a dummy product.
public
class TestCatalog : ICatalog {
publicvoid SelectProducts(string keyword,
Action<string, IEnumerable<Product>> productsCallback) {
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(2);
timer.Tick += delegate(object sender, EventArgs e) {
Product testProduct =
new Product {
ASIN = "1",
By = "TestAuthor",
ImageUrl = "http://www.example.com",
ItemUrl = "http://www.example.com",
Title = "Test Title"
};
productsCallback(keyword, new Product[] { testProduct });
};
}
}
And here is one of the tests defined in my test class. Note that I am using the ability to write async tests.
[TestClass] publicclass SearchViewModelTest : SilverlightTest { [TestMethod] [Asynchronous] [Description("Test a typical search result.")] publicvoid TestSearchResult() { ICatalog mockCatalog = new TestCatalog(); bool productsChanged = false; SearchViewModel viewModel = new SearchViewModel(mockCatalog); ((INotifyPropertyChanged)viewModel).PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Products") { productsChanged = true; } }; viewModel.Search("xyz"); EnqueueConditional(() => productsChanged); EnqueueCallback(() => Assert.AreNotEqual(viewModel.Products, null, "Expected non-null products list.")); EnqueueCallback(() => Assert.AreNotEqual(viewModel.Products.Count(), 0, "Expected non-empty products list.")); EnqueueTestComplete(); } }
Using the Unit Testing engine to execute my tests in the browser, i.e. running in the context of the Silverlight CLR, I see the following result, indicating goodness...
Summary
Hopefully this sample gave a good flavor of what the ViewModel pattern is all about, and how action behaviors can help create the bridge between the View and the ViewModel in Silverlight today. There are various other interesting discussion points and further exploration that relate to this, so stay tuned, but in the mean time I am curious what people think, and what questions arise as well, to help guide both the discussion, and the feature as its worked in into the framework.
From Nikhil Kothari's Weblog, 4 months ago,
0 comments
A couple of weeks back, StyleCop, which used to be an internal tool was rebranded and publicly released as Microsoft Source Analysis. Right around that time, we were having an internal discussion within the team around what sort of coding style guidelines we should put in place for a new project.
Such discussions are always fun, and can serve as fodder for ongoing back and forth unless someone just gives in. If design guidelines are debatable (eg. Id vs ID), style guidelines are at least an order of magnitude more debatable; everyone has an opinion and a set of preferences around source code. I think what we really need is a system around how code is a model, not just text, and the editor is simply a view over that model that reflects a user's choice. In the meantime, we have guidelines, and tools such as StyleCop to help enforce them.
Speaking about debatable guidelines, it seems one of the big point of debates was around the tool's default rule that tabs should not be used for indentation. I personally agree with that one, but I'll throw in an even more debatable rule that is a preference of mine (which unfortunately the tool doesn't default to): K&R bracing style. You've already seen me use it in blog posts that contains code snippets. Ultimately, independent of specific stylistic choices, a consistent and predictable code base is a first step toward facilitating readability and discoverability. Definitely check out the tool if you haven't already.
For those curious, I actually have a coding guidelines document I use that is mostly based on what we agreed on for the ASP.NET code base some years back. I tried to tweak the settings offered by the tool to create a matching set, though I think I'll need to write some custom rules around ordering and spacing if I want the tool to exactly match my preferences.
On a related note, this tool completely works as expected with Script# projects, as I expected. So, if you're using Script# to build an Ajax app or component, you too can now benefit from this tool. This just shows how a good chunk of both new and existing .NET tooling can be repurposed without much work.
From Nikhil Kothari's Weblog, 4 months ago,
0 comments
Every year, Microsoft holds an Engineering Excellence Conference. This is that week. In addition to a variety of conference sessions around engineering practices and trustworthy computing, a number of awards are handed out during the opening keynote.
One of the awards that is handed out recognizes innovation in tools and practices that promote better engineering and have broad impact, and adoption. I am glad to share that this year, Script# was presented this award. :-)
In terms of impact and adoption, a number of product teams across Microsoft are using Script# to implement their Ajax-based Web experiences. It is always fun to see folks adopting something you've worked on and creating some amazing applications, but more importantly, the award helps make a case for the productivity wins and the engineering discipline that Script# can bring to Ajax development by leveraging the .NET programming model and tools. In addition to Live Messenger and Live Mesh, there are others that are in the works (that I don't think I can share publicly just yet), but as always, I'll share as and when they do become public.
I'd like to say thanks to those who helped champion the technology early on beyond just a personal project, and help improve the project - folks like Steve Gordon, Shaofeng Zhu and Justin Rockwood from Microsoft, and Wei Zhu, who is now at Facebook, as well as the many others, internal and external, who have shared feedback, bug reports and enthusiasm over the course of the last couple of years.
I've been a bit on the busy side recently, but still to come is sharing sources over on the CodePlex site in addition to the ongoing discussion forums.
From Nikhil Kothari's Weblog, 5 months ago,
0 comments
Yesterday I blogged about using and creating behaviors in Silverlight. This post will walk you through an autocomplete behavior that will hopefully furher crystallize the behavior concept.
To recap, a behavior is simply an object that can be declaratively attached to another component to extend the built in functionality of that component. Typically a behavior will encapsulate some event handling logic. This event handling logic could have been written by the app developer in their code-behind, but moving it into a behavior makes it much more encapsulated and suited for reuse. It has the nice side-effect of making things a bit more designer-friendly by cleaning up the code-behind and turning things into a more XAML-friendly form.
Remember Google Suggest? That kicked off a spree of auto-complete implementations for use in Ajax apps including the one we did for ASP.NET Ajax (and later in the Ajax Control Toolkit). The AutoComplete behavior is very similar. It can be used to suggest various completions based on the text that a user has entered so far. This behavior allows extending the standard Silverlight TextBox control (as well as the WatermarkTextBox control). This post will cover various scenarios accomodated by the behavior I've put together.
The screenshot above illustrates the type of experience you can add to any TextBox. You can see and play with a live demo by scrolling toward the end of this post (this requires Silverlight 2). Of course, all of the code is available as well, so you can include this into your own app.
Scenario 1: Basic completion scenario
Lets assume I've got a TextBox on a form that allows your user to enter in the name of a city, and I also have a service on the server that accepts a string prefix and returns a set of matching city names as an array of strings (serialized using the JSON format). I'd like to hook the two of them together to improve the user experience of the form, by offering a list of suggestions.
Here's the most basic use of the AutoComplete behavior in XAML as a way to get started.
<
TextBox
x:Name
="cityTextBox"
>
<
f:Form.AutoComplete
>
<
f:AutoComplete
ServiceUri
="/App_Services/Cities.ashx"
/>
</
f:Form.AutoComplete
>
</
TextBox
>
Done... no code required! The AutoComplete instance assigned to the Form.AutoComplete attached property listens the TextBox events and in the background fetches city suggestions, displays a dropdown list with the cities, and allows the user to pick one. The AutoComplete does all sorts of fancy things by default like not fire off a web request per keystroke, cache results etc. As you can see the declarative XAML-based usage model makes the scenario quite simple to implement.
Here's the corresponding server-side code implementing the service in Cities.ashx:
public
class CityCompletionService : CompletionService<string> {
protectedoverride IEnumerable<string> GetItems(string prefix) {
string[] matchingCities = ...;
return matchingCities;
}
}
Scenario 2: Styling the user interface
One of the most compelling aspects of XAML and Silverlight is the ability to create compelling user interfaces by restyling and reskinning controls to match the overall look and feel of your application. The AutoComplete behavior supports this by allowing you to specify a template for the dropdown used by the behavior. If I've got some customized look and feel defined in the myCustomListBox style, I can reference it as follows:
<
TextBox
x:Name
="cityTextBox"
>
<
f:Form.AutoComplete
>
<
f:AutoComplete
ServiceUri
="/App_Services/Cities.ashx"
>
<
f:AutoComplete.DropDownTemplate
>
<
DataTemplate
>
<
ListBox
Style
="{StaticResource myCustomListBox}"
/>
</
DataTemplate
>
</
f:AutoComplete.DropDownTemplate
>
</
f:AutoComplete
>
</
f:Form.AutoComplete
>
</
TextBox
>
Scenario 3: Going beyond strings
So far the service backing the completion experience has been returning an array of strings. I actually want to use a service that returns something more than just a string (you'll see why in the next step). For example, in this scenario, I want to return an array of CityInfo objects that contain Name, State and ZipCode properties.
Here is the updated service implementation on the server.
public
class CityInfo {
publicstring Name { get; set; }
publicstring State { get; set; }
publicstring ZipCode { get; set; }
}
publicclass CityCompletionService : CompletionService<CityInfo> {
protectedoverride IEnumerable<CityInfo> GetItems(string prefix) {
CityInfo[] matchingCities = ...;
return matchingCities;
}
}
In order to implement this scenario on the client I need to do a couple of things. First I need to provide a client-side type that the AutoComplete behavior uses to deserialize the JSON into. Next I'll want to customize the ItemTemplate of the ListBox to display the additional fields. Finally, I'll want to handle the Completed event to convert a CityInfo object into text that is used to put into the TextBox once a user selects a particular city.
public
class CityInfo {
publicstring Name { get; set; }
publicstring State { get; set; }
publicstring ZipCode { get; set; }
publicstring Location {
get {
return" (" + State + ", " + ZipCode + ")";
}
}
}
<TextBoxx:Name="cityTextBox"><f:Form.AutoComplete><f:AutoCompleteServiceUri="/App_Services/Cities.ashx"ServiceResultType="CityInfo"Completed="OnCityCompleted"><f:AutoComplete.DropDownTemplate><DataTemplate><ListBox><ListBox.ItemTemplate><DataTemplate><StackPanel><TextBlockText="{Binding Name}"/><TextBlockText="{Binding Location}"/></StackPanel></DataTemplate></ListBox.ItemTemplate></ListBox></DataTemplate></f:AutoComplete.DropDownTemplate></f:AutoComplete></f:Form.AutoComplete></TextBox>privatevoid OnCityCompleted(object sender, AutoCompleteCompletedEventArgs e) {
// This event handler is optional. By default e.SelectedItem.ToString()// is used by the AutoComplete.e.SelectedItem = ((CityInfo)e.SelectedItem).Name;
}
Scenario 4: Filling dependent TextBoxes
There was a reason to return CityInfo objects instead of simply city names. Lets say my form also has a TextBox for entering ZipCode. If the user selects a city from the auto-complete dropdown, I'd also like to fill the zip code for added convenience.
I can simply update my Completed event handler above to extract the ZipCode and populate the ZipCode TextBox accordingly.
private
void OnCityCompleted(object sender, AutoCompleteCompletedEventArgs e) {
zipCodeTextBox.Text = ((CityInfo)e.SelectedItem).ZipCode;
e.SelectedItem = ((CityInfo)e.SelectedItem).Name;
}
Scenario 5: Using local computed values
So far I've been showing scenarios where the AutoComplete behavior makes a web request to get at the list of the completion items to show in its dropdown. Some times, an app might want to show a list of values computed in client-side logic. Or you may have already loaded data from a web service call, and just want to plug in that data, rather than making a separate call.
This scenario is implementable by handling the Completing event of the AutoComplete behavior which allows you to either plug in your items, or to suppress the dropdown altogether for the particular prefix text that the user has entered. For example:
<
TextBox
x:Name
="cityTextBox"
>
<
f:Form.AutoComplete
>
<
f:AutoComplete
Completing
="OnCityCompleting"
/>
</
f:Form.AutoComplete
>
</
TextBox
>
private
void OnCityCompleting(object sender, AutoCompleteCompletingEventArgs e) {
string prefix = e.Prefix;
string[] cities = ...; // code to lookup some local data using prefixe.SetCompletionItems(cities);
}
Live Demo
Finally, here is a demo of the AutoComplete behavior. To experiment, type in something "San" in the city TextBox to see a list of cities pop up. Select a city (such as San Francisco) to see both the city and the zip code TextBoxes get filled.
Yet another behavior... TextFilter
Actually, I've slipped in another behavior as well into the mix, just for some more fun. This is the TextFilter behavior that can also be associated with a TextBox to restrict input to say numeric characters.
<
TextBox
x:Name
="zipCodeTextBox"
>
<
f:Form.Filter
>
<
f:TextFilter
Filter
="Numbers"
/>
</
f:Form.Filter
>
</
TextBox
>
Hopefully these examples really start making the behavior concept more concrete, and clear.
You can download the code, which includes the behavior framework, all the behaviors I've written about so far, as well as a sample app that demonstrates using them. Enjoy!
From Nikhil Kothari's Weblog, 5 months ago,
0 comments
In the past, I've written about behaviors and control extenders in the context of Ajax and HTML-based UI. This post introduces a similar behavior semantics for Silverlight and XAML-based UI as well.
The mini-behavior framework I have prototyped allows you to write and use behavior as a combination of a component + an attached property. The framework provides the logic to attach/detach behaviors for behavior authors. The rest of this post demonstrates using and writing a simple behavior based on this framework. Over the next few posts, I'll discuss a few more behaviors as a way to further experiment and demonstrate the behavior concept.
Using the DefaultCommit Behavior
Lets say you're implementing a typical form with a TextBox and a search Button. You'll probably want to allow users to press the Enter key after typing in some search keywords to kick off the search rather than force them to click the button explicitly. What you'd normally do is write a couple of event handlers to handle both the Click event from the Button and the KeyDown event from the TextBox (to look for the Enter key) in your code-behind, and trigger the search logic from each of them. This is more complicated and messy than it needs to be.
Ideally you simply want to handle a single event - the button's Click event. In fact, in HTML forms, this is built in into the notion of a Form with a submit button. However, it isn't so in Silverlight, where a Form concept is baked in. This is where this behavior comes in. Once this behavior is available, I can author the following XAML:
<
TextBox
x:Name
="searchTextBox"
>
<
f:Form.Commit
>
<
f:DefaultCommit
ButtonName
="searchButton"
/>
</
f:Form.Commit
>
</
TextBox
>
<
f:Button
x:Name
="searchButton"
Content
="Search"
Click
="OnSearchButtonClick"
/>
Essentially the DefaultCommit behavior is attached to the TextBox using the XAML syntax above. For those new to XAML and Silverlight, f:Form.Commit refers to the Commit attached property offered by the Form class. This is similar to Canvas.Left, which you've probably encountered. The only difference is that the type of the Canvas.Left attached property is a simple double value, whereas the type of the Form.Commit property is a DefaultCommit.
Underneath the covers, the DefaultCommit behavior does the same thing you'd do in code-behind, but does so in a way that the logic is now encapsulated and is easily reusable. You can instantiate as many of these as you want, especially across multiple forms/pages without duplicating the event handling logic all over.
Here is a live demo (if you've got Silverlight installed) - simply type in something and press Enter. The app behaves as if you had clicked the button. There is no really search hooked up though.
You might have noticed the use of <f:Button> instead of a regular Button. Unfortunately, unlike WinForms and HTML buttons, the Silverlight Button control currently doesn't have any way to programmatically invoke the Click event, so I had to add that functionality in a derived class.
Implementing the DefaultCommit Behavior
The behavior framework I have put together introduces two classes Behavior and BehaviorManager.
The first step is to implement a behavior by deriving from the Behavior class. The Behavior class is a generic class, to allow indicating the type of objects that behavior can be associated with.
public
class DefaultCommit : Behavior<TextBox> {
}
The next step is to add any properties exposed by the behavior itself.
public
class DefaultCommit : Behavior<TextBox> {
privatestring _buttonName;
publicstring ButtonName {
get { return _buttonName; }
set { _buttonName = value; }
}
}
The behavior base class holds the reference to the associated object as its AssociatedObject property. It defines a couple of abstract methods to manage the lifetime of a behavior instance: OnAttach, and OnDetach. The derived behavior class implements these to perform associated logic, such as setup and cleanup including subscribing and unsubscribing to events raised by the associated object.
public
class DefaultCommit : Behavior<TextBox> {
protectedoverridevoid OnAttach() {
AssociatedObject.KeyDown += OnTextBoxKeyDown;
}
protectedoverridevoid OnDetach() {
AssociatedObject.KeyDown -= OnTextBoxKeyDown;
}
privatevoid OnTextBoxKeyDown(object sender, KeyEventArgs e) {
if ((e.Key == Key.Enter) && (AssociatedObject.Text.Length != 0)) {
Button button = AssociatedObject.FindName(_buttonName) as Button;
if (button != null) {
button.PerformClick();
}
}
}
}
The final step is to define an attached property that can be used to declaratively create an instance of this behavior and have it be associated with a TextBox. This is where the BehaviorManager class will come into play. It provides a set of utility methods that correctly attach/detach behaviors.
public
static
class Form {
publicstaticreadonly DependencyProperty CommitProperty =
DependencyProperty.RegisterAttached("Commit", typeof(Form), typeof(DefaultCommit),
OnCommitPropertyChanged);
publicstatic DefaultCommit GetCommit(TextBox textBox) {
return BehaviorManager.GetBehavior<DefaultCommit>(textBox);
}
publicstaticvoid SetCommit(TextBox textBox, DefaultCommit commitBehavior) {
BehaviorManager.SetBehavior(textBox, commitBehavior);
}
privatevoid OnCommitPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {
BehaviorManager.UpdateBehavior(o, CommitProperty,
(DefaultCommit)e.OldValue,
(DefaultCommit)e.NewValue);
}
}
There you go... writing a basic behavior is quite straightforward.
Concepts and Next Steps
One rough analogy to behaviors is that of extension methods in C# 3.0. Those are at the method level. Behaviors are similar, but are live components. More specifically, a behavior is a component that encapsulates some functionality and can be attached to another component to extend its built-in functionality, without creating a derived class. A couple of example behaviors that can be attached to a TextBox besides the one implemented above include auto-complete and input filtering.
The fact that behaviors are attached components that implies a composition-like metaphor, offers two advantages whenever derivation is non-essential:
Almost all behaviors handle events and encapsulate a set of event handlers into a reusable component that can then be instanced declaratively. Often this leads to a more declarative style of programming (something I love) and reduced code-behind clutter.
I chose a simple behavior scenario to introduce the concept. In a future post, I'll demonstrate some more interesting behaviors, including AutoComplete , and some animation scenarios. Stay tuned. Over time, I'll continue to experiment with this. I have some ideas on implementing declarative views that are enabled via this concept.
I'd love to hear ideas you might have for behaviors that would be useful additions for Silverlight and XAML-based UI, and especially for RIA scenarios.
You can also download the code which contains the behavior framework, the sample behavior, and a sample app that makes use of them.
From Nikhil Kothari's Weblog, 5 months ago,
0 comments
Live Mesh is finally public - it was announced earlier today at the Web 2.0 conference. We’ve had the social graph buzzword bantered around for some time in the context of Facebook. Will mesh become the next one to go around? Check out the intro post. Live Mesh is all about software + services, and connecting and bringing devices together into your own personal "mesh" enabling them to work in a connected way.
Ray Ozzie alluded to the Web as the Hub of the social mesh and the device mesh earlier at MIX08. Over on the Live Mesh blog, Mike Zintel alludes to a bunch of concepts around the Live Mesh platform, such as mesh object, and a data synchronization platform. I am particularly excited about the prospect of seeing a new generation of Web apps that leverage the platform in all sorts of interesting ways, not just for local storage, but also synchronized local storage of application data and personal data, and offline execution, as a means to differentiate and cater to new user experiences on the Web. The APIs that emerge around this platform will be something to keep an eye on.
On another personal note, I am super excited to see and run the Web version of Live Mesh, which simulates a Vista desktop and Explorer folders right within your Web browser for anywhere access to your devices and a data. While it will be interesting to see the user reactions around this UI metaphor in the browser as shown in the screenshot, the Ajax code behind the scenes is pretty much written in Script# (I've worked with the team for a while), and now that the site is public, I’ve added it to the new showcase page on my project site.
From Nikhil Kothari's Weblog, 5 months ago,
0 comments
This is a quick post on the latest release of Script# (Build 0.5). I'll be following up with subsequent posts with more details on some of the specific feature additions, but here is a list of whats new (besides bug fixes, and improved compiler error reporting):
Also, Script# is now on CodePlex (actually it has been on there for a month or so, but this is the first release since). The forums associated with the CodePlex project should significantly improve the experience around sending feedback, and having discussions around the technology and using it. Several folks have asked me in the past about open sourcing it. My plan is to eventually have the source out there as the project approaches its v1 status, starting the with the core framework and runtime, and subsequently the compiler itself. Stay tuned on that front for more in the next few months.
There are a couple of related CodePlex projects to call out:
Finally, I've updated my project site as well with more introduction to Script#, release notes, and a high-level roadmap. I will also be transitioning the documentation that is currently available in pdf form to the site over time.
From Nikhil Kothari's Weblog, 5 months ago,
0 comments
Just over a month ago, at MIX08, I presented a talk on Real-World Ajax. One of the demos I included was an Ajax templating technique to demonstrate separation of presentation and content from behavior to help manage script complexity, and to help facilitate designer/developer workflow.
The demo was based on early thoughts around what we need to do in this area. What is presented here is still quite simplistic in terms of the range of options it provides to developers. The demo worked well with the audience, and I'd love to hear any feedback people have in this area that can be fed into the design process at this early stage (I alluded to this work in comments to my Ajax vs. Silverlight post).
Here is my scenario - in my Ajax app, script issues a web request to fetch a list of data, in this case a list of bookmarks, and constructs HTML to visualize the results. This is often implemented as follows:
<
div
id
="bookmarkList"
></
div
>
<
script
type
="text/javascript"
>
function fetchBookmarks() {
// Issue an XMLHTTP request to retrieve user's bookmarks.
}
function onBookmarksAvailable(bookmarks) {
// Update display using retrieved bookmarks. Each boomark has Url and Title properties.var sb = new Sys.StringBuilder();
sb.append("<ul>");
for (var i = 0; i < bookmarks.length; i++) {
sb.append("<li>");
sb.append("<a href=\"");
sb.append(bookmarks[i].Url);
sb.append("\">");
sb.append(bookmarks[i].Title);
sb.append("</li>");
}
sb.append("</ul>");
$get('bookmarkList').innerHTML = sb.toString();
}
</script>
This works. However, there is a problem. The definition of the UI is now embedded in script. Its hard to design and change it. And its hard to preview it without running the page. The problem is worse if the structure of each item is more complicated than what the sample tries to do.
Here is where templating comes into the picture. Templates have been super common in server-side frameworks like ASP.NET, and are now popping up in client-side script frameworks, as Ajax apps start becoming more client-centric. With templating the developer or designer can define the structure of an item in regular markup, and the templating engine is then responsible for generating the script equivalent.
In the demo, I wrote a simple template engine, which I can use by to rewrite the script as follows:
<
div
id
="bookmarkList"
>
<
ul
id
="itemContainer"
></
ul
>
</
div
>
<
div
id
="bookmarkTemplate"
style
="display: none"
>
<
ul
id
="itemContainer"
>
<
li
><
a
href
="{Url}"
>{Title}</a></ul></div>
<
script
type
="text/javascript"
>
function fetchBookmarks() {
// Issue an XMLHTTP request to retrieve user's bookmarks.
}
function onBookmarksAvailable(bookmarks) {
// Update display using retrieved bookmarks. Each boomark has Url and Title properties.var template = new Templating.Template($get('boomarkTemplate'));var itemContainer = $get('itemContainer', $get('bookmarkList'));
for (var i = 0; i < bookmarks.length; i++) {
var item = template.createInstance(bookmarks[i]);
itemContainer.appendChild(item);
}
}
</script>
The interesting lines are in bold. The template is defined using regular XHTML markup representing how items should appear. This can be independently edited/designed and previewed. You simply embed atomic tokens such {Url} etc. into the markup.
The script is responsible for creating the template, which effectively generates the script equivalent, (this is done once), and then as the script loops over the list of bookmarks, it uses the template to create new instances of the list items and anchors, and adds them into the DOM to generate the display.
With this we have a client-side templating mechanism. However web development is all about balancing and meeting several requirements (at once). In particular here are some of the things I also want to tackle as a developer.
These can be addressed through some form of server-side rendering, sort of how you've been doing using server-side data-bound controls for years. The goal however, in the context of Ajax, is to leverage a single template definition for both server-side and client-side processing. This is where server controls really shine. They allow you to do Ajax better by providing end-to-end solutions.
I've written an AjaxRepeater server control as part of the prototype. It does server-side data-binding (using the same token format we've seen above), renders the list on the server, but also generates a client-side Repeater control (using the ASP.NET Ajax UI pattern for writing controls). The client-side Repeater control consumes the same template definition, and provides the ability to dynamically add rows on the client, or reset the list of items to be displayed. The sample below illustrates using this control, along with both server-side code and client-side script working against it.
<
n:AjaxRepeater
runat
="server"
id
="bookmarkList"
>
<
ul
id
="itemContainer"
>
<
li
><
a
href
="{Url}"
>{Title}</a></ul></n:AjaxRepeater>
<
script
runat
="server"
>
void Page_Load() {
bookmarkList.DataSource = new Bookmark[] {
new Bookmark { Title="...", Url="..." }, ...
};
bookmarkList.DataBind();
}
</script><scripttype="text/javascript">function addBookmark(title, url) {
var bookmark = { Title: title, Url: url };
$find('bookmarkList').addDataItem(bookmark);
}
</script>
The current implementation is pretty much based on what can be done via String.Format to perform substitutions of tokens in the template with actual data (I used a tweaked version of James' FormatWith code). Eventually the hope is to productize this feature, and at that point we'd like you to be able add expressions in the template as well as express conditional segments within the template. For example, one might be able to write this:
<
n:AjaxRepeater
runat
="server"
id
="bookmarkList"
>
<
ul
id
="itemContainer"
>
<
li
>
<
a
href
="{Url}"
class="{ IsShared ? 'bookmark shared':'bookmark' }">{Title}</a><!--- if (!IsShared) { ---><buttontype="button"onclick="...">Share</button><!--- } ---></li></ul></n:AjaxRepeater>
As we extend the functionality of those templates, it is important to preserve the server-side rendering capabilities. One way to accomplish this is to use the DLR and JavaScript on the server. This can actually be done quite efficiently by doing the script-generation and compilation using the DLR at page parse time, once for the lifetime of the application, in much the same way that regular ASP.NET template markup is parsed and compiled once into a delegate that can be invoked multiple times. For ongoing prototyping at this moment, I am starting to look at JScript.NET, until the DLR is part of the framework.
One key realization here is that targeting the mainline scenarios that Ajax developers encounter all the time keeps the overall solution simple and elegant for both the developer and the framework. Combining that with the right server-side support makes the solution much more interesting, as it starts to address the end-to-end scenarios with a single set of concepts and a consistent approach.
I'll reiterate that this is a prototype that I partly demo'd at MIX, and isn't meant to represent exactly what might eventually make it into the product (as we all know, things change as we iterate on ideas, and put together feature plans)... but as I mentioned earlier, if you do have thoughts you'd like to share, then go ahead, and post them below.
For those who are interested at poking around in the code for either the templating engine (which is really quite small), or the server-side control, you can download the prototype as it exists today. If you delve in deeper, you might also notice that the included script was generated using Script# (as you might have come to expect of me by now) and comes along with the originating C# source as well. If you haven't installed Script#, then simply ignore the 2nd project in the solution when it prompts you. I am hoping to get a client-side templating engine added to Script# as well a little further down the road.
From Nikhil Kothari's Weblog, 6 months ago,
0 comments
I get the Silverlight vs. Ajax question all the time, whether it is at a conference, over email, or over on discussion forums. In the interest of seeding a broader discussion, and hearing what other people think, I thought this would be an interesting blog post, along with the side benefit of having a ready-made answer the next time the topic comes up.
There have been a number of blog posts pitching Ajax vs. RIA (whether its Flash or Silverlight) such as this one here. Personally, I think Ajax and Silverlight complement each other, and the "vs." is a bit misplaced. Furthermore, the way I see it, there is a continuum, with a number of sweet spots representing specific classes of applications. This perspective is perhaps directly reflected in the makeup of the UIFX team that I work on at Microsoft - the team is spread across ASP.NET, Ajax, Silverlight and RIA frameworks all at once actively working on cool stuff in each of these areas (i.e. lots to look forward to).
Reach and Rich
The diagram represents a spectrum of application development approaches and technologies/platforms with increasing reach on one end, and increasing capabilities on the other. Applications have distinct scenarios and correspondingly gravitate toward a sweet spot. Some apps lie squarely on the left, with the need to first and foremost prioritize universal reach. At the same time, some apps have experience or functionality as the high order bit, where it is necessary to leverage a more capable platform, even if it means somewhat reduced reach. Still, the best apps will probably be those that leverage multiple front-end options to follow the user, with a common back-end (sort of a software and a service model).
One thing is sure - users are expecting more, and apps are trying to differentiate by meeting them. For example, the Ajax hype has given way to broad mainstream and pragmatic use of the technology (hence I call the older style of Web apps as "Classic" in the diagram).
RIA Islands
At the same time, the reality is a number of applications are no longer "pure" Ajax, i.e. just HTML and Script-based. Ajax applications are increasingly relying on plugins such as Silverlight, Google Gears, and Flash to incrementally enrich the experience they can offer (ideally, in a manner such that they gracefully degrade). These plugins let Ajax applications do interesting things like use local storage, access user's files, integrate rich media and vector graphics, background processing etc. Just like ASP.NET server controls make it quite easy to incorporate Ajax functionality, they are also nicely positioned to simplify the "Islands of Silverlight" scenario. Imagine a data-bound server control that renders a Silverlight chart, and degrades to a static image dynamically rendered on the server without requiring the app developer to learn several new technologies. I've spoken on this at recent conferences, and will be blogging more on this end. Wilco blogged about Silverlight Interop to cover the use of Silverlight to implement HTML code-behind and creating a better file uploader for Ajax apps.
Trends
The second thing that is also interesting about the diagram are the trends in effect. The reach platform, starting to be referred to as the Open Web by some, is bound to get richer in terms of the execution engine, the presentation stack, and its framework capabilities. HTML 5 promises to improve some core pieces of the browser-based platform, and all the browsers (yes, that includes IE) are already stepping up to improving the state of the art in their next versions. The interesting question is when we will see ubiquity around the next batch of incremental improvements like the ubiquity of XMLHTTP that fueled the Ajax wave a couple or so years ago. RIA technologies are becoming more ubiquitous, and starting to become a viable or required choice for development in the next generation of Web apps. Over time as what is considered "rich" today gets commoditized by the reach platform, the platforms on the right need to constantly redefine themselves by finding new ways and value offerings in order to differentiate, which always keeps them interesting and in the forefront. It's a constant tug-of-war ... and it doesn't seem like either Ajax or the RIA approach is going to all out win any time soon.
A .NET Theme
So if you agree, the world isn't Ajax vs. RIA, but is rather Ajax and RIA (and Desktop), and there is room for them to co-exist, the final thing I'll point out is how the Microsoft platform plays out in this space. Clearly, the consistent theme across the board is .NET and managed code, which allows developer skills, as well as in many cases, common code that can be shared and leveraged as apps transition or grow. Ray Ozzie spoke to this when referring to connected development at MIX 08. We have .NET on the server providing that common backend, .NET on Web/Ajax front with ASP.NET and even . NET-flavored scripting with technologies like Script#, and of course, .NET on the client with WPF. Silverlight 2 brings .NET to the RIA space. In fact, the simpl