Silverlight — The Silver Lining for Line-of-Business Applications - Real World .NET, C#, and Silverlight: Indispensible Experiences from 15 MVPs (2012)

Real World .NET, C#, and Silverlight: Indispensible Experiences from 15 MVPs (2012)

Chapter 5

Silverlight — The Silver Lining for Line-of-Business Applications

by Jeremy Likness

Archeologists claim that humans mastered fire approximately 400,000 years ago. Controlled blazes warmed early tribes as they moved into cooler regions and used their flames to hold predators at bay. Generations later, I would smile at the irony that I was investing most of my time putting out fires. I was the development manager of a team that wrote software to help companies manage their mobile devices. It seemed that the browsers were managing us as we spent more and more time testing, writing, and reworking code to achieve the holy grail of cross-browser compatibility.

The aptly named “Acid” tests allude to the corrosive and loose interpretation of standards intended to drive the consistent rendering of Hypertext Markup Language (HTML) documents on any platform or browser. You can visit the www.acidtests.org site to run the tests that can mercilessly pound your computer with standards-based tags and JavaScript to produce a smiling face that happily declares, “This browser is compliant.”

Most browsers failed these tests miserably when they were first released, while line-of-business (LOB) application developers independently discovered that building a rich online experience involved more than just quality code and smart design. Too many honest ASP.NET developers were unwillingly dragged into the realm of Cascading Style Sheet (CSS) and JavaScript “hacks.” They were left worn, haggard, and irritated at the effort it required to make a seemingly simple user interface (UI) behavior work across the full spectrum of target platforms and browsers.

I knew there had to be a better way.

Meanwhile, Microsoft had already released two versions of a product with the “Jolt core” codenamed “Windows Presentation Foundation/Everywhere” that finally morphed to the identity we are familiar with today: Silverlight. The first version of Silverlight provided a JavaScript API with some rich graphics controls that would support only JavaScript Object Notation (JSON) and XML-based data. Developers bemoaned the lack of basic features needed for rich web applications, and the world at large scratched their heads wondering why the world needed another video player to compete with Flash.

The development community began to take notice when Silverlight 2 hit the web with a new engine, this time a streamlined version of the full .NET core Common Language Runtime (CLR). This created a plethora of options that included the capability to write code using familiar languages such as C# and Visual Basic, the use of complex types, and a data-binding engine reminiscent of the mature Windows Presentation Foundation (WPF) platform. Silverlight 3 and 4 later provided capabilities ranging from network detection and isolated storage, to offline mode and printing.

There was a better way!

The proof of concept I developed took 2 weeks to build from start to finish, and convinced management that Silverlight was something worth looking into. Just a month after that, we had strategic portions of the application moved to Silverlight. We completely eliminated any need to code for browsers because it would run as-is on any platform that supported the plug-in. The UI was far more advanced than what was possible using HTML markup, and the entire project was written using the C# language our team was familiar with.

I estimate that the switch to Silverlight enabled the team to produce four times more code in a sprint using Silverlight compared to ASP.NET. In a recent Microsoft-run Silverlight Firestarter event, the company Global Pay shared similar statistics, adding that the client footprint makes it possible to deploy an enterprise-scale application at 1/31th the cost of traditional methods because of savings on data center iron. (The work is offloaded to the customer.)

To truly appreciate the power of Silverlight for building LOB applications, it makes sense to start at the beginning. In this chapter, you build a simple “Hello, World” application and learn how to go from a clean slate to a fully functional, cross-platform and browser solution in just a few minutes.

Getting Started

To follow the steps in this chapter, you must prepare your environment for Silverlight development. The easiest way to do this is to visit the Silverlight website and follow the instructions available at www.silverlight.net/getstarted/.

Hello, Business World!

It's time to start with your first application!

Open Visual Studio 2010, and choose Silverlight Application on the New Project page, as shown in Figure 5.1. Name your application HelloBizWorld.

Figure 5.1 Creating a new project

5.1

When the New Silverlight Application dialog appears, simply click OK. Visual Studio creates two projects, as shown in Figure 5.2.

Figure 5.2 Automatically created projects

5.2

The HelloBizWorld.Web project is a typical ASP.NET web project to host the Silverlight application. HelloBizWorld is the Silverlight solution. Following are two main parts to the solution you can see:

· Application class

· UserControl class

The Application Class

The Application class inherits from Application and is the root type that drives the Silverlight program. Two files exist for this class: App.Xaml and App.Xaml.cs. The Extensible Application Markup Language (XAML) is a declarative XML-based language used for initializing types and objects. You learn more about XAML later in this chapter.

The other file is the C# code-behind file. This partial class declaration extends the class defined in XAML. The default code-behind does several things, including the following:

· Hooking into the application startup for code to launch when the application first runs

· Hooking into the application exit for code to launch when the application is closed

· Wiring the unhandled exception event so that unhandled errors can be trapped and dealt with

· Assigning the root visual, which is the top-level “view” for the application

The application can also host global resources that other types and classes can consume.

The UserControl Class

The UserControl class is a user-defined control that is visible within the application. By default, a UserControl called MainPage.xaml is created. This UserControl also has code-behind, just like the application class. This is the control that the application class creates and assigns to the root visual when the application first starts.

This is also where you can perform most of your work with the Silverlight UI. By default, the designer opens on the main page. Depending on how you have configured your Visual Studio 2010 settings, you should see a split screen with a design view at the top and a XAML view at the bottom, as shown in Figure 5.3.

Figure 5.3 Two views in the Silverlight UI

5.3

Open your toolbox and click the TextBlock control. Drag it onto the design surface. The text box outline appears in the design area, while the XAML element for the text box is inserted into the XAML area.

Edit this element and update the XAML so that it looks like Listing 5.1.

note

Listing 5.1: TextBox for the Hello, Business World Application

<TextBlock HorizontalAlignment="Center" VerticalAlignment=

"Center" Text="Hello, Business World" />

Code file [021965 CH05 code for download.zip] available for download at Wrox.com.

Press CTRL+F5. Your application will compile, and you should see a web browser window open with the text, “Hello, Business World.”

Congratulations! You've just written your first Silverlight application. Behind the scenes, the Visual Studio compiler generated a dynamic link library (DLL) for your project and packaged it into a special file known as a XAP (pronounced “Zap”). This file contains a manifest listing the content and all the resources needed by your Silverlight application (such as DLLs, embedded images and fonts, and resource files). This file is actually a compressed ZIP file.

note

A XAP file is nothing more than a ZIP file with a different extension. To see the contents of the XAP file, simply rename it to have a ZIP extension, and open it with Windows Explorer.

The XAP file is automatically copied to a special folder in the web project called ClientBin. The Silverlight plug-in understands how to download the XAP file and extract the contents to run your application.

Project Templates

When you created the Silverlight project, you may have noticed several different project templates. Each template can help structure a new application based on your specific goals. You need to be familiar with the various project types so that you know which template to use when starting a new project.

Silverlight Application

You have already used the Silverlight Application template, which is the most common template. This template can create a sample web project to host your Silverlight application and a basic template for the application. It can also create a default page to start with. This should be the starting point for any of your Silverlight applications, unless you have a more specific need addressed by the other templates.

Silverlight Class Library

The Silverlight Class Library template creates an independent DLL that can be linked into other Silverlight projects. It is similar to the standard C# Class Library. Use this template to create a set of types, methods, and properties that will be shared across different projects. Class libraries do not output XAP files. Rather, a single DLL is output that can then be referenced to be included in other projects.

note

Silverlight uses a special subset of the core CLR that drives the full .NET Framework. You cannot reference a DLL created for .NET from Silverlight because it may contain references to namespaces not supported by Silverlight. However, you can build a DLL in Silverlight and reference it from a .NET application. Therefore, when you want to create a common DLL shared between Silverlight and .NET applications, you should create it as a Silverlight Class Library.

Silverlight Business Application

Silverlight Business Application is a comprehensive template that includes examples of functionality needed in typical LOB software. A theme (for skinning, or setting the application style and colors) is provided, along with the built-in navigation framework that enables you to jump between the Home page and the About page. A Login button introduces a pop-up window (in Silverlight, this is created using the ChildWindow control) to enable a login and a registration.

The web project includes classes shared between the Silverlight application and the .NET application on the server. This project also introduces the concept of web services, and provides sample service endpoints for registering a user and logging in.

In addition, various controls, helper classes, and utilities are commonly used in applications. This is an advanced template that should be used only after you are familiar and comfortable with developing Silverlight applications.

Silverlight Navigation Application

Like the Silverlight Business Application template, the Silverlight Navigation template provides a default theme and uses the built-in navigation framework to create a multipage application. Unlike the Silverlight Business Application template, this template does not include the sample login and registration processes, shared libraries, or services. This template is lightweight and is often used as the starting point for applications that require URL-based navigation.

Other Application Templates

Other application templates may be downloaded from the web or installed with other packages. For example, the Silverlight Unit Testing Framework enables you to write and run unit tests in the browser. This package introduces the Silverlight Unit Test Application template used to create a new project for unit tests.

With any application, you are given the option to enable Windows Communication Foundation (WCF) Rich Internet Application (RIA) Services. WCF RIA Services is a special feature of Silverlight that makes it easier to interact with data on the server. It uses a technique known as projection to make working with data look and feel like you are accessing the data directly inside of the Silverlight application. Behind the scenes, the technology generates web service endpoints and coordinates the activity on the client with the server to provide a seamless data experience.

Table 5.1 compares the various Silverlight templates you can use for a new project.

Table 5.1 Silverlight Application Templates

images/c05tnt001.jpg

XAML Is Object XML

Earlier in the chapter, you were introduced to a concept known as XAML. When I ask developers to define what XAML is, I often hear answers related specifically to Silverlight and the UI, such as the following:

· “XAML is a UI markup language.”

· “XAML is something special in Silverlight for designing screens.”

· “XAML is used to lay out controls in Silverlight.”

XAML is simply the XML representation of an object graph. The XAML interpreter can use the markup to create and initialize various types. The “X” in XAML refers to the extensibility and flexibility of the language. Although XAML is often used to provide layout instructions for controls, any object with a parameterless constructor can be instantiated through XAML.

To help you better understand XAML, Listing 5.2 shows the markup for MainPage.xaml in the application you wrote earlier.

note

Listing 5.2: MainPage.xaml

<UserControl x:Class="HelloBizWorld.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d"

d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">

<TextBlock HorizontalAlignment="Center" VerticalAlignment=

"Center" Text="Hello, Business World" />

</Grid>

</UserControl>

Code file [021965 CH05 code for download.zip] available for download at Wrox.com.

The XAML interpreter can read the code and interpret it like this:

1. Create an instance of the MainPage type.

2. In the Content of MainPage, create an instance of a Grid type.

3. Set the name of the grid to LayoutRoot.

4. Set the background of the grid to the color white.

5. Create an instance of the TextBlock type.

6. Set various properties on the text block.

Anything possible through XAML is also possible through code. The XAML in Listing 5.2 is equivalent to the C# code shown in Listing 5.3.

Listing 5.3: C# equivalent for the MainPage.xaml

var control = new MainPage();

var grid = new Grid();

grid.SetValue(NameProperty, "LayoutRoot");

grid.Background = new SolidColorBrush(Colors.White);

var textBlock = new TextBlock

{

HorizontalAlignment = HorizontalAlignment.Center,

VerticalAlignment = VerticalAlignment.Center,

Text = "Hello, Business World."

};

grid.Children.Add(textBlock);

control.Content = grid;

Understanding that XAML is actually a set of instructions to initialize types and set properties can help you build better Silverlight LOB applications, and troubleshoot them more easily.

Hosting Silverlight Applications

One powerful feature of Silverlight is that it can be hosted on virtually any server. Silverlight is simply a special type of file downloaded from the web server. It is the browser's job to recognize the file and interpret it as a Silverlight application. When it is downloaded to a browser with the Silverlight plug-in installed, the plug-in takes over to open the XAP file and execute the Silverlight program.

So, what's the secret to hosting the Silverlight application? It's simple. Using the web server of your choice, you need to perform only two steps:

1. Place the XAP file in the hosted site.

2. Configure the Multipurpose Internet Mail Extensions (MIME) type for the XAP file.

MIME is not just used in e-mail. MIME types are also used by web servers to determine how to process and deliver content. With Silverlight XAP files, the server simply needs to map the .xap file extension to the MIME type application/x-silverlight-app. That's all that is needed to instruct the browser to execute the Silverlight plug-in.

Providing Excellent IApplicationService

Bad habits are tough to break, so it's always good to start with best practices. One thing you'll notice as you begin to work with Silverlight is that the majority of examples on the web, and the templates provided in Visual Studio, all tend to follow a pattern of hooking into start-up, shut-down, and exception-handling events in the code-behind for the App.xaml file. Although this practice certainly makes sense for smaller, standalone applications, LOB applications can use a better approach.

For example, consider a module that helps serialize objects to isolated storage so that it may be used in different applications. The module reads some configuration data from the initialization parameters passed into the Silverlight application by the web control. Parsing these parameters in theApp.xaml code-behind would mean modifying the code for every application that uses the module. This is not only inconvenient to the developer, but also introduces risk by creating another step, and a potential area to introduce bugs.

A cleaner approach is to implement the two interfaces provided by Silverlight for these types of modules: IApplicationService and IApplicationLifetimeAware.

The IApplicationService interface provides two simple methods: StartService and StopService. The StartService method is called when the application first starts up. It is passed an ApplicationServiceContext object that contains all the initialization parameters. This is the perfect place to parse configuration information and store it for later use. When the application exits, the StopService method is called. This enables the module to clean up data and store any necessary information before the application exits.

If you require even more control, consider implementing IApplicationLifetimeAware in addition to IApplicationService. This introduces the methods Starting, Started, Exiting, and Exited. These methods provide more fine-grained control. For example, Starting is called before the Application.Startup event is fired, whereas Started is called after. The former may provide configuration information, whereas the latter can interact with views that have been initialized, or other modules.

Listing 5.4 shows an example snippet of code to configure a logging framework using the IApplicationService interface.

Listing 5.4 : Example IApplicationService

public class LoggerService : IApplicationService

{

const string TRACE_LEVEL_KEY = "TraceLevel";

public LoggerService()

{

_traceLevel = TraceLevel.Warning; // default

}

private TraceLevel _traceLevel;

public ILogger Logger { get; private set; }

public static LoggerService Current { get; private set; }

public void StartService(ApplicationServiceContext context)

{

Current = this;

if (context.ApplicationInitParams.ContainsKey(TRACE_LEVEL_KEY))

{

_traceLevel = (TraceLevel)Enum.Parse(typeof (TraceLevel),

context.ApplicationInitParams[TRACE_LEVEL_KEY], true);

}

Logger = new CustomLogger(TraceLevel);

Logger.WriteLine(TraceLevel.Information, "Logger service started.");

}

public void StopService()

{

Logger.WriteLine(TraceLevel.Information, "Logger service stopped.");

}

}

Classes that implement these interfaces are easy to integrate into other applications. When you have a reference to the project that implements the interfaces, you can include the type in the App.xaml using the special ApplicationLifetimeObjects collection, as shown in Listing 5.5.

Listing 5.5: Using a Class that Implements IApplicationService

<Application.ApplicationLifetimeObjects>

<MySilverlightApp:LoggerService/>

</Application.ApplicationLifetimeObjects>

This is another example of how Silverlight provides the right tools for LOB applications, making it easy for you to produce modules that can be integrated across your product lines.

Choosing the Right Silverlight Framework

LOB applications are often composed of multiple modules that can be shared across product lines, and that may be developed by separate teams within the enterprise. Often, there is a design team independent of the development team. Writing quality software that accommodates this type of environment can be challenging. Fortunately, Silverlight has well-established patterns and best practices that facilitate enterprise development.

One reason it is important to understand the patterns and practices for Silverlight is to facilitate “developer-designer workflow.” Although it is less impactful on smaller projects, larger projects typically have separate design and development teams. The traditional workflow in this scenario is to receive the requirements for the application, wait for the design team to produce the wireframes, and finally, turn it all over to the development team to build. Often, developers would then return the code to the design team to “clean up” and finish the product.

With Silverlight and the clean separation provided by XAML and the data-binding engine, this workflow can be streamlined in a major way. After the functionality of the application has been determined, development and design may begin immediately. The design team can work completely independently of the development team when the right architecture is used because both efforts are integrated using a special type of class called a ViewModel. ViewModels are examined in more detail later in this chapter, but for now, think of them as a “contract” agreed upon between the design team and the development team, enabling both to build their parts of the project independently, and glue them together at the end.

So, how do you create the right framework to handle the optimal development workflow? The good news is that you don't need to reinvent the wheel. There are several out-of-the-box frameworks available to help you construct your applications. These frameworks provide shortcuts, commonly used functions and utilities, and guidance for how to implement common concerns. The bad news is that sometimes it can be a challenge choosing the right framework.

Getting SOLID: MVC, MVP, and MVVM

Most Silverlight articles and blog posts address Model-View-ViewModel (MVVM) in some form or another. The pattern is almost synonymous with both Windows Presentation Foundation (WPF) and Silverlight development. You might be asking yourself, “Why do I need to learn a new pattern? What's wrong with the patterns I'm used to, like MVC?”

The answer lies in the S.O.L.I.D. principles of software design:

· Single Responsibility — A class should focus only on one specific task.

· Open/Closed Principle — A class should be open for extensibility and closed for modification.

· Liskov Substitution Principle — A derived class should behave the same if it is cast to its base class.

· Interface Segregation — Interfaces should be fine-tuned to address specific concerns.

· Dependency Injection — Dependencies should be based on abstract contracts, not concrete implementations.

The principles collectively are considered by many to be the cornerstones of object-oriented design. Silverlight is typically written using C# or VB.NET, which are both object-oriented languages. Most design patterns, including Model-View-Controller (MVC), Model-View-Presenter (MVP), and MVVM, provide guidance to help applications adhere to these principles.

The MVC pattern addresses the concern of separating the view from the business logic that drives the view. As shown in Figure 5.4, the controller manages the view directly, while the view exposes events to send information back up to the controller. The model is the rest of the application infrastructure used to communicate with the back-end processes and business logic, and typically surfaces information interesting to the view through properties that the view can inspect and display.

Figure 5.4 The MVC pattern

5.4

In MVP, the view is often created first (unlike MVC, where the controller returns the view). To separate the concerns of the view from the business logic, the view always raises events that the presenter listens to. The presenter then interacts with the view via an interface, as shown in Figure 5.5. The interface enables the view to be mocked during testing, and allows multiple views to be managed by the same presenter.

Figure 5.5 The MVP pattern

5.5

MVVM is similar to these patterns. All the patterns contain a View (which is the UI component) and a Model (which is typically data), but can also encapsulate behavior and business logic in the system. The ViewModel is a special structure that is more like a controller than a presenter. The ViewModel maintains the View's state but is not directly aware of the View. There is no interface it uses to communicate with the View. Instead, MVVM specifically addresses a feature of the Silverlight Framework known as data binding.

As shown in Figure 5.6, data binding is the process that connects the UI to the ViewModel. In that View, certain elements may specify a binding. (This is most often done in XAML.) The binding is like a contract that prescribes how a View should obtain its data, and how it can publish events and inputs from the user. The binding is tied to a special property on the View known as the DataContext. The data context is most often the ViewModel itself. It exposes properties that the bindings refer to.

Figure 5.6 The MVVM pattern

5.6

The ViewModel is the link between the View and the rest of the application. It may communicate with interfaces to obtain configuration information, or call services to retrieve data. The information is then exposed via properties on the ViewModel that can be bound to the View itself. Figure 5.6shows several examples, such as a “busy” property to indicate when work is being performed, a command to submit a form, a collection of items, and a “current item” based on user selection.

The ViewModel contains the properties that are data-bound to the View. The ViewModel does not have specific knowledge of the View. For example, the ViewModel may contain a Boolean property that determines whether a panel is displayed. The ViewModel will not directly reference the View or refer to a Panel object. Instead, the View contains a data-binding directive that correlates the visibility of the panel with the value of the property.

In this way, ViewModels can be designed to hold the data and commands that a View requires. They can be independently tested without the presence of a View, and even be attached to different Views. Conversely, Views can be designed with special design-time ViewModels that satisfy the data-binding directives with sample data. This enables a clean separation of concerns while taking advantage of the data-binding system built into both Silverlight and WPF.

Dependency Injection and Inversion of Control

Dependency injection and inversion of control refer to the design practice of allowing an external object to determine the concrete implementation to use for a dependency. It is a useful principle because it enables the class to focus on a single concern (what the class was designed for, in alignment with the Single Responsibility Principle) and delegates external concerns elsewhere. This layer of abstraction often uses interfaces to decouple the class from the dependency. The dependency is injected by another mechanism, and the control is inverted from the class to an external mechanism.

The traditional problem is that a particular implementation always has its own dependencies. A module that generates PDF reports might need to also reference a third-party PDF tool. Any module requiring report generation then must also reference the same tool. This can lead to complex relationships and dependencies within the application.

A cleaner way would be for the modules to rely on a contract for reporting, and leave the details of how the report is generated to the report module itself, without having to carry additional dependencies.

The practices described previously can enable you to write decoupled code that is easy to test, maintain, and extend. With any decoupled system, there must be some point of resolution, in which interfaces and abstract classes are resolved to concrete types. (The module may reference a report interface, but eventually a real report module must be invoked to implement the interface.) Although a variety of patterns address this concern (for example, using a factory to retrieve an instance), several Silverlight Frameworks were built to specifically solve the problem.

Microsoft offers a product called Unity from the Patterns & Practices team. Unity was originally targeted to the Core CLR but was extended to support the latest versions of Silverlight. Unity provides attributed and fluent configuration.

note

Visit the Unity site online at http://msdn.microsoft.com/en-us/library/ff678312.aspx.

Ninject is an Open Source solution for dependency injection known for being lightweight, fast, and easy to use. Ninject also uses an attribute-based system, along with fluent configuration.

Other solutions for Silverlight include AutoFac (http://code.google.com/p/autofac/) and Castle Windsor (www.castleproject.org/container/index.html).

note

You can download Ninject online at http://ninject.org/.

The Managed Extensibility Framework

Although third-party tools do exist to address the problem of inversion of control, there is a solution provided within the .NET Framework that satisfies most dependency injection requirements in Silverlight. The framework also provides some powerful functionality to facilitate extensibility of applications, including a built-in way to modularize your Silverlight applications and dynamically load code at runtime. The problems of extensibility, discovery, and metadata (tagging modules with information) are addressed by the Managed Extensibility Framework (MEF).

Most inversion of control frameworks deal with what you know. At runtime (or during your tests), you can configure the framework to map a known concrete type to an interface. This is often done in a class referred to as a bootstrapper (a term that comes from the idea of “pulling yourself up by your boot straps”). Whenever a piece of code requests that interface, the concrete type is provided. In modular applications, the implementation for a particular interface might exist in a separate assembly (or in the case of Silverlight, XAP file). How can you connect that type to your interface when the type is not “known” to the CLR?

With MEF, the solution is simple. MEF introduces the concept of a ComposablePart. A part includes a contract, imports, and exports.

The contract defines what the part should address. A contract is a combination of an identifier and a type. The type might be an interface, an abstract class, or a concrete type. The identifier can default to the type name, or any arbitrary value used to further categorize the part. For example, an “error” identifier might be appended to a string type to specify a part that contains strings for errors.

The imports are all of the types that require the part. (Think of a retail store that must import products.) Whenever you require a part, you specify a property to hold the part, and then tag it with an attribute that indicates MEF should supply an implementation.

The exports are the implementations (like a manufacturer that provides product). Whenever you implement the contract for a part, you may export that implementation to make it available to MEF, which performs a task referred to as composition that matches exports to imports and makes the parts available to your application.

To illustrate how MEF works, create a new Silverlight application using the Silverlight Application template, as described earlier in this chapter. Name your project HelloMEF. After the projects have been created, right-click the References under your Silverlight project in the Solution Explorer, and add references from the .NET tab to System.ComponentModel.Composition and System.ComponentModel.Composition.Initialization. These are the DLLs used by MEF.

In the XAML file, simply place a TextBlock control so that your XAML looks like Listing 5.6.

note

Listing 5.6: MainPage.xaml for the Hello, MEF Example

<UserControl x:Class="HelloMEF.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d"

d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot" Background="White">

<TextBlock x:Name="tbText"/>

</Grid>

</UserControl>

Code file [021965 CH05 code for download.zip] available for download at Wrox.com.

In the code-behind for the main page, add the code shown in Listing 5.7.

note

Listing 5.7: MainPage.xaml.cs for the Hello, MEF Example

namespace HelloMEF

{

public partial class MainPage

{

[Import]

public string Text { get; set; }

public MainPage()

{

InitializeComponent();

CompositionInitializer.SatisfyImports(this);

tbText.Text = Text;

}

}

}

Code file [021965 CH05 code for download.zip] available for download at Wrox.com.

This code helps define a part. The contract for the part is a string. (This is implicitly derived from the tagged property.) In the constructor for the main page, the CompositionInitializer is called. This is a special class that MEF provides for Silverlight projects that examines the Silverlight application for parts and satisfies any requests. In this case, it sees the request for a string part and looks to satisfy it.

If you run the code now, you receive an error because the part is not complete. You haven't added an export yet.

To provide an export and “complete” the part, simply add a new class and name it Exports.cs, as shown in Listing 5.8. The class isn't used by the application, except to provide the exports that MEF needs. The exports can just as easily be provided in other classes, including the main page.

note

Listing 5.8: Exports.cs for the Hello, MEF Example

namespace HelloMEF

{

public class Exports

{

[Export]

public string HelloMef

{

get { return "Hello, MEF!"; }

}

}

}

Code file [021965 CH05 code for download.zip] available for download at Wrox.com.

Now, when you run the application, you should see the text, “Hello, MEF!” appear.

The Import and Export tags both create a part. The contract for that part is the string type. The import is provided by the main page (it requires the part to show the text) and the export is provided by the Exports class. (It supplies the implementation.)

The CompositionInitializer is a helper class specifically for Silverlight. Underneath the covers, MEF operates using a container. The container is simply a place to hold parts. Within the container are several catalogs. A catalog is a way of instructing MEF where to look for parts.

An AssemblyCatalog scans the assembly passed to it for imports and exports. A TypeCatalog can simply have types passed to it and scans the type definition for imports and exports. In Silverlight, a special DeploymentCatalog handles parts in a deployment, or XAP file. A container may have only one catalog. The special AggregateCatalog enables a collection of catalogs to be used.

The code in Listing 5.9 shows an example of this.

Listing 5.9: Containers and Catalogs with MEF

var mainCatalog = new AggregateCatalog(new DeploymentCatalog());

var container = new CompositionContainer(mainCatalog);

CompositionHost.Initialize(container);

CompositionInitializer.SatisfyImports(this);

An aggregate catalog is created, and a deployment catalog is passed to it. This instructs MEF to scan the current XAP file for parts. The Initialize method is called to tell MEF to “use this container” instead of the default one MEF would otherwise use. Finally, when the container and catalogs are specified, MEF is instructed to perform the composition by satisfying any import requests in the current class.

This was just a simple example to show how MEF works. MEF provides many more rich features that you may want to explore. For example, MEF can enable you to import multiple implementations for a contract and tag those with attributes to enable filtering and sorting. Through a feature called recomposition, MEF can also enable you to dynamically load new XAP files that also contain exports and can automatically merge those exports into your existing classes at runtime.

These features make it more than an inversion of control container and highlight the power of MEF as an extensibility framework. By using imports, you can not only defer implementation of functionality, but also allow it to be extended at runtime through concepts such as modules and plug-ins. Finally, MEF truly shines because it is part of the .NET Framework, so there is no need to download a third-party control or sort through licensing issues. If you have the Silverlight Framework installed, you can take advantage of MEF.

MVVM Frameworks

Now that you've explored some fundamentals for best coding practices in Silverlight LOB applications, you can find that existing frameworks help to address the majority of your basic concerns. In MVVM LOB applications, following are the common concerns:

· Managing INotifyPropertyChanged

· Connecting view models to views

· Providing infrastructure for ICommand implementation

· Enabling manipulation of visual states from the ViewModel

· Messaging between ViewModels

· Enabling modularity

note

Concept

ICommand is an interface that exists in both WPF and Silverlight. The command pattern is a useful way to separate the trigger (that is, a button or mouse click) for an action from the action itself, and the rules concerning whether the action may be performed. Although Silverlight provides no native implementation of ICommand, many of the MVVM frameworks described in this chapter provide an implementation for you.

Several frameworks exist to help solve these problems. Choosing the right framework can help you save time by supplying the fundamentals your LOB applications need. Selecting the right framework is a question of what you are comfortable with, whether you have a preference over how the inversion of control concerns are addressed, which features are important, and whether the license is compatible with your company's requirements.

Now take a look at a few popular frameworks to help you start. All these frameworks are Open Source projects hosted at CodePlex.

Prism

Prism is a framework provided by the Microsoft Patterns & Practices team. As of this writing, it is in Version 4.0. Prism is a large application with thorough documentation. It includes a library that can be used in your project, a reference application, and several quick-starts to target specific areas.

Prism enables you to choose which dependency injection framework you use, with built-in support for both Unity and MEF. It contains a command implementation, messaging via the event aggregator pattern, and a set of tools for modules and navigation. It is perhaps one of the most well-known frameworks, having started on the WPF platform, as evidenced by the hundreds of thousands of downloads on the site.

note

Prism can be accessed online at http://compositewpf.codeplex.com/.

MVVM Light

MVVM Light is one of the most popular frameworks for Silverlight, and is used in many commercial Silverlight and Windows Phone 7 projects. It provides explicit support for design-time modeling of data, a ViewModel locator pattern for helping bind ViewModels to Views, and lightweight messaging service.

One reason why MVVM Light may be so popular is that it also includes several project templates and code snippets to make it easy to start new projects. Common code constructs such as raising a property change notification are tackled by convenient code snippets. There is a large user community that supports and is familiar with the toolkit, and it is a great starting point for anyone looking to build Silverlight LOB applications.

MVVM Light is, as the name implies, far more lightweight than many other frameworks, including Prism. This makes it easier to grasp and understand for beginners to the MVVM pattern.

note

Download MVVM Light online at http://mvvmlight.codeplex.com/.

nRoute

Another popular MVVM framework is nRoute. This framework is well known for supporting several different asynchronous patterns and for working closely with Reactive Extensions (Rx). Rx enables asynchronous operations to be handled as “push streams” that drive events as they happen.

One notable feature of nRoute is the “reverse ICommand.” This enables binding events in the View to the ViewModel, while keeping the two decoupled. The framework has extensive documentation and several sample projects.

note

nRoute is available online at http://nroute.codeplex.com/.

Calburn.Micro

Calburn.Micro is an extremely small (only a few thousand lines of code) framework that packs a powerful punch. It is well known for its convention-based data-binding model. (View elements are bound to the ViewModel based on naming conventions and element types, rather than explicit binding commands.) The framework also takes a “ViewModel first” approach, which means that ViewModels are created and then spin up the Views, instead of the more common practice of having a View request to or bind to a ViewModel.

Another interesting feature of Calburn.Micro is the use of co-routines. Co-routines are state engines that help developers manage asynchronous code. Using co-routines, you can aggregate several asynchronous processes into a set of sequential code blocks that are easy to understand and follow. It is a great way to bridge the gap between existing functionality and what will be released in the next version of C# with the await keyword.

note

Caliburn.Micro is available online at http://caliburnmicro.codeplex.com/.

Jounce

Jounce is a tool that I developed less as a framework and more as guidance. The idea behind Jounce is to provide common patterns and best practices for developing large LOB applications in Silverlight using MEF and the MVVM pattern. Jounce relies heavily on MEF to help connect ViewModels and Views, and for routing modules. It provides region management (handling how and where Views are generated), an event aggregator, a versatile navigation framework, and easy logging facilities.

Jounce also includes several quick-starts that demonstrate different ways to manage patterns in Silverlight applications. One example is the use of a special “entity ViewModel” that facilitates tracking changes and firing validations for Create/Read/Edit/Update (CRUD) operations. Another example shows how to integrate with the Silverlight Navigation Framework.

note

Jounce is available online at http://jounce.codeplex.com/.

Table 5.2 provides a high-level overview of the various frameworks, based on statistics taken from CodePlex and feedback from users about the required learning curves.

Table 5.2 MVVM Frameworks

images/c05tnt002.jpg

Taking Silverlight Out-of-the-Box

Silverlight provides a set of powerful features for enterprise applications. Earlier in this chapter, you learned about some of the core frameworks that power Silverlight applications. Now it's time to learn about some advanced features that make Silverlight shine. From dynamic loading to desktop installs, local databases, and inter-application communication, you can find there are plenty of powerful features to meet the demands of your software product.

Dynamic Loading

Silverlight runs on the client browser. This can be extremely beneficial but also introduces some risk. From an enterprise perspective, distributing workload to the client by running business logic and validations locally can benefit the entire system by easing the strain on the central server. As a developer, however, you must take care not to overtax the client's system. Sending too much information can create unwanted delays, and allocating memory for various features and functions may degrade performance.

Dynamic loading helps solve these problems by enabling you to divide your application into logical units that load independently. The initial application is small and results in a faster load time over the network, and a smaller memory footprint on the client. Areas of functionality are loaded on demand as the user requests them. Typically, users launch an application to work in a particular area. Although the entire application may span dozens of areas of functionality, only the ones currently used are loaded into memory and onto the client system.

The easiest way to handle dynamic loading “out-of-the-box” in Silverlight is to take advantage of the MEF. As you learned earlier, MEF contains a special deployment catalog. By default, the deployment catalog simply references the current XAP. You can pass a URI to the deployment catalog and instruct MEF to download a separate XAP file.

To create a dynamic module using MEF, you first create a project using the Silverlight Application template (not the Silverlight Class Library template). The Silverlight Application template is required to compile the code into a XAP file and generate the necessary manifest, while the Silverlight Class Library template generates a standalone assembly. You can delete the App.xaml and MainPage.xaml files because these won't be needed in the dynamic module. In the new project, you can then create classes, types, and controls, and either specific imports or exports as required by your application.

Listing 5.10 shows all the code required to download a dynamic XAP file named Plugin.XAP. After the XAP file is loaded, MEF automatically recomposes the parts and integrates the additional exports into the application. (The deployment catalog must be added to the main container, so this example assumes an aggregate catalog is available that has already been loaded into the main container.)

Listing 5.10 : Example of Loading a Dynamic XAP File

var deploymentCatalog = new DeploymentCatalog("Plugin.XAP");

mainAggregateCatalog.Catalogs.Add(deploymentCatalog);

deploymentCatalog.DownloadAsync();

The deployment catalog has additional methods to enable you to track the progress of the download, receive a notification when the download has completed, and respond to any errors.

Out-of-Browser Applications

Silverlight is a special type of application that is easily delivered over the web. The default place for Silverlight to run is in a trusted sandbox within the browser. Silverlight does not need to be confined to this space, however. Silverlight enables for a special mode called Out of Browser (OOB) that enables your application to run standalone.

There are two important reasons why you might want to consider an OOB application. The first is offline execution. The main limitation of web applications is that they require an active Internet connection to function. For agents in the field using an LOB application to collect information, this can be problematic because they are not always guaranteed connectivity at their customer locations.

By allowing the application to run offline, your users can run the application even when an Internet application doesn't exist. With the use of isolated storage (which will be discussed shortly), you can even store information and forward it when the Internet becomes available. The default mode for OOB works across any platform that Silverlight runs on, including both Windows and OS X.

The second compelling reason to write OOB applications is when you require elevated trust. By default, Silverlight applications (even OOB ones) run in a “security sandbox.” To avoid disruption to the client computer, access to various features such as communication ports, USB, or even disk storage outside of isolated storage is prohibited. There are some applications that require access to these sensitive resources. For example, an application that scans barcodes would need access to the communication and USB ports that connect to the scanning device.

By specifying “elevated trust” for your Silverlight OOB application, you can gain access to these resources. The user is asked to “opt-in” and allow the application access to sensitive data. When this happens, you can do things such as performing COM inter-op and accessing areas in the file system that are normally restricted. Silverlight 5 can also offer direct access to USB ports and provide a facility to p/Invoke or directly call unmanaged code.

Isolated Storage

In many cases you may want to store information locally on the client machine running the Silverlight application. Although Silverlight does not come with an embedded database, it does provide access to a specialized file system known as isolated storage. Isolated storage is not specific to Silverlight and exists as part of the core .NET Framework as an “information sandbox” for applications to store data without requesting elevated trust.

Isolated storage in Silverlight is unique because it provides some control over quotas for storage space and specialized partitions for your data. You can choose to scope data specific to a domain (so that any applications from the same domain may access the data), or to an application. Both modes are specific to the user, so a different user signed on to the same machine cannot directly access the same data.

Isolated storage enables for value/key combinations to be stored in special collections known as site settings (specific to the domain) and application settings (specific to the application). In addition, you can access the file system directly to store and retrieve files. This creates a great opportunity for caching information and storing local data by serializing it to disk.

In an OOB application, you have the opportunity to store local data and allow the application to run offline and disconnected from the Internet. The local data can drive the application and store changes made by the user. When the application comes online, the data can then be transmitted and synchronized with the server.

Several local database options also exist that create databases on top of isolated storage. Many of these are licensed/commercial databases, and a few provide full relational database capabilities including transactions.

For an Open Source option, consider the Open Source Sterling project that I maintain. Sterling is an object-oriented database that automatically serializes most classes and complex object graphs. It supports keys (including foreign keys) and indexes to enable fast in-memory queries that then lazy-load the full objects from disk.

note

You can read more about Sterling and download it online at http://sterling.codeplex.com/.

Communication

Silverlight has a robust communication stack that offers several modes of transmitting data between client and server, web services, and other applications. In addition to out-of-the-box support for standards-based web services, Silverlight can open direct sockets for communication and handle custom protocols.

Silverlight has powerful interoperability with the host HTML Document Object Model (DOM). Silverlight can call JavaScript methods and expose methods for JavaScript to call. This enables integration with traditional ASP.NET Ajax applications and hooks into postback and callback functionality.

The Silverlight WebClient can open any network-based URL and retrieve the data asynchronously. This enables parsing remote web pages, downloading RSS feeds, and even communicating with traditional Plain Old XML (POX)-based solutions. A common technique is to expose data using Representational State Transfer (REST) and JavaScript Object Notation (JSON). The Silverlight web client can access REST resources, retrieve the JSON data, and cast it to a strongly typed object for processing.

One powerful and unique feature in Silverlight is the Local Communication API. This API facilitates communication between different Silverlight applications running on the same computer. This is true regardless of what domain the applications were served from, or whether they run OOB.

To create a communication channel, one application simply instantiates a named sender, and the other creates a receiver with the same name. The creation of channels can include information to restrict the channel to other instances of the same application, to the same domain, or to enable any type of cross-channel communication. After a channel is created, you can simply register for events. And when the sender sends a message, the receiver can fire the event and pass the message.

A practical use for this is for authentication scenarios. The OAuth protocol, for example, requires opening a new window so that the user may authenticate with a separate web page. Although there is a URL for the user to return to, this forces the user to leave the currently running Silverlight application. By using local communication, a separate Silverlight application can receive the completed OAuth request and then communicate with the original application to pass credentials. This enables a seamless login experience without having to restart the Silverlight application.

The Future of Silverlight

Silverlight was formally released in 2007 as a sort of “super JavaScript” interface and has evolved as of the version 5 beta in 2011 to a robust in-browser subset of the full core CLR, with support for offline and out-of-browser modes. Although you've been introduced to a few of the important LOB concepts and features, there is far more functionality available in Silverlight for LOB applications. Following are a few of the key features available as of version 5:

· Multicolumn text modes

· PostScript vector printing

· WS-Trust support (a security standard for web services)

· Support for 64-bit operating systems

· GPU-accelerated three-dimensional (3D) graphics API

· Embedded HTML content (a “web browser” within your Silverlight application)

· Interoperability with Microsoft Office

· Interface with USB and COM ports

· Run unmanaged code using p/Invoke

· Full profiling and test support

Perhaps two of the most powerful and compelling benefits of Silverlight are that it is easily delivered via the web, and it is available on multiple platforms and browsers. This means that your team can focus on building one robust application, rather than a different application for Windows and OS X environments, all without wasting precious cycles on browser-incompatibility issues.

Summary

Silverlight powered the back-end health monitoring system used by Microsoft during the 2010 Vancouver Winter Olympics. It has been used by major cities to provide consumer interfaces for monitoring traffic, and even to provide feedback to the city about issues such as the locations of potholes. The medical community has embraced the rich UI and uses Silverlight for advanced imaging. Financial institutions use it within their SharePoint applications to provide rich, interactive dashboards and drilldowns.

In this chapter, you learned how Silverlight enables you to leverage existing languages and the familiar Visual Studio environment to build LOB applications. The availability of XAML enables powerful workflows with parallel design and development. Silverlight provides hooks and interfaces to build modular applications that are extensible through the use of the Managed Extensibility Framework (MEF).

A special design pattern called MVVM has evolved to take advantage of the unique qualities of data binding provided by the Silverlight framework. Several implementations of the pattern have evolved as Open Source frameworks you can leverage to start building LOB applications right away.

Features like isolated storage and out-of-browser applications make it an ideal platform to build offline solutions that target multiple platforms. Silverlight's communication stack enables you to connect directly to existing SOAP, Plain Old XML (POX), and JavaScript Object Notation (JSON) web services. These features continue to evolve with each successive release, with Silverlight 5 introducing some of the most important LOB features to date.

If you haven't tapped into the power of the Silverlight framework, you'll want to start exploring right away. It just might be the silver lining you've been looking for.

About the Author

Jeremy Likness is a Silverlight-focused developer/architect and technical project manager with sales and entrepreneurial experience, a passion for mentoring and public speaking, and a strong social media presence. In July 2010, he received the Microsoft Most Valuable Professional (MVP) award for his work with Silverlight. Backed by 15 years of experience developing enterprise applications, he currently serves as a senior consultant and project manager for Wintellect. He has worked with software in multiple vertical industries, including insurance, health and wellness, supply-chain management, and mobility. His primary focus for the past decade has been building highly scalable web-based solutions using the Microsoft technology stack with a recent focus on Silverlight and WCF.