What's New in the .NET Framework 3.5
- About the Extensible Application Markup Language (XAML), the XML grammar that new .NET Framework technologies, particularly Windows Presentation Foundation (WPF), use heavily.
- How to create amazing user interfaces by using WPF.
- To create distributed applications using the latest distributed technology, Windows Communication Foundation (WCF).
- To document and design complex business processes using Windows Workflow Foundation (WF).
- How sensitive user data can be better protected through Windows CardSpace.
- About optimizing data access and queries through the use of Language Integrated Query (LINQ).
This lesson will introduce you to the new features available in the .NET Framework version 3.5.
Overview
The .NET Framework is continuously being upgraded and improved through the introduction of brand new technologies and through the extension and enhancement of existing technologies. The last major update to the .NET Framework was version 2.0. In version 2.0, most of the included technologies received major enhancements. The .NET Framework 3.0 was advertised as including a gamut of new technologies but no significant updates to the existing .NET Framework 2.0 technologies. The new technologies in the .NET Framework 3.0 include:
- Windows Presentation Foundation (WPF)
- Windows Communication Foundation (WCF)
- Windows Workflow Foundation (WF)
- Windows CardSpace
The new technologies are illustrated in the following diagram.
The .NET Framework 3.5 is considered an interim update that introduces some enhancements to existing technologies in the form of new controls, fixes, etc. and includes the integration of two new technologies: Language Integrated Query (LINQ / XLINQ) and ASP.NET AJAX. The figure below illustrates the progression of technologies added through versions 2.0, 3.0, and 3.5.
Windows Presentation Foundation (WPF)
The Windows Presentation Foundation (WPF), as its name implies, is the new Microsoft standard for creating user interfaces. WPF is a consolidation of previously used presentation technologies including Windows Forms, GDI+, Windows Media Player, and DirectX. WPF provides the following benefits:
- A common platform and environment for developing cutting edge user interfaces that combines all previously used Microsoft presentation technologies. WPF is capable of interacting with all of the previous technologies to aid in progressive application upgrades. All Microsoft presentation development going forward should use WPF or the subset of WPF, Silverlight.
- The ability for developers and designers to work together, simultaneously on projects - a result of the proper division of markup from code and the correct usage of tools.
- A common and standardized technology that can be used for both Windows and Web applications. WPF offers the ability to create standalone WPF applications which are analogous to Windows Forms applications and to create XAML Browser Applications (XBAPs) - the same WPF applications hosted in a Web browser and subject to more stringent security settings.
The features included in the WPF standard are:
- A complete application framework integrated into the .NET Framework 3.0
- Layout control and user interface controls
- Complete support for styles and templates
- Advanced text formatting and display capabilities (through ClearType) that greatly improve text readability
- Support for both fixed layout and flow layout documents and the introduction of a brand new fixed document format standard known as the XML Paper Specification (XPS) document standard
- Easy display and integration of all image formats, video, audio, 2D graphics, 3D graphics as well as graphics transformations and effects and animations
- Advanced data binding capabilities
The figure below illustrates the WPF architecture:
The Extensible Application Markup Language (XAML)(see footnote)
The Extensible Application Markup Language (XAML - pronounced "zammel") is an XML grammar that is used to define objects and their contained properties and methods that are typically used to construct a user interface. XAML has been made popular through its use in the Windows Presentation Foundation (WPF), which is used to define the Windows Vista user interface. XAML was created by Microsoft and introduced with the .NET Framework version 3.0. It can be used to define 2D and 3D graphics and animations.
Elements that are declared in XAML generally represent objects that exist in the .NET Framework and attributes generally represent properties of an object. Consider the following XAML fragment:
<TextBlock Margin="15,8,98,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="38" FontFamily="Segoe UI"> <Run FontSize="14" Text="Welcome to my Fantasy League Manager"/> </TextBlock>
The XAML fragment above is used to define a TextBlock on a WPF Window. When the XAML parser encounters this element, it creates an instance of the System.Windows.Controls.TextBlock class. The TextBlock class is used to display small amounts of flow content, such as text or labels. In the example above, the TextBlock contains a Run child object that accommodates further formatting of contained text. The attributes of the TextBlock and Run elements are declared to set values for the properties of the instantiated TextBlock and Run objects. The XAML shown above declares the heading displayed on the window shown in the figure below:
The great part of using XAML to define user interface components is that XAML is programming-language and development-environment agnostic. Just as with other .NET Framework technologies and Web technologies, you can create XAML documents by using any text editor and can parse and manipulate XAML by using virtually any programming language. WPF is optimized to read, parse, and execute XAML.
Bear in mind when working with XAML, that you must follow XML syntax rules:
- XML is case-sensitive; hence, XAML is case-sensitive. In most cases, XAML casing must match the casing of underlying objects and properties.
- White space in XAML is consolidated into a single space and is, in essence, not significant.
-
All XML documents must have a single root, or document-level, element. The document element for XAML files, when used with WPF, should be one of the following depending upon the type of application being created.:
- <Window>
- <UserControl>
- <Page>
Attribute Syntax vs. Property Element Syntax
The implementation of XAML illustrated in the example shown above is the simplest and most common XAML configuration for assigning values to attributes and is referred to as, not surprisingly, attribute syntax. When creating an XML grammar, extended data values may be defined through either attributes or child elements. The same applies to the XAML standard. By default, properties are defined for objects through attributes in XAML and this method works great for simple property values. However, some properties require more complex values to be assigned to them, such as child objects (reference types), or, potentially, a property may accommodate multiple values to be assigned to it. In such a scenario, a simple attribute assignment won't suffice.
In scenarios where attribute syntax is not adequate for assigning a value to a property, additional elements should be used to identify the property value(s). When elements are used to identify property values in XAML, it is referred to as "property element" syntax. Any property values declared by using attribute syntax should also be able to be declared by using property element syntax, however, the opposite is rarely true.
As an example, the XAML used to define the background of the WPF window shown above uses property element syntax as shown in the code snippet below.
<Window.Background> <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5" SpreadMethod="Pad"> <GradientStop Color="#FF495B24" Offset="0"/> <GradientStop Color="#FFB4C397" Offset="0.416"/> </LinearGradientBrush> </Window.Background>
In the code shown above, the background of the window could optionally be declared by using attribute syntax as <Window Background="<property values...>" />. However, look at the code snippet above. How can a single attribute value summarize the more complex LinearGradientBrush settings? It is not possible. Hence, in order to adequately accommodate more advanced property values, the values must be stated by using elements instead of attributes as shown above.
Markup Extensions
When creating XAML documents, bear in mind that the XAML parser is creating object instances as it encounters XAML elements. In many scenarios, the default XAML parser behavior may result in non-optimal use of memory. For instance, when defining styles, behind the scenes, a formal Style object is created to hold the style information. Style information, in general, will likely be shared across many objects in the user interface. By specifying style information at the element level for each object in the user interface, many style objects are created behind the scenes that hold identical information. Fewer resources would be consumed by creating a single Style object and sharing it amongst the user interface objects. Additionally, style information could be managed and updated much more easily if it were defined in a single location.
The solution to better memory optimization is to declare a Style (or other object) as a global, or shared, resource. A shared resource can then be referenced by other objects in the user interface through markup extensions. A markup extension allows you to define an attribute value as a reference to a shared resource. There are several types of markup extensions:
- Binding Markup Extension - used in data binding
- Static Resource Markup Extension - used to reference static shared resources (resources declared and available at compile time)
- Dynamic Resource Markup Extension - used to reference dynamic shared resources (resources not available until run time)
A markup extension reference is delimited using opening and closing curly braces ({}). The example below illustrates gradient background colors used as window resources and referenced using dynamic resource markup extensions.
The XAML code shown below is used to generate the window shown earlier.
Code Sample: WhatsNewNETFramework35/Demos/MyFantasyPicks/MyFantasyPicks/Window1.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyFantasyPicks.Window1"
Title="Fantasy League Manager 2008" Height="216" Width="529" x:Name="DisplayMyPicks" xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Window.Resources>
<Color x:Key="myGreenColor">#FFB4C397</Color>
<Color x:Key="myDarkGreenColor">#FF495B24</Color>
</Window.Resources>
<Window.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5" SpreadMethod="Pad">
<GradientStop Color="{DynamicResource myDarkGreenColor}" Offset="0"/>
<GradientStop Color="{DynamicResource myGreenColor}" Offset="0.431"/>
</LinearGradientBrush>
</Window.Background> ---- Code Omitted ---- </Window>
XAML Namespaces
XAML documents created using Microsoft tools will typically contain two namespace declarations:
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" - This is thee default namespace and is a reference to the WPF framework.
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - This is a reference to the XAML standard. The namespace is generally qualified with the "x" prefix.
Events
XAML documents, as implemented by Microsoft technologies, are built around the same basic architecture as ASP.NET documents (Web forms, Web services, Web user controls, etc). XAML documents have associated code behind files. The XAML document is a text-based document that contains the XAML markup. A code behind file is an associated file that contains a class, properties, methods, etc in a particular .NET-compliant programming language and is used to handle events initiated by objects declared in the XAML markup. Code behind files are generally compiled into a .NET assembly and are associated with the XAML markup file through the x:Class attribute in the document element of the XAML markup file.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="MyFantasyPicks.Window1"> </Window>
In the sample XAML above, the x:Class attribute identifies the Window1 class residing in the MyFantasyPicks namespace as the class that will handle events initiated by objects in the Window1 XAML file.
Routed Events
XAML elements correlate to .NET Framework objects. .NET Framework objects are fully object oriented. One characteristic of objects is that they define behavior through function members. The most common type of function member is a method. A method can be called directly by another piece of code or can be identified as functionality to be performed in response to a user-initiated event. The most common user-initiated event in a graphical user interface (GUI) is a click event carried out by the user clicking on UI elements with the mouse.
Any XAML element that correlates to a .NET Framework object that contains a particular event can directly assign a handler to handle that event. For instance, a XAML Button element correlates to a .NET Framework Button object. The .NET Framework Button object contains an OnClick event. As such, the XAML Button element can assign an event handler to handle the Click event as shown in the Button element declaration below.
<Button Click="btnDisplayPicks_Click" HorizontalAlignment="Left" Margin="15,41,0,0" VerticalAlignment="Top" Width="189" Height="23" Content="Display My Picks" x:Name="btnDisplayPicks" />
The associated event handler, btnDisplayPicks_Click, resides in the code behind file. In this example, the code behind is written by using C#. The event handler opens the XML file and displays the stored picks as shown in the code listing below:
Code Sample: WhatsNewNETFramework35/Demos/MyFantasyPicks/MyFantasyPicks/Window1.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace MyFantasyPicks
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
/// <summary>
/// This method opens the XML file and displays the stored picks.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnDisplayPicks_Click(object sender, RoutedEventArgs e)
{
// Create an XMLDocument object.
XmlDocument xmlDoc = new XmlDocument();
// Load the XML file.
xmlDoc.Load(@"FantasyPick.xml");
// We should have error handling
// and more elaborate code in here
// but this works for an example.
// Reference the first pick element.
XmlAttributeCollection pickElementAttributes = xmlDoc.DocumentElement.FirstChild.Attributes;
XmlNodeList pickElementChildren = xmlDoc.DocumentElement.FirstChild.ChildNodes;
// Display my picks.
txtPicks.Text = "My fantasy picks for week number " + pickElementAttributes[0].Value + " are:\r\n";
// Iterate through the picks.
for (int i = 0; i < pickElementChildren.Count; i++)
{
txtPicks.Text +=
pickElementChildren[i].Attributes[0].Value +
" playing " +
pickElementChildren[i].Attributes[1].Value +
"\r\n";
}
// Clean up.
pickElementChildren = null;
pickElementAttributes = null;
xmlDoc = null;
}
}
}
XAML is an XML grammar and, as such, it is built in a hierarchy. Most objects that contain events are nested inside of a containing object.
One classic user interface design practice declared a central event handler at the container object level that would handle events for all contained child objects. This design practice required the container object to also implement the event handled. For example, a centralized click event handler could be created at a window level. Due to the bubbling up behavior of events, the click events for all contained child controls would then be handled at the window level. This practice was possible in classic Windows development because the Window object implemented a click event handler.
Controls and objects in XAML have been streamlined and optimized so that container objects contain very few event handlers. However, just about any object represented by XAML may fire an event contained by another object. In particular, a container object can easily fire events of contained objects even if the container object does not directly implement the event. This behavior is possible through XAML routed events.
A routed event is an event call that can be routed through an object separate from the object that contains the event. When a container object declares a routed event for contained objects, such as a StackPanel that handles Click events for child contained Button objects, the declaration is made at the container object level and the type of object for which the event is being handled qualifies the event name. In the example below, the StackPanel contains a Button The StackPanel does not implement a Click event, however the StackPanel handles the click event for all contained Button objects by declaring the Button.Click as a routed event.
<StackPanel Button.Click="Button_ClickHandler">
<Button HorizontalAlignment="Left" Margin="15,41,0,0" VerticalAlignment="Top" Width="189" Height="23" Content="Display My Picks" x:Name="btnDisplayPicks">
<Button.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF3F3F3" Offset="0.005"/>
<GradientStop Color="#FFEBEBEB" Offset="0.44"/>
<GradientStop Color="#FFDDDDDD" Offset="0.531"/>
<GradientStop Color="#FFDAB925" Offset="0.904"/>
</LinearGradientBrush>
</Button.Background>
</Button>
</StackPanel>
The full XAML associated with the event handler shown above is shown in the code listing below:
Code Sample: WhatsNewNETFramework35/Demos/MyFantasyPicks/MyFantasyPicks/Window1.xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyFantasyPicks.Window1"
Title="Fantasy League Manager 2008" Height="216" Width="529" x:Name="DisplayMyPicks" xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Window.Resources>
<Color x:Key="myGreenColor">#FFB4C397</Color>
<Color x:Key="myDarkGreenColor">#FF495B24</Color>
</Window.Resources>
<Window.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5" SpreadMethod="Pad">
<GradientStop Color="{DynamicResource myDarkGreenColor}" Offset="0"/>
<GradientStop Color="{DynamicResource myGreenColor}" Offset="0.431"/>
</LinearGradientBrush>
</Window.Background> ---- Code Omitted ---- </Window>
The figure below shows the WPF form this XAML code will render after the button has been clicked and the event handler executed:
XAML Tools
The XAML above was written using Microsoft development tools. Although XAML was created by Microsoft, there are many third party XAML editors and utilities available. The primary XAML tools from Microsoft are described below:
Visual Studio 2008
Visual Studio is Microsoft's premiere integrated software development environment. Visual Studio now hosts management utilities as well as development tools.s
Expression Blend
Microsoft Expression Suite includes a new line of cutting edge tools for designers. One such tool, Microsoft Expression Blend, is used for XAML development in both WPF and Silverlight. Microsoft designed the Expression suite of tools to integrate nicely with Visual Studio. We'll look more closely at Expression Blend in another section of this course.
For more information on WPF, visit the Windows client Web site located at http://windowsclient.net. The figure below illustrates the WindowsClient.NET Web site.
Windows Communication Foundation (WCF)
From its inception, the .NET Framework has included functionality for creating distributed applications. A distributed application includes components that reside in different locations that come together to form an integrated application. From the get-go, the .NET Framework has included advanced support for creating, hosting, and consuming Web services.
In a nutshell, a Web service is a component, similar to a procedure file or an object with methods, that is callable over the Web using Web protocols. Just as a procedure file or object with methods, a Web service is called from code to provide a service or benefit to the calling code. By default, Web services use HTTP as a communication protocol and an XML grammar called the Simple Object Access Protocol (SOAP), to transport data. Just as any client with a Web browser can view a Web page, a Web service can be called by any programming language that is capable of working with open Web standards. And, due to the use of HTTP as a communication protocol, Web services are generally accessible through firewalls.
The use of SOAP and HTTP make a Web service broadly available, however, a side effect of this is that the communication is not optimized for any particular environment. If you have control of both the client and the server in a distributed environment, you can use more efficient means of communicating between them. The .NET Framework offered .NET remoting as a solution to creating a distributed application where you controlled both the client and the server. .NET remoting uses more efficient protocols and transport mechanisms but was also more complex to implement.
The .NET Framework also included functionality for working with other distributed technologies.
Windows Communication Foundation (WCF)
As a new, consolidated solution to creating distributed systems, Microsoft introduced Windows Communication Foundation (WCF) with the .NET Framework version 3.0. WCF encompasses all preceding distributed application development technologies offered by Microsoft and is capable of continuing to intercommunicate with those technologies for backward compatibility. WCF simplifies distributed application development; however, its extensibility allows it to keep up with and incorporate the latest technologies and advances. The following figure shows the WCF architecture.
WCF provides:
- An advanced system for configuring endpoints in a distributed environment.
- The ability to configure communication protocols to be used between endpoints.
- A reliable system for sending and receiving messages between endpoints.
- The ability to send messages may be sent asynchronously, secured, and within managed transactions.
- The functionality for serializing and deserializing primitive, complex, and binary data.
The WCF architecture, as illustrated in the figure above:
- Includes contracts for describing all communication terms, protocols, and the overarching agreement and description between endpoints.
- Provides a service runtime that includes classes and functionality in the .NET Framework to initiate the communication process.
- Provides a messaging system that includes the functionality that carries out the packaging and handling of messages. Messages are processed through two types of channels:
- Transport channels - reads and writes messages to the network once the messages are packaged.
- Protocol channels - implements the various WS protocols when messages are being read and written and packaged.
- Provides activation and hosting of services. A WCF service must be activated or hosted to be of any use. Services are created by using .NET programming languages and compiled into .NET assemblies. The methods available for hosting or activating a service correlate to the two types of assemblies created by using .NET: out-of-process (.exe) and in-process (.dll). An out-of-process assembly must be called directly and resides in its own memory space. This type of service assembly is said to be activated. An in-process assembly must be loaded into the memory space of a host application such as Internet Information Services (IIS). This type of service assembly is said to be hosted..
WCF is an elaborate system for creating distributed systems by using the .NET Framework 3.0. (see footnote)
WCF Example
In this module, we will show how to create a hosted WCF service by using Visual Studio 2008. If you are using a different development environment or editor, the steps involved will differ. When using Visual Studio 2008, if you choose to create a Web application WCF service, the service will be hosted by using IIS. If you choose to create a WCF application project type, it will be a self-activated service.
In this example, we will get our fantasy picks from a WCF hosted service and display them on a WPF form.
The Service
The first step in the process of illustrating WCF is to create a WCF service. In Visual Studio 2008, a WCF service can be created in one of two ways. If you want to create a WCF service that is hosted by IIS and fulfills the same role as a standard Web service, select the New Web Site option from the File menu. When prompted with the New Web Site dialog, select the option to create a WCF service as shown in the figure below.
If you choose to create a self-activating WCF service, select the New Project option from the File menu. When prompted with the New Project dialog, under the language of your choice, select the WCF Service Library option as shown in the following figure:
Once the option is selected for creating a WCF service, the first step in the process is to configure the interface. It is a standard practice to prefix interface names with an uppercase "I".
As a new, consolidated solution to creating distributed systems, Microsoft introduced Windows Communication Foundation (WCF) with the .NET Framework version 3.0. WCF encompasses all preceding distributed application development technologies offered by Microsoft and is capable of continuing to intercommunicate with those technologies for backward compatibility. WCF simplifies distribute application development while being extensible in order to keep up with and incorporate the latest technologies and advances. The following figure shows the WCF architecture.he service interface. The service class used in this example is shown in the code listing below:
Code Sample: WhatsNewNETFramework35/Demos/FantasyLeagueService/App_Code/FantasyLeagueService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Xml;
using System.Web.Hosting;
public class FantasyLeagueService : IFantasyLeagueService
{
public string GetPicks()
{
// Declare the return string.
string returnValue = "";
// Create an XMLDocument object.
XmlDocument xmlDoc = new XmlDocument();
// Load the XML file.
xmlDoc.Load(HostingEnvironment.ApplicationPhysicalPath + @"App_Data\FantasyPick.xml");
// We should have error handling
// and more elaborate code in here
// but this works for an example.
// Reference the first pick element.
XmlAttributeCollection pickElementAttributes = xmlDoc.DocumentElement.FirstChild.Attributes;
XmlNodeList pickElementChildren = xmlDoc.DocumentElement.FirstChild.ChildNodes;
// Display my picks.
returnValue = "My fantasy picks for week number " + pickElementAttributes[0].Value + " are:\r\n";
// Iterate through the picks.
for (int i = 0; i < pickElementChildren.Count; i++)
{
returnValue +=
pickElementChildren[i].Attributes[0].Value +
" playing " +
pickElementChildren[i].Attributes[1].Value +
"\r\n";
}
// Clean up.
pickElementChildren = null;
pickElementAttributes = null;
xmlDoc = null;
return returnValue;
}
}
The code listing above should be straightforward to .NET programmers. The only items to point out are the reference to the System.ServiceModel namespace and that the service class implements the IFantasyLeagueService interface.
If you run the WCF service application from within Visual Studio 2008, you will be given a page showing you that the service is running successfully. However, unlike classic ASP.NET Web services, you cannot test the WCF service from this page. The Visual Studio 2008 WCF service output page is shown in the figure below.
The Client
Once a service is in place, the service is ready to be consumed by a client application. Any application type created by using Visual Studio 2008 should be able to serve as a WCF client. Once a client application is open in WCF, right-click the project in the Solution Explorer and select Add Service Reference. The Add Service Reference dialog should appear as shown in the following figure.
The code necessary in our WPF client code behind is now surprisingly short. With the Service Reference in place, the click event handler in the Window1.xaml.cs code behind file has now been consolidated to that shown in the following snippet.
Code Sample: WhatsNewNETFramework35/Demos/FantasyLeagueClient/MyFantasyPicks/Window1.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace MyFantasyPicks
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
/// <summary>
/// This method opens the XML file and displays the stored picks.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnDisplayPicks_Click(object sender, RoutedEventArgs e)
{
// Go get the picks from the fantasy league service.
// Call the method synchronously for now.
FantasyLeagueService.FantasyLeagueServiceClient fantasyManager = new FantasyLeagueService.FantasyLeagueServiceClient();
txtPicks.Text = fantasyManager.GetPicks();
}
}
}
Windows Workflow Foundation (WF)
Windows Workflow Foundation (WF) is used to document workflows:
- System-based
- Human-based
- A combination of both
A workflow is a real world set of activities that can be documented in their order of precedence. WF is a layer on top of the .NET Framework version 3.0 and is created and maintained by using .NET programming languages. Visual Studio 2008 provides a designer for WF and all future Microsoft products that implement a workflow of some type (this includes most products) will use and benefit from WF. Workflows are documented graphically using the WF designer. The creation of the underlying objects, code, and services is mostly automated.
In many scenarios, a workflow will represent a process that may require human interaction at one or more points along the process. For example, in the fantasy league manager, when users are drafting players to be on their fantasy teams, the workflow has a process to place a player on a user's fantasy team. However, the workflow cannot carry out this process without a user making a player selection (drafting a player). A fantasy draft typically takes a few hours to an entire day, depending upon the intensity of the users involved. As such, it will take the workflow an unknown amount of time before it can proceed. If the fantasy league manager were servicing many teams, each team should have a separate workflow instantiated in memory. If a workflow is waiting in limbo for hours on users to make draft decisions before moving on, it would be beneficial to system performance if a workflow could go into a sleep state and not consume memory while waiting.
WF includes the ability to put a workflow to sleep for an indefinite amount of time. When a workflow is put to sleep, it is serialized to a data store, where it can persist indefinitely and even survive system reboots. When a workflow is sleeping, WF will listen for requests for the workflow. When a request is initiated, the workflow is awaken and re-instantiated to resume from where it left off.
The figure below illustrates the WF architecture.
WF provides:
- A runtime engine and services for managing workflows. Workflow process steps may be represented by objects and services.
- Advanced design tools and modeler through Visual Studio 2008.
- Indefinite persistence of workflows.
- Workflow management through transactions, tracking, timing, and threading.
The figure below shows the Visual Studio 2008 WF designer with a workflow for the Fantasy League Manager in process.
The code listing shown below correlates to the events that would be fired in conjunction with the workflow shown above.
Code Sample: WhatsNewNETFramework35/Demos/FantasyLeagueManagerWF/FantasyLeagueManagerWF/FantasyLeagueProcess.Designer.cs
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Reflection;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace FantasyLeagueManagerWF
{
partial class FantasyLeagueProcess
{
#region Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
[System.Diagnostics.DebuggerNonUserCode]
private void InitializeComponent()
{
this.CanModifyActivities = true;
this.StatsNotification = new System.Workflow.Activities.CodeActivity();
this.UpdateStats = new System.Workflow.Activities.WebServiceOutputActivity();
this.CallUpdateStats = new System.Workflow.Activities.WebServiceInputActivity();
this.SelectNewPlayer = new System.Workflow.Activities.CodeActivity();
this.ReviewCurrentStats = new System.Workflow.Activities.CodeActivity();
this.UserAuthentication = new System.Workflow.Activities.CodeActivity();
//
// StatsNotification
//
this.StatsNotification.Name = "StatsNotification";
this.StatsNotification.ExecuteCode += new System.EventHandler(this.StatsNotification_ExecuteCode);
//
// UpdateStats
//
this.UpdateStats.InputActivityName = "CallUpdateStats";
this.UpdateStats.Name = "UpdateStats";
//
// CallUpdateStats
//
this.CallUpdateStats.InterfaceType = typeof(FantasyLeagueManagerWF.FantasyLeagueService);
this.CallUpdateStats.MethodName = "GetStats";
this.CallUpdateStats.Name = "CallUpdateStats";
this.CallUpdateStats.InputReceived += new System.EventHandler(this.UpdateStats_InputReceived);
//
// SelectNewPlayer
//
this.SelectNewPlayer.Name = "SelectNewPlayer";
this.SelectNewPlayer.ExecuteCode += new System.EventHandler(this.SelectNewPlayer_ExecuteCode);
//
// ReviewCurrentStats
//
this.ReviewCurrentStats.Name = "ReviewCurrentStats";
this.ReviewCurrentStats.ExecuteCode += new System.EventHandler(this.ReviewCurrentStats_ExecuteCode);
//
// UserAuthentication
//
this.UserAuthentication.Name = "UserAuthentication";
this.UserAuthentication.ExecuteCode += new System.EventHandler(this.UserAuthentication_ExecuteCode);
//
// FantasyLeagueProcess
//
this.Activities.Add(this.UserAuthentication);
this.Activities.Add(this.ReviewCurrentStats);
this.Activities.Add(this.SelectNewPlayer);
this.Activities.Add(this.CallUpdateStats);
this.Activities.Add(this.UpdateStats);
this.Activities.Add(this.StatsNotification);
this.Name = "FantasyLeagueProcess";
this.CanModifyActivities = false;
}
#endregion
private CodeActivity ReviewCurrentStats;
private CodeActivity SelectNewPlayer;
private WebServiceInputActivity CallUpdateStats;
private WebServiceOutputActivity UpdateStats;
private CodeActivity StatsNotification;
private CodeActivity UserAuthentication;
}
}
Comprehensive coverage of WF is beyond the scope of this course. (see footnote)
Windows CardSpace
Windows CardSpace is Microsoft's new digital identity management system. CardSpace is client-side software that is included with the .NET Framework 3.0. CardSpace stores a user's digital identities and presents them to users in the form of visual cards as shown in the following figure.
CardSpace is used to identify users over the Web. Users can create their own identities and verify those identities through third party vendors. When
the user visits a Web site that is Cardspace enabled, Windows will display the user's
defined Cardspace identities in a dialog, including information on the Web site making the request. The user can then select the identity to use for authentication at the Web site. CardSpace can then contact the third party vendor who issued the digital identity to the user to verify that the user identity is valid and, in turn, acquire a digitally signed XML token to send to the Web site for authenticating the user. The figure below illustrated the overall process of CardSpace authentication.
CardSpace is built on the latest Web Service protocols and provides:
- A unified, secure, private, and interoperable method for managing digital identities
- Support for any digital identity system
- User control of digital identities
- Replacement of password-based Web login mechanisms
- Improved user confidence in Web security and authentication
For a greater understanding of the design concepts that Microsoft had in mind when crafting CardSpace, read the Laws of Identity located at http://msdn2.microsoft.com/en-us/library/ms996456.aspx. CardSpace is being quickly adopted by vendors industry-wide. Extensive coverage of CardSpace is beyond the scope of this course. (see footnote)
Language Integrated Query (LINQ)
The final major addition to the .NET Framework in version 3.5 is Language Integrated Query (LINQ), the purpose of which is to make application data more accessible. SQL queries that pull data from a relational database schema are abstracted away from business logic and middle-tier code. Furthermore, data is generally represented at the business logic and code level through objects, arrays, and collections. Developers regularly have to search these constructs with tailor-made loops.
LINQ makes it easier to get at data stored in objects and collections. It can also be used to query relational data stored in databases, XML data, and other data sources. However, data queried by using LINQ must be stored as objects. If data is queried from a relational data source using LINQ, it must first be represented using an object model.
LINQ is covered in more detail in a module later in this course. (see footnote)
LAB: Training Tool Using WPF and WCF
In the following exercises, you will create an online training tool using:
- Visual Studio 2008
- Optionally, Expression Blend
- XAML
- WPF
- WCF
This module has introduced new technologies available as of the .NET Framework version 3.0 and version 3.5. We'll create a training tool from scratch using WPF and WCF. As we haven't covered data access, we'll pul the training data from the standalone XML file.
Exercise: Create a WCF Service
In this exercise, you will create a WCF service that provides functionality used in the training tool.
- Start or open Visual Studio 2008. If you are using Microsoft Windows Vista, be sure to right-click the Visual Studio icon and select Run as Administrator to start Visual Studio with proper permissions to run a WCF service.
- Select File > New Web Site.... Be sure that the ".NET Framework 3.5" is selected in the target dropdown at the top-right of the dialog.
- Under the Visual Studio Installed Templates, select ASP.NET Web Site. Name your project MyTrainingPortal and select Visual C# for the language, then click OK.
- Right-click the project in Solution Explorer and select Add New Item...
- Under the Visual C# Category, scroll down and select WCF Service and name the file TrainingService.svc then click Add.
- Double-click the ITrainingService.cs in the App_Code folder to open it. Modify the body of the interface so that it contains three method signatures:
- The first method signature should accept a single string type input parameter representing the unique id assigned to a course and the method should return a string of the course title.
- The second method signature should accept a single string type input parameter representing the unique id assigned to a course and the method should return a string containing all of the topics for the course.
- The third method signature should accept a single string type input parameter representing the name of a topic and the method should return a string containing the details for the topic.
- The resulting interface should resemble that shown in the code listing below:
[ServiceContract] public interface ITrainingService { [OperationContract] string GetCourseTitle(string courseId); [OperationContract] string GetTopics(string courseId); [OperationContract] string GetTopicDetailsByName(string topicName); } - Now that the contract for the service (the interface) is in place, the next step of the process is to implement the interface in a class that will provide the functionality for the service. Double-click the TrainingService.cs file in the App_Code folder inside Solution Explorer. Include the following two "using" clauses at the top of the class file:
namespace in your class file, in the using section at the top.
using System.Xml;
- Next we will add an XML file containing course information. The XML data source schema is shown below. Create the schema and then populate it with several elements of data for testing. Save the XML file as CourseLibrary.xml inside the App_Data folder of your solution. NOTE: You can alternatively use a completed XML data file located at ClassFiles\WhatsNewNETFramework35\Solutions\MyTrainingPortal\App_Data\CourseLibrary.xml.
<?xml version="1.0" encoding="utf-8" ?> <Library> <Course id="" name=""> <Topic id="" title=""></Topic> </Course> </Library>
- Next, let's create the code for the GetCourseTitle method. This method will be used to retrieve and display the course title on the training portal. All of the methods in this service will open and work with the same XML file. In a real world scenario, we'd optimize any code so that it was not duplicated. In this example, for simplicity, we'll duplicate the two lines of code that open and load the XML file. Another thing to note, you cannot directly access the ASP.NET Server object in a hosted WCF service although it appears that you should be able to. Instead, you'll need to use the ApplicationPhysicalPath property of the System.Web.Hosting.HostingEnvironment class when referencing files in the project, such as the XML data source file. Attempt to create the method on your own and then refer to the example code below. Your resulting code should resemble the example.
public string GetCourseTitle(string courseId) { // Create an XML document object. XmlDocument xmlDoc = new XmlDocument(); // Load the document. xmlDoc.Load(HostingEnvironment.ApplicationPhysicalPath + @"App_Data/CourseLibrary.xml"); // Locate the course. XmlNodeList nodeList = xmlDoc.SelectNodes("//Course[@id='" + courseId.ToString() + "']"); // Load the course title. if (nodeList.Count > 0) { return nodeList[0].Attributes[1].InnerText; } else { return "No such course found."; } } - The code for the remaining methods will be very similar in concept. Go ahead and attempt to complete the methods on your own. If you run into problems, the completed methods should resemble the methods shown below.
public string GetTopics(string courseId) { // Create an XML document object. XmlDocument xmlDoc = new XmlDocument(); // Load the document. xmlDoc.Load(HostingEnvironment.ApplicationPhysicalPath + @"App_Data/CourseLibrary.xml"); // Locate the course. XmlNodeList nodeList = xmlDoc.SelectNodes("//Course[@id='" + courseId.ToString() + "']/Topic"); // Load the topics. if (nodeList.Count > 0) { string topics = ""; foreach (XmlNode node in nodeList) { topics += node.Attributes["title"].InnerText + "|"; } return topics; } else { return "No such course found."; } } public string GetTopicDetailsByName(string topicName) { // Create an XML document object. XmlDocument xmlDoc = new XmlDocument(); // Load the document. xmlDoc.Load(HostingEnvironment.ApplicationPhysicalPath + @"App_Data/CourseLibrary.xml"); // Locate the topic. XmlNodeList nodeList = xmlDoc.SelectNodes("//topic[@name='" + topicName.ToString() + "']"); // Load the topic content. if (nodeList.Count > 0) { return "<h2>" + nodeList[0].Attributes["title"].InnerText + "</h2><p>" + nodeList[0].InnerText + "</p>"; } else { return "<h2>No such topic found.</h2>"; } } - Save all changes and press F5 to test the service. If prompted to enable debugging, select the option to let Visual Studio modify the web.config for you and click OK. If the service built successfully and all is good, a browser window similar to the following figure should be displayed.
Exercise: Consume the WCF Service Using a WPF Application
In this exercise, you will create a new version of the online training tool by using a WPF Application. The WPF application will serve as a client to the WCF service created above.
- From the main Visual Studio menu, select File > Add > New Project. This will add a new project to the current solution.
- Note that if you just completed the last exercise, you will need to stop debugging (Shift F5) if you haven't yet done so.
- Under the Project Types panel, expand the Visual C# node then select the Windows node. Select WPF Application and assign the project a name such as MyTrainingPortalClientWPF and click OK.
- Open Window1.xaml in the XAML editor and design a User Interface similar to the following figure:
- A Grid control should already exist in Window1.xaml. Define grid columns and rows to create the correct layout for the page.
- Drop Rectangle controls into the grid cells and set their Fill property to a desired background color.
- Drop a TextBlock control into the footer and configure it to display the footer label.
- Drop a TextBlock control into the sidebar navigation for displaying the course title.
- Drop a StackPanel control into the sidebar navigation for adding button to so that we can display topics.
- Drop a TextBlock control into the white body cell for displaying the topic header. Drop another TextBlock control into the white body cell for displaying the topic content.
- Right-click the project in the Solution Explorer and add a new folder named Images. Right-click the Images folder and add the existing image for the header from the following location:
\ClassFiles\WhatsNewNETFramework35\Exercises\Images\MTP.gif
- Drop an Image control onto the header cell and set the Image control's Source property to the newly imported MTP image.
- Drop a TextBlock control onto the header cell and configure it to display the header label.
- Drop a TextBlock and a Button control onto the header cell and configure them to perform the topic search. The resulting form as shown in Visual Studio 2008 is shown in the following figure.
- The XAML for recreating the design of the form is shown in the code listing below:
<Window x:Class="MyTrainingPortalClientWPF.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="My Training Portal" Width="794" Height="473" Loaded="PageLoaded"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="273*"/> <ColumnDefinition Width="521*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="107*"/> <RowDefinition Height="312*"/> <RowDefinition Height="54*"/> </Grid.RowDefinitions> <Rectangle Grid.Row="1" Name="rectangle3" Stroke="Black" Fill="Cornsilk"/> <StackPanel Grid.Row="1" Margin="14,36,16,24" Name="spTopics" Opacity="0" HorizontalAlignment="Left"> </StackPanel> <Rectangle Grid.ColumnSpan="2" Name="rectangle1" Stroke="Black" Fill="AliceBlue"/> <Rectangle Grid.ColumnSpan="2" Grid.Row="2" Name="rectangle2" Stroke="Black" Fill="AliceBlue"/> <TextBlock Grid.Row="2" Margin="14,6,17,0" Name="textBlock1" Text="copyright 2009 - my training portal" TextAlignment="Center" Grid.ColumnSpan="2" FontWeight="Normal" FontSize="11" Height="20.922" VerticalAlignment="Top"/> <TextBlock Grid.Column="1" Grid.Row="1" Margin="9,8,17,0" Name="tbTopicHeader" Height="23" VerticalAlignment="Top" Text="" FontSize="16"/> <TextBlock FontSize="12" Margin="9,36,17,24" Name="tbTopicContent" Text="" Grid.Column="1" Grid.Row="1" FontWeight="Normal"/> <Image Grid.Column="1" Height="32" HorizontalAlignment="Right" Name="image1" Stretch="None" VerticalAlignment="Top" Width="62" Source="/MyTrainingPortalClientWPF;component/Images/MTP.gif" Margin="0,2,3,0"/> <TextBlock Grid.Column="1" Margin="221,37,4,49" Name="textBlock2" Text="Welcome to My Training Portal" TextAlignment="Right"/> <TextBox Grid.Column="1" Height="23" HorizontalAlignment="Right" Margin="0,0,82,3" Name="txtSearchTerm" VerticalAlignment="Bottom" Width="162" FontSize="11" FontWeight="Normal" VerticalContentAlignment="Center"/> <Button Grid.Column="1" Height="23" HorizontalAlignment="Right" Margin="0,0,4,3" Name="btnSearch" VerticalAlignment="Bottom" Width="75" FontWeight="Normal" FontSize="11">Find Topic</Button> <TextBlock Grid.Row="1" Height="23" Margin="14,8,8,0" Name="tbCourseTitle" VerticalAlignment="Top" Text=""/> </Grid> </Window>
- Right-click the WPF project in the Solution Explorer and select the option to add a Service Reference. Click the Discover button to locate the service in the current solution. Assign the reference a meaningful namespace name such as TrainingService and click OK.
- Assign an event handler to the Loaded event of the XAML Window as shown in the XAML above.
- In the code behind, create the event handler and use it to retrieve the course title and display it. The resulting code in the code behind is shown in the code listing below:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace MyTrainingPortalClientWPF { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { TrainingService.TrainingServiceClient service = new TrainingService.TrainingServiceClient(); public Window1() { InitializeComponent(); } public void PageLoaded(object sender, RoutedEventArgs e) { // Display the course title. // We've hard coded the course id for now. tbCourseTitle.Text = service.GetCourseTitle("001"); } } } - The resulting WPF form thus far should resemble the figure below.
Thus far, we've put everything in place to complete the WPF training portal form. As a challenge, if time permits, attempt to complete the WPF form by implementing the remaining WCF service methods. Use the GetTopics method to populate the sidebar navigation StackPanel control from the PageLoaded method of the WPF form. Use the GetTopicDetailsByName method to display topic details when a topic is selected in the sidebar navigation or when a topic is searched for.
What's New in the .NET Framework 3.5 Conclusion
In this lesson of the Silverlight tutorial, you
- Explored the Extensible Application Markup Language (XAML).
- Created an alternate user interface for the training portal by using WPF.
- Learned about how WCF has replaced and improved earlier .NET Framework distributed technologies.
- Reviewed documenting a simple business process by using WF.
- Learned about storing user credentials and digital information using Windows CardSpace.
- Briefly familiarized yourself with Language Integrated Query (LINQ).
Footnotes
-
Complete coverage of the Extensible Application Markup Language (XAML) is beyond the scope of this course. To learn more about XAML, visit the XAML developer center at MSDN located at http://msdn2.microsoft.com/en-us/library/ms747122.aspx.
-
For more information on WPF, visit the WPF Developer Center located at http://msdn2.microsoft.com/en-us/netframework/aa663326.aspx.
-
To learn more about Service Oriented Architecture (SOA), visit the Service Oriented Architecture Developer Center located at http://msdn2.microsoft.com/en-us/architecture/aa948857.aspx. Additionally, the standards body that oversees SOA standards is OASIS. Visit the OASIS Web site located at http://www.oasis-open.org/home/index.php. Another location for more information on Web standards, including those that comprise SOA is XML.org located at http://www.xml.org/ or the W3C Web site located at http://www.w3.org/.
-
For more information on the latest Web Service supporting technologies, visit the SOA Developer Center located at http://msdn2.microsoft.com/en-us/architecture/aa948857.aspx.
-
For more information on WCF, visit the WCF Developer Center located at http://msdn2.microsoft.com/en-us/netframework/aa663324.aspx. The WCF home page is located at http://wcf.netfx3.com/.
-
To learn more about Windows Workflow Foundation (WF), visit the Windows Workflow Foundation Developer Center located at http://msdn2.microsoft.com/en-us/netframework/aa663328.aspx and for general information on WF, visit the WF home page located at http://netfx3.com/content/WFHome.aspx.
-
To learn more about CardSpace, visit the CardSpace home page located at http://cardspace.netfx3.com/. The CardSpace Developer Center is located at http://msdn2.microsoft.com/en-us/netframework/aa663320.aspx.
-
To learn more about LINQ, visit the LINQ Developer Center (the LINQ Project) located at http://msdn2.microsoft.com/en-us/netframework/aa904594.aspx.