Windows Mobile Application using C#

Using WPF and C#

Posted in Windows 7 Mobile Application Development | Leave a comment

SSIS Package Programmatically (C#)

Nowadays, ETL technologies are widely used in the software industries.

Posted in SSIS Programming | Leave a comment

SSIS Basics

SQL Server Integration Services

Integrating data into applications or reports is one of the most important, expensive, and exacting activities in building enterprise data warehousing applications. SQL Server Integration Services with the acronym SSIS, is a high performance solution consisting of multiple tools dedicated to this task in MS SQL Server 2005 and is tightly integrated with the .NET Framework tools. SSIS is a product which has evolved over time from MS SQL Server 7.0, where it was called Data Transformation Service (DTS). Although DTS was the forerunner of SSIS, it is not just an improvement, but an entirely new product, which has all the features of the earlier tool, but with a vastly improved development interface, an extensible architecture, enlarged set of tools to address the varied and changing pattern of data in line with the latest developments in data related technology, looping structures, ease of integrating with Analysis Services, better management and performance.

ETL that is, extracting, transforming, and loading takes care of all the activities needed to accomplish data integration. This process consists of extracting data from a source, transforming the extracted data and then loading the modified data to a target server to be used by the application. There are a large number of independent vendors such as Ascential, Informatica, and so on, as well as several database vendors such as Oracle, IBM, and Microsoft in this market.

Enterprise data can be of very different kinds ranging from flat files to data stored in relational databases, with the more recent trend of data being stored in XML data stores. The extraordinary number of database related products, and their historic evolution, makes this task exacting.

SSIS Basics

[ ]

It is not very frequent that extracted data is usable as it is, and may need some kind of transformation. Often, the extracted data has inconsistencies. There are many reasons for inconsistencies, as computer applications may be affected by changes in technology (version changes, new methodologies, etc.), poor or no validation, which are the norms in legacy data software changes (for example, the date and time will be new data types in SQL 2008 to address several issues of awareness of time zones, higher precision needed in financial applications, address compatibility with third party vendors, etc.), changes in the way applications interact with backend data, localization, etc.

Some inconsistencies can be understood quite easily, such as the same information stored in different data formats, while others could be more difficult.

The efficiency and agility of an enterprise would depend on the quality of data in its databases. Hence it is not only necessary to cleanse or scrub data, but also modify it to be internally consistent, and have the correct data quality. Low quality data has been one of the main causes of accidents and frauds in recent times. SSIS has built-in transformations such as fuzzy lookup and fuzzy grouping that can be used to clean, and standardize the data required by the target database. It is very important to standardize data across an enterprise, especially when data is originating from several subdivisions of the enterprise, where different sets of standards may be operative, or where data is consolidated from distributed systems.

Further, the target database may have a different data type from the one that is extracted, and in which case the data has to be modified. Data transformation or modification can range from very simple to very complex. While changing the data type of an extracted data to match the data type of the target database, or changing the case of the extracted data (string) can be simple, combing several columns based on some logic can be complex. What is nice about SSIS is that you can concatenate several simple tasks to arrive at a complex transformation with each link providing a specific change. As an alternative to concatenating transformations or tasks, using the script task with the full force of the .NET framework behind it, it can produce an optimized solution. This is indeed an awesome tool that should be put to good use.

When it comes to loading data to the target database, there is the challenging aspect of loading the data to match the metadata of the target. Many middleware programs, such as Siebel, have their own proprietary database on which they have built their application. In such cases, the incoming data has to be properly matched to the target database schema. Since the middleware uses data from different database products (MS SQL Server, Oracle, etc.), the ETL process has to step up to this task. In fact SSIS is best suited for this task, as a plethora of data access methods are provided. You will see an example of data going between SQL Server and an Oracle database in Chapter 13.

Chapter 1

[ ]

Objects Used in SSIS

SSIS is governed by an object model. Working with SSIS requires a clear understanding of this model. This section describes some important and salient features of the object model. The objects used in building an Integrated Services Package, and the manner in which they work together in the package workflow, are as follows:

Package: This contains all objects in a single unit of work that can be retrieved, executed, or saved at one of several locations.

Control Flow: These elements consist of tasks and containers, and take care of the work flow by preparing data, and arranging for interaction with other processes, but the ordering of tasks is controlled by precedence constraints, which is another important constituent of flow control.

Data Flow: These components consist of a source (adapter) and destination (adapter) for the data, as well as any data transformation that may be needed. The source, destination, and the transformation stages are connected by a sequencing path to maintain the order of flow.

Connection Managers: They stand apart, and facilitate connection to various sources for both extracting (sources) and loading (destination).

Variables: They are used to communicate between various objects. The objects are isolated from one another by design to bestow security, manageability, and maintainability. The variables that support dynamic updating of column values, conditions used in establishing precedence of flow, and reference to record-set destination are some of the examples.

Event Handlers: They run in response to events raised by other objects at run time. Every container has an event handler associated with it that executes at run time.

Log Providers: These are objects, used for logging package run time information.

In addition to this, there are features that help in debugging and diagnosing problems in design. In the following sections, you will learn some of the basic details about each of the above topics. You will also be using them in the various exercises that you will be doing.

• • • • • • • SSIS Basics [ 10 ]

The SSIS Package

The package is an assembly consisting of the several objects described briefly in the previous section. It may also include other packages (nested package). Specifically it can consist of:

Connections

Control Flow Elements

Data Flow Elements

Event Handlers

Variables

Configurations

All elements are not necessary to build a package. In fact, a package can be empty; however, being empty, it will achieve nothing. In order to have functionality, it should have a control flow element, and one or more data flow elements.

A package can be either assembled using the graphical design tools that SSIS provides, or can be built by writing a program. The package built using these methods can be saved to Sql server, an SSIS Package store, or to a file system. The saved package can be retrieved, executed, modified, and saved.

The Control Flow Elements

As mentioned previously, the control flow elements consist of containers and tasks. The following figure shows the various items that you can find in the Toolbox that belongs to Control Flow Items. Tasks do all the work, and the containers provide the tasks with a medium to orchestrate them. Containers may contain other containers as well. The precedence constraints further orders the flow.

The list of tasks in SSIS includes most of the tasks that one would find in its earlier embodiment, the DTS designer. The various tasks can be more generically classified under—data preparation tasks, analytical services related tasks, scripting tasks, SQL Server tasks, maintenance tasks, etc. You will have the opportunity to work with some of these tasks in the various chapters of this book.

• • • • • • Chapter 1 [ 11 ]

Of the available control flow tasks, the following are used in this book :

Send Mail Task

Data Flow Task

Bulk Insert Task

XML Task

Web Service Task

Transfer Database Task

Execute Process Task

File System Task

Execute Package Task

• • • • • • • • • SSIS Basics [ 12 ]

Execute SQL Task

FTP Task

ActiveX Script Task

Script Task

Maintenance Plan Task

Data Flow Components

SSIS provides three types of data flow components— sources, destinations and transformations. Basically, data coming from the source is transformed before being loaded to the destination.

Data Source Components

Since extraction of data is one of the operations needed for ETL, SSIS is equipped with a rich interface for retrieving or merging data from heterogeneous data stores.

The variety of data sources that SSIS can connect to is rather large, using .NET, OLEDB, and ODBC data access methods. While .NET and OLEDB access methods are used for connecting to relational data, ODBC data access is used for legacy data. The ODBC data access method is especially useful, because there are ODBC drivers for practically every kind of database product. In addition to this, SSIS can also leverage data from flat files, XML files, MS Excel spread sheet files, and use MSOLAP provider, to access Analysis Services. The following figure shows various options for data source components available in the Visual Studio 2005 IDE (Standard Edition). It should be mentioned that the DataReader Source, a component of the .NET Data Access Strategy, connects to many of the vendors thorough the optimized .NET provider.

• • • • • Chapter 1 [ 13 ]

Of the available Data Flow Sources, the following are used in this book:

DataReader Source

Excel Source

OLE DB Source

While .NET data providers were developed recently, OLEDB and ODBC have existed for a considerable amount of time and there exists a large number of both Microsoft and non-Microsoft products for establishing connectivity. The following figure shows a list, DataLink.udl Properties, which depends on OLEDB data access providers. It can be seen that there are a large number of providers, all of which can be used for connecting to data sources.

• • • SSIS Basics [ 14 ]

The following data access providers have been used in this book:

.NET Provider\SqlClient Data Provider

OLE DB Provider

Microsoft Jet 4.0 OLE DB Provider

Native OLE DB\Sql Native Client

Native OLEDB\Microsoft OLE DB Provider for SQL Server

Native OLEDB\Microsoft OLE DB Provider for Oracle

In SSIS, a source is typically a data flow component that conduits data from external data sources to other data flow components in a package. The following figure is a schematic representation of a Source obtaining its input from an external source and delivering it to the transformation stage. The error output has two columns describing errors in addition to the columns originating from the source.

Data Transformation

SSIS has built-in transformation that can be used to clean or scrub and standardize the data required by the target database. Standardizing data in an enterprise, especially when data is originating from multiple subdivisions having different standards, is important. Also, with globalization of enterprises, the importance of transformation has risen. The following figure shows the built-in data transformations available in Visual Studio 2005 (Standard Edition).

Posted in SQL Server | Leave a comment

WPF Basic

WINDOWS PRESENTATION FOUNDATION (WPF)

  1. 1. INTRODUCTION

2.   Windows Presentation Foundation Services

    • Integration
    • Vector graphics
    • Declarative programming
    • Easy deployment
    • Document lifecycle

3.    Data Binding

  • Data Binding To A Class
    • Binding data to Combo box from the SQL Server Database
    • Binding data to List View from SQL Server Database
    • General Concepts about Data Binding

  • Binding Mode
  • Controlling Binding Time
  • Data Binding To Another Control

4.       Apply Property Triggers on a Control

5.        Usage of Document Viewer Control

6.        Usage of Menu

7.        Usage of ListBox

8.         Expander Control

  • Expander Properties
  • Usage of Expander Control

9.         Writing Your Own Controls

  • User Controls
  • Custom Controls
    • User Control Development
  • User Control Development(2)

10.       Properties

  • Properties (2)

•      CLR Properties limited in functionality

  • Properties (3)
  • Properties (4)
  • Properties (5)

11. Custom Controls

  • Custom Controls (2)
  • Custom Controls (3)
  • Custom Controls (4)
    • Custom Controls (5)
  • In Custom Control Development

  1. 12. Event Handlers in WPF

  • Event Handlers
  • Binding a Event to a Event Handler
  • Visual Approach
  • Code Approach
  • The Event Handler’s Arguments
  • The Sender
  • The Event
  • · Routed Events
  • Conclusion

  1. 1. INTRODUCTION:

The purpose of this paper is to introduce you to a number of the concepts and features of the Windows Presentation Foundation (WPF, formerly code-named “Avalon”), part of the Windows Vista developer platform, and the foundation for the next generation of Windows applications and content.

WPF enables software developers to achieve a new level of quality in the “User Experience” (UX) aspect of applications. Developers will be able to use WPF to build applications similar to those they construct atop Win32 today… but they will also use WPF to create and display media-rich interactive content, animations, and traditional documents. With the initial release of WPF, developers will be able to write applications that match the functionality and experience that is prevalent for Win32 or DHTML applications and content. Twitch games and high-end scientific visualization/CAD applications, typically the focus of Direct3D developers, are not within the scope for WPF in its first release; however, even in those application domains, there are ways that WPF (particularly its support for documents) can be used to add UI value.

The WPF is not just about graphics. Its coverage of all common forms of presentation—UI, media, vector graphics, and documents—represents a degree of unification that is new to the Windows platform. The “silo” effect found in today’s current disjoint set of client-side technologies has been replaced by a single managed set of classes providing a consistent set of base properties and methods. The result is an unprecedented ability to “mix and match” UI controls, content (document and media), and vector graphics in a seamless manner.

WPF also has features intended to streamline the development process, by reducing the amount of procedural code in application specification, and by enabling a greater and more direct collaboration by members of the development team—UI designers and graphic artists, as well as software engineers. The fundamental technology behind this marriage of design and implementation is a declarative markup language called XAML.By building the WPF atop the cutting-edge Direct3D graphics engine, Microsoft makes it possible for everyday applications to take advantage of the rapidly evolving power of graphics hardware, without the need for direct access to the Direct3D layer. WPF applications will automatically benefit from the optimization capabilities found in Direct3D now and in the future.

  1. 2. Windows Presentation Foundation Services
Base Services XAML, Property System, Input and Eventing, Accessibility
Media Services 2D, 3D, Audio, Video, Text, Imaging, Animation, Effects, Composition Engine
Document Services XPS Documents, Open Packaging Conventions
User Interface Services Application Services, Deployment, Controls, Layout, Data Binding

The design principles behind Windows Presentation Foundation can be categorized as follows:

  • Integration: Windows Presentation Foundation offers a unified API that spans the services identified. Developers today are faced with a myriad choice of disparate technologies and APIs, depending on whether they are targeting 2D graphics (GDI or GDI+), user interface (USER32 or Windows Forms), media (DirectShow), or 3D (Direct3D or OpenGL). Windows Presentation Foundation provides a single model that is orthogonal across all these services and allows seamless integration of content within a single application. You can use the same constructs for animation, data binding and styling, regardless of whether you are targeting 2D, 3D or text content.
  • Vector graphics. As described in the introduction, Windows Presentation Foundation takes full advantage of the powerful Graphical Processing Units that are part of modern PC systems. At its heart, the composition engine is vector-based, allowing for scaling of all output to match the resolution of a specific machine. The rendering architecture uses Direct3D for all output: on video cards that implement DirectX 7 or later in hardware, Windows Presentation Foundation renders output using the GPU wherever possible. In situations where hardware rendering cannot be used, software rendering is available as a fallback. Lastly, a floating-point logical pixel system and 32-bit ARGB color support provide a rich high-fidelity experience that anticipates future technology needs, such as high-DPI displays.
  • Declarative programming. Windows Presentation Foundation introduces XAML (extensible Application Markup Language), an XML-based language for instantiating and populating nested object hierarchies. While XAML isn’t exclusively tied to Windows Presentation Foundation, it is inherently suitable for tasks such as UI definition and construction. The design of XAML allows applications to parse and manipulate UI logic at run-time for dynamic workflow scenarios. Importantly, the XAML / code-behind model embodied in Windows Presentation Foundation allows designers and developers to work collaboratively on client application design and development, using tools such as Expression “Sparkle” as well as third-party specialist tools including ZAM 3D and Mobiform Aurora.
  • Easy deployment. With support for both standalone applications and Web-browser applications, Windows Presentation Foundation offers the best of both deployment models. Web-browser applications run from within Internet Explorer, either occupying the entire window or within an inline frame. They offer the ease of deployment for which Web applications are famed, as well as operating within a partial trust sandbox that protects the client machine against malicious applications. Yet they can still take advantage of the local client hardware and use 3D and media services for the richest Web experience available today. On the other hand, standalone applications are locally installed via Click Once or MSI technologies and offer full access to the underlying platform.
  • Document lifecycle. Windows Presentation Foundation introduces a new set of document and print technologies. Applications that need to persist data to a local store can use the Open Packaging Conventions, a ZIP-based packaging convention shared with Office 12 that supports core properties and custom metadata, digital signatures and rights management functionality. For applications that want to share documents for collaboration across multiple machines, even without the application installed, the XML Paper Specification allows visuals to be fixed in a printable, portable format.

  1. 3. Data Binding

The document specifies how the data binding and event handling can be done with WPF controls.

  • Data Binding To A Class
  • For a simple Data Binding to a class all we need to do is create a class in the .cs file like this.

Namespace binding

{

Class Person

{

String Name;

String name

{

get

{

return Name;

}

set

{

Name=value;

}

}

Public void Person ()

{}

Public void Person (string name)

{

Name=name;

}

}

}

  • Then in the XAML part the first thing we have to do is refer the XAML page to a local namespace like this

Xmlns: local=”clr-namespace: binding”

  • Then we have to declare the resources instantiate the class in Windows   resources

<Window. Resources>

<local: Person x: Key=”xyz” Name=”Gill Cleeren” Age=”27″/>

</Window. Resources>

  • Then create a grid with the Data Context property set to {Static Resources   xyz} which is nothing but the x; key
  • Then any control that you pull in, apply Data binding to appropriate property as

{Binding Path=Name} etc…..

You are done with binding it to a class!!!

  • Binding data to Combo box from the SQL Server Database :

  • Write the Code to connect to Database and the corresponding Data Access commands.(Similarly U did it for .Net 2.0)
  • Add only one Extra line i.e. Assign Data Context to any Collection object.

I.e. Data Context=Patient List.

  • Data Context allows Data to be bound in XMAL.
  • In XAML, Write the below code

<Window.Resources>

<DataTemplate x:Key=”DataKey”>

<TextBlock Text=”{Binding Path=Column_Name}” FontWeight=”Bold” />

</DataTemplate>

</Window.Resources>

Column_Name  === Column to be bound to the Combobox

x:Key              ===  Unique Key name for DataTemplate(Any name U can give)

  • In XAML, for ComboBox control, assign the ItemTemplate with the Resource Key tag and Item Source as Binding.

<ComboBox ItemTemplate =”{StaticResource ListTemplate}”   Name=”comboBox1″ ItemsSource=”{Binding}”></ComboBox>

  • Binding data to List View from SQL Server Database :
  • Write the Code to connect to Database and the corresponding Data Access    commands.(Similar U did it for .Net 2.0)
  • Set the Items Source property of the List view as the Collection object.

i.e. ListView1. Items Source=Patient List;

We can’t set Data Set as the ItemsSource for List View.

  • For showing data in Listview,write the below code,

<ListView Name=”lsvPatient”>

<ListView.View>

<GridView AllowsColumnReorder=”True”>

<GridViewColumn  DisplayMemberBinding=”{Binding Path=     Column_Name}”  Header=”Patient Name” Width=”100″/>

</GridView>

</ListView.View>

</ListView>

  • General Concepts about Data Binding :

Binding Mode:

By Default it will be Two Way. Various Binding options are given below.

Binding Mode Description
Two-Way Moves changes, from either the bound control or the source of the binding, to one other in a bi-directional way. (This is the default mode.)
OneWay Moves changes only from the source to the control. As changes occur in the source, the bound control’s data is changed.
OneTime Data is bound only at startup, and changes to the source are ignored once the control is filled with data the first time.

You can specify the mode by simply including the mode in the markup, as follows.

i.e. {Binding Element Name, Path=Text, Mode=OneWay}

·         Controlling Binding Time:

In addition to the Mode, you can also specify when the binding pushes the changes, by using the UpdateSourceTrigger. You can specify that the binding make the change only at specified times, by specifying the UpdateSourceTrigger type.

The UpdateSourceTrigger property specifies when to update the source with changes. This is valid only with Mode=TwoWay bindings (which is the default). The valid values for the UpdateSourceTrigger are shown in Table 2.

UpdateSourceTrigger Description
Explicit The source is updated only by explicitly calling the BindingExpression.UpdateSource method.
LostFocus The source is updated as the bound control loses focus.
PropertyChanged Changes are updated to the source every time the property changes. This is the default behavior.
  • Data Binding To Another Control

Suppose you wish to bind a label to a text box, meaning whatever changes happens in the textboxes should be reflected real time in the label, then follow the steps

  • First create a text box, give it a unique name.
  • Then create a label with the content property set to {Binding Element, path=Text}

4.   Apply Property Triggers on a Control

Property triggers are triggers that come into picture when we are on watch for some property like IsMouseOver etc being true

  • So what we need to understand first is that the we need to set a common style to which one or more controls would refert to using style={Static Resources (style id Ex:normal)}

<Style x: Key=”normal”>

<Setter Property=”Control.FontSize” Value=”12″ />

<Setter Property=”Control.HorizontalAlignment” Value=”Center” />

<Setter Property=”Control. Margin” Value=”2″ />

</Style>

  • Then we need the controls to refer to this style so we write

<Button style= {Static Resource normal}/>

Now whatever is specified in the style will be applicable to that particular control that refers to it

  • Now we need  to  set  a  trigger  on  some  particular  property, Example  if  we need to set an IsMouseOver property trigger on a button then we need to write

<Style. Triggers>

<Trigger Property=”Control.IsMouseOver” Value=”true”>

<Setter Property=”Control.FontStyle” Value=”Italic” />

<Setter Property=”Control.Foreground” Value=”Green” />

</Trigger>

<Trigger Property=”Button.IsPressed” Value=”true”>

<Setter Property=”Control.Foreground” Value=”Red” />

</Trigger>

</Style.Triggers>

but  this  entire  thing  should  be  in the  resources  tag  so  the  completed  thing  becomes

<Grid. Resources>

<Style x: Key=”normal”>

<Setter Property=”Control.FontSize” Value=”12″ />

<Setter Property=”Control.HorizontalAlignment” Value=”Center” />

<Setter Property=”Control. Margin” Value=”2″ />

<Style.Triggers>

<Trigger Property=”Control.IsMouseOver” Value=”true”>

<Setter Property=”Control.FontStyle” Value=”Italic” />

<Setter Property=”Control.Foreground” Value=”Green” />

</Trigger>

<Trigger Property=”Button.IsPressed” Value=”true”>

<Setter Property=”Control.Foreground” Value=”Red” />

</Trigger>

</Style.Triggers>

</Style>

</Grid. Resources>

5.   Usage of Document Viewer Control

  • Ø How to: Data-Bind Document Viewer’s Zoom Property to a Textbox
    • This example shows how to bind the Zoom property of a Document Viewer to a text control, using Extensible Application Markup Language (XAML).
  • Ø Given below the pseudo code for the same.

<Grid>

<Grid.RowDefinitions>

<RowDefinition Height=”*” />

<RowDefinition Height=”*” />

</Grid.RowDefinitions>

<DocumentViewer Name=”dvZoomSource” Grid.Row=”0″ />

<TextBox Grid.Row=”1″

FontSize=”{Binding ElementName=dvZoomSource, Path=Zoom}”    Text=”{Binding ElementName=dvZoomSource, Path=Zoom,Mode=OneWay}”/>

<Image Source=”C:\Program Files\Movie Maker\Shared\Sample1.jpg”

Height=”{Binding ElementName=dvZoomSource, Path=Zoom}”   Width=”{Binding ElementName=dvZoomSource, Path=Zoom}”/>

</Grid>

  • In this example, any changes to the value of Zoom are immediately reflected in the data-bound Textbox.
  • This example uses a “simple” binding declaration to bind the value of Zoom to the Text property of a Textbox.
  • The ElementID clause in the binding declaration refers to the Name of the source element, which in this case is “dvZoomSource”.
  • The Path clause in the binding declaration names the source property, which in this case is Zooming.
  • The Mode clause in the binding declaration specifies that this is a one-way data binding; updates to the source value of Zoom are reflected in the target Textbox, but changes to the contents of the Textbox do not change the value of Zoom.

6.   Usage of Menu

This example shows how to create MENU controls. The example illustrates Menu controls with submenus and Menu Item elements with ToolTip controls. The example also shows how to use the Is Checkable property to make Menu Item controls that can be checked.

<Grid>

<Menu Width=”30″ Margin=”10, 10, 5, 5″ HorizontalAlignment=”Left”        Background=”White”>

<MenuItem Header=”_File”>

<MenuItem Header=”_New” IsCheckable=”true”/>

<MenuItem Header=”_Open” IsCheckable=”true”/>

<MenuItem Header=”_Close” IsCheckable=”true”/>

<Separator/>

<MenuItem Header=”Menu with Submenu”>

<MenuItem Header=”_submenuitem1″ IsCheckable=”true”/>

<MenuItem Header=”_submenuitem2″ IsCheckable=”true”>

<MenuItem Header=”_submenuitem2.1″ IsCheckable=”true”/>

</MenuItem>

</MenuItem>

<Separator/>

<MenuItem Header=”_Menu item with ToolTip”>

<MenuItem.ToolTip>

<ToolTip>ToolTip Information.</ToolTip>

</MenuItem.ToolTip>

</MenuItem>

</MenuItem>

</Menu>

</Grid>

7.   Usage of ListBox

  • Include a class Mystrings.cs. This is used to populate the List Box

public class MyStrings : List<String>

{

public MyStrings()

{

this.Add(“Hello”);

this.Add(“Goodbye”);

this.Add(“Heya”);

this.Add(“Cya”);

}

}

  • The below code specifies how the binding is done by using   ObjectDataProvider.

This code should be included in the xaml page.

<Window.Resources>

<ObjectDataProvider x:Key=”MyStringData” ObjectType=”{x:Type    local:MyStrings}” />

</Window.Resources>

<StackPanel>

<TextBlock HorizontalAlignment=”Center” FontWeight=”Bold”>

Simple Source Example </TextBlock>

<ListBox Name=”theListBox” Width=”200″ Height=”300″

ItemsSource=”{Binding Source={StaticResource MyStringData}}”/>

</StackPanel>

</Window>

8.      Expander Control:

  • Ø If the content of the expanded window is too large for the window, you can wrap the content of the Expander in a Scroll Viewer control to provide scrollable content. Scrolling capability is not automatically provided by the Expander control.
  • Ø For an Expander to work correctly, do not specify a Height on the Expander control when the Expand Direction property is set to down or up. Similarly, do not specify a Width on the Expander control when the Expand Direction property is set to Left or Right. When you set a size on the Expander control in the direction that the expanded content is displayed, the area that is defined by the size parameter is displayed with a border around it. This area displays even when the window is collapsed. To set the size of the expanded window, set size dimensions on the content of the Expander control or the Scroll Viewer that encloses the content.
  • Ø When an Expander control is the last element in a Dock Panel, the Expander is sized to fill the remaining area of the Dock Panel. To prevent this, set the LastChildFill property on the Dock Panel to false, or make sure that the Expander is not the last element in a Dock Panel.
  • Ø The alignment of Expander content can be defined by setting the Horizontal Content Alignment and Vertical Content Alignment properties on the control. These properties are applied to the header and to the contents of the expanded window.

The following example shows how to create an expander control in Add   Patient:

<Expander

HorizontalAlignment=”Left” Header=”C

ExpandDirection=”Down” ToolTip=”Patient Info “/>

  • Expander Properties:

  • Expand Direction Property:

Gets or sets the direction in which the Expander content window opens.

The following example shows how to set the Expand Direction property.

<Expander Name=”myExpander1” Expand Direction=”up” Header =” Patient Info” Content=”expanderContent”/>

  • Is Expanded Property:

Gets or sets whether the Expander content window is visible. The following   example shows how to set Is Expand property.

<Expander Name=”myExpander1” Is Expanded=”True” Header =”Patient Info”   Content=”expanderContent”/>

  • Usage of Expander Control

An Expander allows a user to view a header and expand that header to see   further details, or to collapse a section up to a header.

The following example shows how to create an Expander. The example   uses a Bullet Decorator control, which contains an image and text, in order to define the Header. A Scroll Viewer control provides a method for scrolling the expanded content.

Note that the example sets the Height property on the Scroll Viewer instead of on the content. If the Height is set on the content, the Scroll Viewer does not work correctly because it does not know about the size limitation. The Width property is set on the Expander control and this setting applies to the Header and the expanded content.

<Grid>

<Expander Width=”200″ HorizontalContentAlignment=”Stretch”>

<Expander.Header>

<BulletDecorator>

<BulletDecorator.Bullet>

<Image Width=”50″ Source=”C:\Program Files\Movie      Maker\Shared\Sample1.jpg”/>

</BulletDecorator.Bullet>

<TextBlock Margin=”20,0,0,0″>My Expander</TextBlock>

</BulletDecorator>

</Expander.Header>

<Expander.Content >

<ScrollViewer Height=”50″>

<TextBlock TextWrapping=”Wrap”>

</TextBlock>

</ScrollViewer>

</Expander.Content>

</Expander>

</Grid>

9.   Writing Your Own Controls

• Two ways

  • User Controls
  • Simple development model (similar to application dev)
  • Need to compose control of only existing components
  • Do not need customization (e.g. templates and styles)
  • Custom Controls
    • Want full control over the look and feel of new control
    • Need special rendering support
    • Want to support being a container for other controls
    • User Control Development

• Typical WPF-like Development Experience

  • Write XAML that defines the control
  • Similar to WinForms and ASP.NET User Controls
  • XAML + CodeBehind

<UserControl x: Class=”CustomWPF.MyUserControl”

xmlns=”…” xmlns:x=”…”>

<Grid>

<Ellipse Width=”50″ Height=”50″ />

<Path Fill=”Black” Data=”M18,12 18,38 35,25″/>

</Grid>

</UserControl>

Public partial class MyUserControl : UserControl

{

Public MyUserControl ()

{

PlayIcon.Opacity = .5;

}

}

  • User Control Development (2)

• Use Controls by importing the CLR Namespace

  • You import the entire namespace, not individual classes
  • Can use new control in XAML
  • Specify the xml namespace and the type name
  • If control is in another assembly, you specify the name

<Window x:xmlns=”…” xmlns:x=”…”

xmlns:cust=”clr-namespace:CustomWPF”>

<cust:MyUserControl />

</Window>

<Window x:Class=”Tester.MainWindow” xmlns=”…” xmlns: x=”…”

xmlns:cust=”clr-namespace:CustomWPF, MyAssembly”>

<cust:MyUserControl />

</Window>

10.  Properties

• Adding Properties is simple

  • CLR Properties work in XAML

Public partial class MyUserControl : UserControl

{

// …

Brush _iconColor = Brushes.Black;

Public Brush IconColor

{

get { return _iconColor;

}

set {

_iconColor = value;

PlayIcon.Fill = value;

PauseIcon.Fill = value;

}  }

}

  • Properties (2)

• CLR Properties limited in functionality

  • Simple assignment work
  • Only works with simple code or XAML assignment

<StackPanel>

<Rectangle Fill=”Red” />

<TextBlock>User Control:</TextBlock>

<!– Simple Assignment Works –>

<cust:MyUserControl IconColor=”Blue” />

<!– Data Binding Does Not –>

<cust:MyUserControl IconColor=”{Binding ElementName=aRect,         Path=Fill}”      />

</StackPanel>

  • Properties (3)

• DependencyProperties

  • Allows values to be set without using Reflection
  • Objects register their properties
  • Support rich use of all WPF’s functionality
  • Data binding
  • Animation
  • Triggers
  • Properties (4)

• DependencyProperties

  • Registration creates the runtime metadata
  • Optionally define change notification and default value

Public static readonly DependencyProperty IconColorProperty =

DependencyProperty.Register(“IconColor”, // Property Name

typeof (Brush),

// Type of the Property

Typeof (PlayButton));

// Type of the Owner

// of the Property

  • Properties (5)

• DependencyProperties

  • Storage handled in WPF stack, not in your class

Public Brush IconColor

{

get { return (Brush)GetValue(IconColorProperty);

}

set { SetValue(IconColorProperty, value);

}

}

11. Custom Controls

  • Unlike User Controls
  • No base class requirements
  • Pay for Play choices of features
  • You decide how much or little you want
  • Pay == Labor involved in development, not runtime
  • Support for
  • Styling
  • Templates
  • Theming
  • Custom Controls (2)
  • In Visual Studio creating a new Custom Control
  • Creates a class that derives from Control
  • Builds a default theme template
  • Custom Controls (3)

• New control can derive from any of the classes

public class MyNewControl : Control {

// …

}

public class MyNewControl : FrameworkElement {

// …

}

public class MyNewControl : Button {

// …

}

  • Custom Controls (4)
  • Which class is right?
  • Higher
  • Less Built-in Functionality
  • Lower
  • More Built-in Functionality
  • Less Control
  • Custom Controls (3)

• Also creates (or adds to generic.xaml)

<!– Generic.xaml –>

<ResourceDictionary xmlns=”…” xmlns:x=”…” xmlns:local=”clr-           namespace:CustomWPF”>

<Style TargetType=”{x:Type local:MyNewControl}”>

<Setter Property=”Template”>

<Setter.Value>

<ControlTemplate TargetType=”{x:Type local:MyNewControl}”>

<Border Background=”{TemplateBinding Background}”

BorderBrush=”{TemplateBinding BorderBrush}”

BorderThickness=”{TemplateBinding BorderThickness}”>

</Border>

</ControlTemplate>

</Setter.Value>

</Setter>

</Style>

</ResourceDictionary>

  • Custom Controls (4)

• Themes allow you to create designs that fit the OS

• Theme files are resource dictionaries

  • Each is for different OS theme
  • Generic.xaml: The fallback theme file.
  • Luna.normalcolor.xaml: Windows XP Blue Theme
  • Luna.homestead.xaml: Windows XP Olive Theme
  • Luna.metalic.xaml: Windows XP Silver Theme
  • Aero.normalcolor.xaml: Windows Vista Theme
  • Classic.xaml: Windows Classic Theme
  • Custom Controls (5)
  • In Custom Control Development:
  • Custom Control Development is different
  • In WPF Development:
  • You are working with a XAML file that describes the UI
  • You can access the hierarchy as properties
  • The template should do as much of the behavior as possible
  • Events should do the rest
  • The more functionality you put in the code
  • The Less users can override that behavior

For more details refer  www.wildermuthconsulting.com,www.adoguy.com

12.Event Handlers in WPF

Whenever you click on a button or type some text into a form in your browser, you are using events. More than likely, you never think about this, because it just works. You don’t worry about how the mouse click is recognized, how your application knows which key was pressed, etc. The reason is that many of these lower level details are handled by your graphics framework itself. Even as a developer, your work with events is largely on the surface of what really goes on behind the scenes, but there is plenty of surface area to cover though! So, in this tutorial, I will explain how to use event handlers in the Windows Presentation Foundation (WPF).

  • Event Handlers
    Don’t let the introduction scare you though. Event handling is extremely common, and if you’ve ever made your application do something when a button was clicked, you already know most of what is to know about using event handlers.

An event handler is simply a method (function) that receives the input from a device such as a mouse or keyboard and does something with it. Like its name implies, it handles events – more specifically, input events. For example, the following code shows an event handler called ButtonOKClicked that is fired when a button is clicked:

Private Void ButtonOKClicked (object sender, RoutedEventArgs e)

{

This. Close ();

}

There are really two things that need to be done when using events:

  1. You need to bind an event handler to a Control (button, text field, menu, etc.).
  2. You need to specify an event handler that receives and reacts to an event.

In this article, I will go over event handlers and how to use them with events. I will provide code examples to reinforce what I will be explaining, but this is more of an article explaining event handlers as opposed to a tutorial where you create a small application using event handlers.

  • Binding a Event to a Event Handler
    Let’s first look at how to bind an event to an event handler. There are two ways of doing this. You can (1) either use an IDE such as Expression Blend or Visual Studio’s WPF Designer (see blog post), or (2) you can bind a control to an event using code itself. The end result is the same, so let’s look at both the visual as well as code-based approaches.
  • Visual Approach
    The visual approach is what most of you will use because there are great tools for designing GUIs using WPF. I won’t go into the details of either Visual Studio or Blend in this tutorial, but if you have, for example, a button, you can view a list of the events and assign an event handler next to the event you wish to fire:

[ assigning a click event to an event handler called ButtonOkClicked ]

In the visual view, you simply find the event that you wish to bind your control to such as Click, and specify the name your event handler will take. When you press Enter you will be taken to the code view where you can see the event handler displayed with the name you provided.

Trivia – Look at the XAML!

If you look at the XAML for the above event-binding, you will see both the Click event as well as our event handler ButtonOkClicked appear:

<Button HorizontalAlignment=”Left” Margin=”130, 92, 0, 86” x: Name=”btnOK” Width=”80” Content=”OK” Click=”ButtonOkClicked”/>

It is the above XAML definition that tells your final application to route all Click events attached to the button to the ButtonOkClicked event handler. A program like Blend or Visual Studio’s Designer serves primarily to provide a nice interface for creating the XAML snippet I posted above.

On the next page, let’s take a look at the code based approach.

In the previous page you got a brief overview of what event handlers are and how to add them usual a visual editor like Visual Studio or Expression Blend.

  • Code Approach
    while the visual approach I outlined above will be the preferred way of binding events to an event handler, you can just as easily use code to accomplish the same thing. You may be wondering why you would choose a less visual approach. One good reason is, if you are dynamically creating a control, the only way to attach events would be through code. I provide an example of that a few paragraphs down, so you can see what I mean.

Let’s say we have a button called btnOK, and our goal is to attach an event to it using just code. All you have to do is pick the appropriate event you wish to use and link it to a new RoutedEventHandler with the name of your event handler:

btnOK.Click += new RoutedEventHandler (ButtonOkClicked);

If you use Visual Studio for writing the code, the inline auto-complete is very handy:

[ auto-complete is quite helpful in times like this ]

Right now you may be wondering how anybody could know to use RoutedEventHandler without the help of AutoComplete. If you are just getting started with WPF, it may be difficult to know that, but just remember that you need to bind an event to an event handler. Later in this article and in greater detail in subsequent articles, I will explain these in more detail.

Like I hinted at in the previous paragraph, one disadvantage with the code approach is that if you want to use events or event handlers beyond the common ones that you are familiar with, you will have to spend some extra time combing through the displayed methods and properties for your object to find the appropriate event:

[ browsing through methods and properties ]

In the visual approach, all events are grouped together in one pane, but in the larger scheme of things, it is just a minor detail that you should be aware of.


Getting the event bound to an event handler is just one part of what you need to. The second part is to actually create an event handler. Before I go into greater detail, let’s first look closely at the event hander I show below:

private void ButtonOkClicked (object sender, RoutedEventArgs e)

{ This. Close (); }

Notice that the event hander takes in two arguments from the event that fired – the sender and the event. Basically, the sender is the control you clicked on, and the event (e) is the particular input that triggered the event handler such as a key press or a mouse click.

If you took the visual approach, the above event handler would automatically be created for you. If you used the code approach, you would need to define an event handler following a similar structure with the two arguments. Let’s look in greater detail at what the two arguments actually do on the next few pages.

  • The Event Handler’s Arguments
    Like I mentioned earlier, the event handler takes in two arguments – a sender and an event. In many cases, you really don’t have to know much about them. For example, in the code from earlier reproduced below, I am not even using either sender or e in my method’s body:

private void ButtonOkClicked (object sender, RoutedEventArgs e)

{ this. Close (); }

But, you will run into cases where you want to do more than just have one control bound to an event handler. When dealing with many interactive controls created using code, you’ll find that knowing more about the sender and event can be helpful.

The Sender
If you want know exactly which control triggered the event, you will need to modify the sender object. The problem, though, is that your controls are of types like Button, Text Field, Checkbox, etc. The argument is of type object. Unfortunately, you cannot simply type in Button foo = sender.

What you need to do is typecast the object into the type of the control that called it. The following code shows an example of how I access the sender Button:

private void ButtonOkClicked(object sender, RoutedEventArgs e)

{ Button clickedButton = (Button) sender;

MessageBox.Show (clickedButton.Name); }

Notice that I create a new Button object called clickedButton that casts my sender object as a Button also. This allows me to access my button’s properties just as if I were manipulating my button directly by name.

When casting, you should make sure that you are actually allowed to cast to that object. For example, I cannot cast my sender object as Checkbox even though both it and a Button can be based on an object. Despite us not knowing what the object type for sender really refers to, internally, WPF has a good idea: P

If you do try to cast something to a type that it cannot be cast to, you will receive an InvalidCastException:

[ I receive an InvalidCastException when tricking a checkbox to behave like a button ]

If you are in a situation where you don’t know what the type of the control you clicked on is, you can use the GetType property to find out:

private void ButtonOkClicked (object sender, RoutedEventArgs e)

{ MessageBox.Show (sender.GetType().Name); }

Now that you have a good idea of how to access the sending object, let me touch back on a topic that I left incomplete earlier. Earlier, I mentioned that the above approach is just as good as if I were “manipulating my button directly by name.” The question is, why am I not directly manipulating the button?

The reason is that, when you have many controls such as an array of Buttons that map to the same event handler, you cannot easily explicitly access each button individually. For example, check out the following mini-application that draws many styled buttons and allows you to interact with them individually:

[ a small demo that shows why code-based event handling is often needed ]

Click here to run the WPF demo and view/download the source code for the above application.

In the above application, when you click on a button, the button’s name is displayed a as a message box. Because I am creating each button dynamically using code, I have to cast the sender object in my event handler so that I can know which button has been rolled over.

Note – Determining the Object without Using Sender

In this section, I explained how to use the sender object to determine what object is passed in. You are not limited to using just the sender though. You can actually use your event e itself to cast the source of the event into what you want:

Button clickedButton = e.Source as Button;

The reason I did not explain the above code in this section because it logically makes more sense to have two arguments standing for two different things – the object and the event

We are almost done with this article! On the next page page I will wrap things up and discuss what the event argument can help you to do.

  • The Event
    The second argument passed to our event handler is the event itself. The event really depends on when you want your control to fire a signal to your event handler. A generic event is what you see in my code called RoutedEventArgs for a button’s Click event:

private void ButtonOkClicked(object sender, RoutedEventArgs e)

{ this.Close(); }

You will get more specialized event arguments depending on what you are trying to do, and those arguments provide you with greater flexibility to deal with these events. Let’s say you have a textbox, and each time you type a character, you want to do something. For this scenario, you are looking at a very particular type of event argument – one that takes key presses into account.

Let’s give our text box the name txtBoxMain, and let’s bind a KeyDown event to an event handler called KeyCount. Visually in Expression Blend, you would simply enter your KeyCount event handler and press Enter:

[Again, you can use a visual approach to bind an event to an event handler]

In code, you would do the following:

txtBoxMain.KeyDown += new KeyEventHandler(KeyCount);

Regardless of which approach (visual or code) that you took, your event handler would look like the following:

private void KeyCount (object sender, KeyEventArgs e)

{ }

Notice that my event argument is now KeyEventArgs. The KeyEventArgs class contains a lot of useful methods that I can use to do more with my event than just recognize that it happened. For example, the following code shows me displaying the letter/name of the key pressed in a message box:

private void KeyCount (object sender, KeyEventArgs e)

{ MessageBox.Show (“Key pressed is: ” + e.Key.ToString()); }

The following is the image you see when you run the above code and press the letter k:

[by using Key I can determine which key was pressed ]

While this example dealt with keyboard arguments, you can bind similar events to their respective event handlers for the mouse, the stylus, etc. Depending on which event handler variation you use, the number of properties you can access will vary. The differences in code among the various actions are too minor to cover in detail in this article. It would also be a bit too boring!

To give you a flavor of the extent of the variation, your argument e’s type may be MouseEventArgs for a mouse related event, and you may not have a Key structure from which to determine key presses, but you will have access to the Left and Right mouse buttons. You can find similar yet distinct variations among the other input methods.

  • Routed Events
    Raising and handling events with the WPF is based on the new XAML markup structures, and how events are routed through a tree of elements. When a XAML page contains nested controls, there are interactive complexities that never before existed in the typical .NET UI environment. ‘Nested’ controls create what is known as a Logical Tree and a Visual Tree. Application developers have been required in times past to ‘Walk-the-Tree’ by raising events and/or calling methods for each logical ‘node’ within a nested hierarchy. Events in the WPF are called Routed because there is a brand new chronological process by which to handle these events. This ordered, or routed, list of events will fire in a controlled fashion, providing full view of event the most complex Visual Trees. With the advent of Routed Events in the WPF, the complications involved with capturing a series of hierarchical events are encapsulated and simplified. Routed Events are a pipeline of event handlers that are automatically fired for a control when any of its nested controls’ events fire. This means that it performs as a self-aware component, knowing when its members are being interacted with, and providing handler logic to respond to user or system related interactions.

    A FrameworkElement could possible contain other sibling and child elements, which forms a tree of elements. In the WPF, the parent element can provide information to child elements, providing usage, customization, and visibility to the potentially smaller, nested objects. “Control Composition” is a term used to describe the creation or design concepts used when creating controls and providing thought to the handling of information within the tree. It leads developers to creating better structure for controls to control and direct the logical flow of events for the tree and its members.
    There are 3 types of routed events:
    * Tunneling
    * Bubbling
    * Direct

    A Bubbling event is the first place we will start, as it provides event handling from the originating element of a Visual Tree to the root of the tree. Tunneling events, on the other hand, fire in the opposite direction and are used to hook into the pre-condition of the controls within the visual tree from the top of the visual tree down. Tunneling and Bubbling event models assist in the complicated logic associated to events raised from / by controls within other controls. Developers can hook into an action before or after it occurs in context to its parent and child controls.

  • Conclusion
    As you can see, event handling can be as easy or as complicated depending on what you are trying to accomplish. Actually, complicated may not be the right word, because one you become familiar with the syntax and when to use some of these tricks, many things become easier.

The goal of this article and other articles on this site (and I’m sure others) is to give you a brief overview of the common uses of a particular use of technology and cover in greater detail the subtle, not-so-common uses that cause endless frustration and sleepless nights. At least that is how I justify having the trivial Note boxes and providing similar sets of code for the same task haha.

Posted in Windows Application | Leave a comment

Update App pool settings in C#

One of the most important thing is to update the IIS application pool settings while deploying an application.

The following code helps to update the application pool settings.

#region Using Statements
using System;
using System.DirectoryServices;
#endregion

namespace AppPoolSetter
{
/// <summary>
/// This class updates the settings of applicatin pool.
/// </summary>
static class Program
{
#region Methods

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
//Call the method for difference application pools.
SetPoolSettings(“poolname1″);
}

private static void SetPoolSettings(string poolName)
{
//Creates an instance of DirectoryEntry using specified application pool path.
DirectoryEntry appPool = new DirectoryEntry(“IIS://localhost/W3SVC/AppPools/” + poolName + “”);

if (appPool != null)
{
try
{
//Updates the properties in application pool
appPool.InvokeSet(“PeriodicRestartTime”, 0);
appPool.InvokeSet(“IdleTimeout”, 90);
appPool.InvokeSet(“AppPoolRecycleTime”, false);
appPool.CommitChanges();

//Log entry for changed settings.
System.Diagnostics.EventLog.WriteEntry(“AppPoolSetter “, “Changed settings for app pool ” + poolName);

}
catch (Exception ex)
{
//log entry for failed settings.
System.Diagnostics.EventLog.WriteEntry(“AppPoolSetter “, “Failed settings for app pool” + poolName + ” Error stack:  ” + ex.Message);
}
}
}

#endregion
}
}

Posted in IIS 6.0 | Leave a comment

WCF Security Implementation

Posted in Distributed Technology | Leave a comment

WCF Security Part 2

Introducing Windows Azure

Implementing Security in a Windows Domain

In the following exercises, you will see how to use transport and message level security in some common scenarios that can arise within a single organization. Because it is easier to demonstrate and explain things this way around, you will start by learning how to implement message confidentiality by encrypting messages. You will then see how to authenticate users running in a Windows environment, and finally, how to use the Windows Token Role provider to authorize access to operations.

Protecting a TCP Service at the Message Level

Message encryption is a very common requirement of most distributed systems; so much so that the majority of the standard bindings available in the WCF library encrypt messages by default. For example, the NetTcpBinding binding automatically encrypts data at the transport level if you have configured SSL over TCP. The NetTcpBinding binding also supports encryption at the message level, giving you a greater degree of control over the encryption algorithm used and without requiring you to configure SSL. You will use message level security to implement message encryption in the first exercise.

Enable message level encryption for the NetTcpBinding binding for the WCF service

  1. Using Visual Studio 2005, open the solution file  ProductsService.sln located in the Microsoft Press\WCF Step By Step\Chapter 4\ProductsService folder under your \My Documents folder.

This solution contains three projects: the ProductsService service, the ProductsService-Host application, and the ProductsClient. These projects are configured to catch and handle SOAP faults, as described in Chapter 3, “Making Applications and Services Robust.”

  1. Expand the ProductsServiceHost project in Solution Explorer, right-click the  App.config file, and then click Edit WCF Configuration.
  2. In the WCF Service Configuration Editor, right-click the Bindings folder and then click New Binding Configuration.
  3. In the Create a New Binding dialog box, select the netTcpBinding binding type and then click OK.

The WCF Service Configuration Editor generates a binding configuration with the default settings for the NetTcpBinding binding.

  1. In the right pane of the WCF Service Configuration Editor, change the Name property of the binding to ProductsServiceTcpBindingConfig.
  2. Click the Security tab.
  3. Change the Mode property to Message. Change the AlgorithmSuite property to Basic128. Leave the MessageClientCredentialType property set to Windows.

These settings cause the binding to use message level security. Users will be expected to provide a valid Windows username and password, and all messages will be encrypted by using the Advanced Encryption Standard (AES) 128-bit algorithm. This is a widely used algorithm that is relatively quick to perform but should provide sufficient privacy for messages inside an organization (if you are sending messages across a public wide area network such as the Internet, you might prefer to use Basic256, which is the default value).

Note If you set the Mode to None, then the binding will not encrypt data and any settings you specify for transport or message level security will be ignored. The Transport mode selects transport level security (SSL) rather than message level security, and the TransportWithMessageCredential mode uses message level security to provide the identity of the user for authorization purposes, while performing encryption at the transport level. Transport level encryption is usually more efficient than message level encryption, although it requires more configuration on the part of the administrator.
  1. In the left pane of the WCF Service Configuration Editor, expand the Products.ProductsServiceImpl service in the Services folder, expand the Endpoints folder, and then click the ProductsServiceTcpBinding endpoint.
  2. In the right pane, set the BindingConfiguration property to ProductsServiceTcpBindingConfig.

This action associates the binding configuration with the binding. All messages sent by using the ProductsServiceTcpBinding will use message level security and will be encrypted.

  1. Save the configuration, and then exit the WCF Service Configuration Editor.
  2. In Visual Studio 2005, open the file  App.config in the ProductsServiceHost project. In the <system.serviceModel> section, you should see the new binding configuration, and the reference to this configuration in the ProductsServiceTcpBinding endpoint, as follows:

12.…

13.<system.serviceModel>

14. <bindings>

  1. 15. <netTcpBinding>
  2. 16. <binding name=”ProductsServiceTcpBindingConfig”>
  3. 17. <security mode=”Message”>
  4. 18. <message algorithmSuite=”Basic128″ />
  5. 19. </security>
  6. 20. </binding>
  7. 21. </netTcpBinding>

22. </bindings>

23.  <services>

  1. <service behaviorConfiguration=”ProductsBehavior”
  2. name=”Products.ProductsServiceImpl”>
  3. <endpoint binding=”netTcpBinding”
  4. bindingConfiguration=”ProductsServiceTcpBindingConfig”
  5. name=”ProductsServiceTcpBinding” contract=”Products.IProductsService” />
  6. </service>

31.  </services>

32.  …

</system.serviceModel>

Be careful not to change anything in this file. Close the  App.config file when you have finished examining it.

The service will expect clients that connect to the endpoint for this binding to use the same message level security settings. You will configure the client next.

Enable message level encryption for the NetTcpBinding binding for the WCF client

  1. In the ProductsClient project, edit the  app.config file by using the WCF Service Configuration Editor.
  2. In the WCF Service Configuration Editor, right-click the Bindings folder and then click New Binding Configuration.
Note The client configuration file already contains a binding configuration for the basicHttpBinding that was generated in Chapter 1, “Introducing Windows Communication Foundation.” Be careful not to modify this binding configuration by mistake!
  1. In the Create a New Binding dialog box, select the netTcpBinding binding type and then click OK.
  2. In the right pane of the WCF Service Configuration Editor, change the Name property of the binding to ProductsClientTcpBindingConfig.
  3. Click the Security tab.
  4. Change the Mode property to Message. Change the AlgorithmSuite property to Basic128. Leave the MessageClientCredentialType property set to Windows.
Note If you select a different algorithm suite for the client and server, they will not be able to decipher each other’s communications. This will result in a runtime exception in the channel stack. If you are curious about this, try setting the AlgorithmSuite to TripleDes (for example) and examine the exception that occurs when you run the solution later.
  1. In the left pane of the WCF Service Configuration Editor, click the NetTcpBinding_IProductsService node in the Endpoints folder, under the Client folder.
  2. In the right pane, set the BindingConfiguration property to ProductsClientTcpBinding Config.
  3. Save the configuration, and then exit the WCF Service Configuration Editor.
  4. Start the solution without debugging.
  5. In the ProductsServiceHost form, click Start. If a Windows Security Alert dialog box appears, click Unblock to allow the service to access the TCP port.
  6. In the client console window, press Enter. Verify that the client application runs exactly as before.
  7. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.

This exercise has shown you how easy it is to configure a WCF service and client application to secure messages by performing encryption, but how do you actually know that the messages have been encrypted? To answer this question, you can enable message tracing and then examine the messages as they flow in and out of the service.

Configure message tracing for the WCF service

  1. In Visual Studio 2005, edit the  App.config file for the ProductsServiceHost project by using the WCF Service Configuration Editor.
  2. In the WCF Service Configuration Editor, expand the Diagnostics folder and then click Message Logging.
  3. In the right pane displaying the message logging settings, set the following properties to True:
    • LogEntireMessage
    • LogMessagesAtServiceLevel
    • LogMessagesAtTransportLevel

The LogEntireMessage property specifies whether the trace output should include the body of messages sent and received. Setting this property to True includes the body of the message. The default value, False, only traces the message header. Setting the LogMessagesAtServiceLevel property to True traces messages as they are presented to the service and as they are output from the service. If you are using message level security, this trace will show the unencrypted messages after they have been received and decrypted at the message level (for incoming messages) or before they are encrypted (for outgoing messages). Setting the LogMessagesAtTransportLevel property to True traces messages as they are sent to or received from the transport level. If you are using message level security, the messages traced at this point will be encrypted, although if you are using transport level security messages will already have been decrypted (for incoming messages) or not yet encrypted (for outgoing messages) at this point.

Important Tracing at the message level records messages in their unencrypted form. You should ensure that you protect the trace files that are generated and only let authorized users examine this data.
  1. In the left pane, right-click the Sources folder and then click New Source.

All tracing information for WCF is received from one or more trace sources. In this case, you will use the MessageLogging source, which traces messages. You can also use other sources. For example, the ServiceModel source traces events that occur in a service, such as tracking when a service starts listening, receives requests, and sends responses.

  1. In the right pane, set the Name property to System.ServiceModel.MessageLogging. Set the Trace level property to Verbose.
  2. In the left pane, right-click the Listeners folder, and then click New Listener.

A listener object is responsible for receiving data from the trace sources, formatting and filtering them, and then sending them to a destination.

  1. In the right pane, set the Name property to MessageLog.
  2. In the InitData property, click the ellipses button. In the Save Log As dialog box, move to the Microsoft Press\WCF Step By Step\Chapter 4 folder under your \My Documents folder. Set the file name to Products.svclog, and then click Save.

The InitData property specifies the name of the file that the listener will use for saving trace data. When tracing starts, if this file does not exist, the listener will create it; otherwise, it will append trace information to the end of any existing data in the file.

  1. In the TraceOutputOptions property, click the dropdown arrow. Clear all items in the list. The trace output options are useful if you are tracing messages for multiple client applications and you need to be able to correlate the different request and response messages. In this example, you will be running a single client application, so this additional information is not really necessary.
  2. Verify that the TypeName property is set to System.Diagnostics.XmlWriter.TraceListener. The listener can output data in several formats. However, you will be using another tool called the Service Trace Viewer to examine the trace output, and this tool expects the data to be in XML format.
  3. Click Add at the bottom of the right pane. In the Add Tracing Source dialog box, select the System.ServiceModel.MessageLogging source, and then click OK.
  4. Save the configuration, and then exit the WCF Service Configuration Editor.

Run the WCF client and service and examine the trace output

  1. Start the solution without debugging.
  2. In the ProductsServiceHost form, click Start.
  3. In the client console window, press Enter. Verify that the client application still runs correctly.
  4. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.
  5. On the Windows Start menu, point to All Programs, point to Microsoft Windows SDK, point to Tools, and then click Service Trace Viewer.
  6. In the Service Trace Viewer, on the File menu, click Add.
  7. In the Open dialog box, move to the Microsoft Press\WCF Step By Step\Chapter 4\ProductsService folder under your \My Documents folder, select the file Products.svclog, and then click Open.
  8. In the Service Trace Viewer, in the left pane, click the Message tab. You will see a list of messages sent and received by the service, identified by their Action values.
Tip Expand the Action column in this pane to see more of the name for each action.
  1. At the top of this list are a number of messages in the http://schemas.xmlsoap.org/ws/2005/02/trust namespace. These messages are concerned with sending and verifying the user’s identity, and negotiating the encryption mechanism and encryption keys that the client application and WCF service will use for sending and receiving messages. These messages are followed by the application messages received and sent by the WCF service, identified by the http://tempuri.org namespace.
  2. Click the first message with the action http://tempuri.org/IProductsService/ListProducts. Note that each action occurs twice. This is because you traced each message twice: once at the message level and once at the transport level.
  3. In the lower right pane, click the Message tab. The window will display the entire SOAP message. This is the version of the message passed from the transport level to the message level. The message has a rather lengthy SOAP header, which you can examine at your leisure. The interesting part is the SOAP body, at the end of the message. This is the encrypted ListProducts request received from the client application. The <e:CipherValue> element contains the data for the request, as highlighted in the following image:

  1. In the left pane, click the second message with the action http://tempuri.org/IProductsService/ListProducts. In the right pane, scroll to the end of the Message window. This is the unencrypted version of the message passed from the message level to the service:

  1. In the left pane, click the first message with the action http://tempuri.org/IProductsService/ListProductsResponse. In the right pane, examine the message body in the Message window. You can see that this is an unencrypted message containing the list of products returned in response to the ListProducts request. This message is the output from the service to the message level and so has not yet been encrypted.
  2. In the left pane, click the second message with the action http://tempuri.org/IProductsService/ListProductsResponse. In the right pane, scroll to the bottom of the Message window and examine the message body. This time you can see that this is the encrypted response sent by the message level to the transport level for transmission back to the client.
  3. Examine the other messages. When you have finished, close the Service Trace Viewer.

Protecting an HTTP Service at the Transport Level

If you recall, the ProductsServiceHost application exposes two endpoints for clients to connect to: one based on the TCP protocol and the other using HTTP. The HTTP endpoint is configured to use the BasicHttpBinding binding. The BasicHttpBinding binding conforms to the WS-BasicProfile 1.1 specification and is intended for use with existing legacy Web services and clients. It is fully interoperable with ASP.NET Web services. By default, this binding provides minimal security; it does not support message level encryption or authentication, for example. To implement message confidentiality and remain interoperable with ASP.NET Web services, you should use transport level security. This requires you to configure HTTPS.

Note The BasicHttpBinding binding also supports message level security. Ordinary ASP.NET Web services and client applications do not implement the WS-Security specification, and so will not be able to communicate with a service that implements message level security. However, Microsoft Web Services Enhancements (WSE) does support WS-Security, so Web services that you create by using WSE can communicate with a WCF service through an endpoint based on the BasicHttpBinding binding by using message level security.

Specify transport level security for the BasicHttpBinding binding for the WCF service

  1. In Visual Studio 2005, in the ProductsServiceHost project in Solution Explorer, edit the  App.config file by using the WCF Service Configuration Editor.
  2. In the WCF Service Configuration Editor, right-click the Bindings folder and then click New Binding Configuration.
  3. In the Create a New Binding dialog box, select the basicHttpBinding binding type and then click OK.
  4. In the right pane of the WCF Service Configuration Editor, change the Name property of the binding to ProductsServiceBasicHttpBindingConfig.
  5. Click the Security tab. Set the Mode to Transport.

In this mode, message security is provided by using HTTPS. You must configure SSL for the service by using a certificate. The client authenticates the service by using the service’s SSL certificate. The service authenticates the client by using the mechanism specified by the TransportClientCredentialType property. The default value of None does not provide any authentication–you will examine some of the other values you can specify for this property later in this chapter.

  1. In the left pane of the WCF Service Configuration Editor, expand the ProductsServices-Impl service in the Services folder, expand the Endpoints folder, and then click the ProductsServiceHttpEndpoint endpoint.
  2. In the right pane, set the BindingConfiguration property to ProductsServiceBasicHttpBindingConfig.
  3. HTTP Web services that implement transport level security must specify the https scheme, so change the Address property as follows:

https://localhost:8000/ProductsService/ProductsService.svc

  1. Save the configuration, and exit the WCF Service Configuration Editor.
  2. Rebuild the ProductsServiceHost project.

The next step is to reconfigure and modify the client to connect to the service by using the endpoint corresponding to the BasicHttpBinding binding.

Specify transport level security for the BasicHttpBinding binding for the WCF client

  1. In the ProductsClient project, edit the  app.config file by using the WCF Service Configuration Editor.
  2. In the WCF Service Configuration Editor, expand the Bindings folder and then click the BasicHttpBinding_IProductsService binding.
  3. In the right pane of the WCF Service Configuration Editor, change the Name property of the binding to ProductsClientBasicHttpBindingConfig. (This is to make the name of the binding consistent with the other bindings you have created. The original binding name was generated by the svcutil utility back in Chapter 1.)
  4. Click the Security tab. Change the Mode to Transport.
  5. In the left pane of the WCF Service Configuration Editor, click the BasicHttpBinding_IProductsService endpoint in the Endpoints folder, under the Client folder.
  6. In the right pane, change the address to use the https scheme as shown below, and verify that the BindingConfiguration property has changed to ProductsClientBasicHttpBindingConfig:

https://localhost:8000/ProductsService/ProductsService.svc

  1. Save the configuration, and then exit the WCF Service Configuration Editor.
  2. In Visual Studio 2005, in Solution Explorer, open the  Program.cs file for the ProductsClient project.
  3. In the Main method, update the statement that creates the proxy object to connect to the WCF service by using the endpoint named BasicHttpBinding_IProductsService:

10.ProductsServiceClient proxy = new ProductsServiceClient(“BasicHttpBinding_

IProductsService“);

  1. Rebuild the ProductsClient project.

If you try and run the client and service at this point, the client will fail with a CommunicationException, like this:

This error occurs because you have not yet configured transport security for the HTTPS protocol. In the next exercise, you will create a certificate for the WCF service, and configure SSL for the service by using the httpcfg utility.

Configure the WCF HTTP endpoint with an SSL certificate

  1. On the Windows Start menu, point to All Programs, point to Microsoft Windows SDK, and then click CMD Shell.

A command prompt window opens, with an environment configured for running the Windows SDK tools.

  1. In the command prompt window, type the following command:

makecert -sr LocalMachine -ss My -n CN=HTTPS-Server -sky exchange -sk HTTPS-Key

The makecert utility is a useful tool for creating test certificates that you can use for development purposes. The command shown here creates a certificate that is stored in the Personal certificates store for the LocalMachine account. For detailed information about the options for the makecert utility, see the Windows SDK Documentation installed with the Windows SDK.

Important Certificates that you create by using the makecert utility should not be used in a production environment as they are not certified by a verifiable certification authority. Remember that the service sends this certificate to the client to prove its identity. The client must be able to trust that this certificate was created by a reliable source that can verify the veracity of the service. When deploying a production service, you should obtain your certificates from recognized certification authority, such as VeriSign or Thawte. Alternatively, you can use Windows Certificate Services, which enables an enterprise to generate its own certificates.

To use the httpcfg utility to configure SSL for the service, you need to find the thumb-print of the certificate. The thumbprint is a hexadecimal string that uniquely identifies the certificate. You can obtain this information by using the Certificates Microsoft Management Console snap-in.

  1. In the command prompt window, type the following command:

mmc

This command starts the Microsoft Management Console, displaying the default Console Root window.

  1. In the File menu, click Add/Remove Snap-In.
  2. In the Add/Remove Snap-In dialog box, click Add.
  3. In the Add Standalone Snap-In dialog box, select the Certificates snap-in and then click Add.
  4. In the Certificates Snap-In dialog box, select Computer account and then click Next.
  5. In the Select Computer dialog box, select Local computer and then click Finish.
  6. In the Add Standalone Snap-In dialog box, click Close.
  7. In the Add/Remove Snap-In dialog box, click OK.
  8. In the Console Root window, expand the Certificates node, expand the Personal folder, and then click the Certificates folder. The HTTPS-Server certificate that you created by using the makecert utility should be displayed:

  1. Double-click the HTTPS-Server certificate.
  2. In the Certificate window, click the Details tab. Scroll to the bottom of the window displaying the details of the certificate. Click the Thumbprint property, and make a note of the hexadecimal string displayed in the lower window:

Tip You might find it useful to simply select the text in the lower window and copy it to the Windows clipboard.
  1. Click OK, close the Microsoft Management Console window, and return to the command prompt window.
  2. In the command prompt window, type the command shown below. Replace the hexadecimal string following the –h flag with the digits from the certificate thumbprint (remove all spaces from the thumbprint string first):

httpcfg set ssl -i 0.0.0.0:8000 -h c390e7a4491cf97b96729167bf50186a4b68e052

If this command is successful, it should report the message “HttpSetServiceConfiguration completed with 0.”

Note Be very careful to specify the correct thumbprint. If you type an invalid thumb-print, the command still succeeds, but the client will not be able to communicate with the service as the thumbprint does not refer to a valid certificate.

This command binds the certificate with the thumbprint indicated with the –h flag to the port indicated by the –i flag. The port is specified as the IP address of the computer followed by the port. Specifying an IP address of 0.0.0.0 denotes the local computer.

Note Under Windows Vista, use the netsh command to configure SSL rather than httpcfg., like this: netsh http add sslcert ipport=0.0.0.0:8000 certhash= c390e7a4491cf97b96729167bf50186a4b68e052 appid={}. The certhash parameter specifies the thumbprint. The appid parameter is a GUID that identifies this binding of the certificate to the port; you can use any unique GUID.
Warning When a client application receives a certificate from a server, the WCF runtime attempts to ascertain that the certificate is valid and that the authority that issued it is trusted. The WCF runtime will fail this check when using the certificate that you have just installed. The following exercise shows how to force the WCF runtime to override this check and allow this certificate to be used. You should never do this in a production environment! The code is provided as-is, and without further explanation (it is not the author’s work–it was written by developers at Microsoft and is included in one of the WCF technology samples provided with the Windows SDK). In the real world, you should go out and buy a valid certificate.

Add code to the WCF client to override certificate validation checking

  1. In Visual Studio 2005, edit the  Program.cs file for the ProductsClient project.
  2. Add the following using statements to the list at the top of the file:

3.  using System.Security.Crytography.X509Certificates;

using System.Net;

  1. Add the following class to the ProductsClient namespace, underneath the Program class:
Note The code for this class is available in the  PermissiveCertificatePolicy.cs file in the Chapter 4 folder, if you don’t want to type it in manually.

5.  // WARNING: This code is only needed for test certificates such as those

6.  // created by makecert. It is not recommended for production code.

7.  class PermissiveCertificatePolicy

8.  {

  1. string subjectName;
  2. static PermissiveCertificatePolicy currentPolicy;
  3. PermissiveCertificatePolicy(string subjectName)
  4. {
  5. this.subjectName = subjectName;
  6. ServicePointManager.ServerCertificateValidationCallback +=
  7. new System.Net.Security.RemoteCertificateValidationCallback
  8. (RemoteCertValidate);
  9. }

18.

  1. public static void Enact(string subjectName)
  2. {
  3. currentPolicy = new PermissiveCertificatePolicy(subjectName);
  4. }

23.

  1. bool RemoteCertValidate(object sender, X509Certificate cert,
  2. X509Chain chain, System.Net.Security.SslPolicyErrors error)
  3. {
  4. if (cert.Subject == subjectName)
  5. {
  6. return true;
  7. }

31.

  1. return false;
  2. }

34.}

  1. Add the following statement shown in bold to the Main method of the Program class, immediately before creating the proxy object:

36.…

37.PermissiveCertificatePolicy.Enact(“CN=HTTPS-Server”);

38.ProductServiceClient proxy = new ProductServiceClient(…);

39.…

Run the WCF client and service

  1. Start the solution without debugging.
  2. In the ProductsServiceHost form, click Start.
  3. In the client console window, press Enter. Verify that the client application runs correctly.
  4. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.

Protecting an HTTP Service at the Message Level

You can configure the BasicHttpBinding binding to provide message level security by selecting the Message security mode for the binding. In this mode, the service uses SOAP message level security to encrypt the message. The service must have a certificate installed, and the client uses the public key from the service’s certificate to perform the encryption. The service can send the certificate containing its public key at the start of the message exchange, or an administrator can install the service certificate on the client computer before the client application (in which case you must specify how to locate the service certificate in the client certificate store by adding a service behavior using the <serviceCredentials> element to the client configuration file). You will learn more about this in Chapter 5. Additionally, the only authentication mechanism supported by a WCF service that uses this mode requires that the client application identifies itself with a certificate–you cannot use authentication mechanisms such as Windows Integrated Security with this mode.

One other option is to use the TransportWithMessageCredential security mode. This is a hybrid combination of message level and transport level security. The service uses the HTTPS protocol and a certificate to provide message integrity and confidentiality. Client authentication is handled at the message level by using SOAP message security, and the client application can provide a username and password to identify the user. You will learn more about this security mode in Chapter 5.

If you really want to implement message level security for a WCF service with the minimum of fuss and configuration, you can opt to use the WSHttpBinding binding. The WSHttpBinding binding conforms to the current WS-* specifications and follows the WS-Security specification for encrypting messages and authenticating users by default. The following exercises demonstrate how to use the WSHttpBinding binding to implement message level security over HTTP.

Configure the WCF service to use the WSHttpBinding binding

  1. In Visual Studio 2005, edit the  App.config file for the ProductsServiceHost project by using the WCF Service Configuration Editor.
  2. In the left pane, expand the Products.ProductsServiceImpl node under the Services folder, right-click Endpoints, and then click New Service Endpoint.
  3. In the right pane, set the properties of the endpoint to the values in the following table. Leave all other properties with their default value:
Open table as spreadsheet Property Value
Name ProductsServiceWSHttpEndpoint
Address http://localhost:8010/ProductsService/ProductsService.svc
Binding wsHttpBinding
Contract Products.IProductsService
  1. Notice that the scheme used for the address of this endpoint is http, and not https.
  2. Save the changes, and exit the WCF Service Configuration Editor.
  3. Rebuild the ProductsServiceHost project.

Configure the WCF client to use the WSHttpBinding binding

  1. Edit the  app.config file for the ProductsClient project by using the WCF Service Configuration Editor.
  2. In the left pane, right-click Endpoints in the Client folder, and then click New Client Endpoint.
  3. In the right pane, set the properties of the endpoint to the values in the following table:
Open table as spreadsheet Property Value
Name WSHttpBinding_IProductsService
Address http://localhost:8010/ProductsService/ProductsService.svc
Binding wsHttpBinding
Contract ProductsClient.ProductsService.IProductsService
  1. Save the changes, and exit the WCF Service Configuration Editor.
  2. In Visual Studio 2005, edit the  Program.cs file in the ProductsClient project. In the Main method, change the code that creates the proxy object to use the new binding, as follows:

6.  ProductsServiceClient proxy = new

ProductsServiceClient(“WSHttpBinding_IProductsService“);

  1. Rebuild the ProductsClient project.

Run the WCF client and service and examine the trace output

  1. Using Windows Explorer, delete the existing trace file Products.svclog in the Microsoft Press\WCF Step By Step\Chapter 4\ProductsService folder under your \My Documents folder.
  2. In Visual Studio 2005, start the solution without debugging.
  3. In the ProductsServiceHost form, click Start. In the client console window, press Enter. Verify that the client application still runs correctly. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.
  4. Start the Service Trace Viewer tool, and open the Products.svclog file.
  5. In the Service Trace Viewer, in the left pane, click the Message tab.
  6. Click the first message with the action http://tempuri.org/IProductsService/ListProducts. In the lower right pane, click the Message tab. You can see that the message has been encrypted–the body element of the message contains encrypted data.
  7. In the left pane, click the second message with the action http://tempuri.org/IProductsService/ListProducts. In the right pane, scroll to the end of the Message window. This is the unencrypted version of the message passed from the message level to the service.
  8. Examine the two ListProductsResponse messages. As with the NetTcpBinding example earlier in this chapter, you can see the encrypted version of the message being output by the service to the message level and the encrypted version of the message passing from the message level to the transport level.
  9. Close the Service Trace Viewer.

The WSHttpBinding binding uses the 256-bit version of the AES encryption algorithm to encrypt data by default. You can select a different algorithm by creating a binding behavior and specifying the algorithm to use in the AlgorithmSuite property of the behavior, as you did when configuring message level security for the NetTcpBinding binding earlier in this chapter.

Authenticating Windows Users

So far, you have seen how to configure the NetTcpBinding, BasicHttpBinding, and WSHttp-Binding bindings to support confidentiality and privacy by encrypting messages. However, transporting messages securely is only useful if a service can verify the identity of the user running the client application. In the exercises that follow, you will look at how a service can authenticate a user when the client application and service are both running within the same Windows domain. In Chapter 5, you will see how to perform authentication when a client and service are located in different, possibly non-Windows, security domains.

You will start by adding code to the ProductsService service that displays the name of the user calling the ListProducts operation. You will then be able to see the effect that the authentication options available in WCF have on the identity passed from a client application to a service.

Note You can configure authentication to be largely transparent to the WCF service. You will see in the exercises in this section that most of the actual authentication process is performed by the WCF runtime executing the service. All the service needs to do is specify the type of authentication it requires.

Display the name of the user calling an operation in the WCF service

  1. In Visual Studio 2005, add a reference to the System.Windows.Forms assembly to the ProductsService project.
  2. Open the  ProductsService.cs file.

This file contains the code that implements the operations for the ProductsService service.

  1. Add the following using statements to the list at the top of the file:

4.  using System.Threading;

using System.Windows.Forms;

  1. Locate the ListProducts method in the ProductsServiceImpl class. Add the following statements as the first two lines of the method:

6.  string userName = Thread.CurrentPrincipal.Identity.Name;

7.  MessageBox.Show(“Username is ” + userName,

“ProductsService Authentication”);

The first statement retrieves the name of the Windows user that the current thread is running on behalf of. The second statement displays the username in a message box.

  1. Edit the  Program.cs file in the ProductsClient project. In the Main method, change the code that creates the proxy object to use the BasicHttpBinding binding, as follows:

9.  ProductsServiceClient proxy = new

ProductsServiceClient(“BasicHttpBinding_IProductsService“);

  1. Start the solution without debugging.
  2. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

A message box appears, displaying the user name sent by the client application. The user name will appear to be missing. This is not an error. By default, the BasicHttpBinding binding does not send authentication information about users. All messages are sent as the anonymous user.

  1. Click OK, and verify that the client application still runs correctly.
  2. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.

In the next set of exercises, you will revisit the BasicHttpBinding binding and implement user authentication. Many of the authentication options available for this binding apply to other bindings as well.

Configure the BasicHttpBinding binding for the WCF service to use Basic authentication

  1. Edit the  App.config file in the ProductsServiceHost project by using the WCF Service Configuration Editor.
  2. In the left pane, expand the Bindings folder and click the ProductsServiceBasicHttpBindingConfig node.
  3. In the right pane, click the Security tab.

Notice that the TransportClientCredentialType property is currently set to None, so the service is not expecting client applications to provide authentication information about users, and anyone who can connect to the service can send it messages and invoke operations.

  1. Set the TransportClientCredentialType property to Basic.

When using Basic authentication, the client application must provide a username and password, which is transmitted to the service. The WCF runtime executing the service can use this information to authenticate the user running the client application, and if the user is valid, it will provide the identity of the user to the service.

  1. Save the configuration, and close the WCF Service Configuration Editor.
  2. Start the solution.
  3. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

The client fails with a MessageSecurityException exception, “The HTTP request is unauthorized with client authentication scheme ‘Anonymous’… .” The WCF runtime for the service was expecting the client application to provide a username and password, which it has not done.

  1. Close the client console window, stop the service, and close the ProductsServiceHost form.

Modify the WCF client to supply the user credentials to the service

  1. In Visual Studio 2005, edit the  app.config file in the ProductsClient project by using the WCF Service Configuration Editor.
  2. In the left pane, expand the Bindings folder and click the ProductsClientBasicHttpBindingConfig node.
  3. In the right pane, click the Security tab.
  4. Set the TransportClientCredentialType property to Basic.
  5. Save the configuration, and close the WCF Service Configuration Editor.
  6. Edit the  Program.cs file in the ProductsClient project.
  7. In the Main method, add the following statements shown in bold immediately after the code that creates the proxy object. Replace LON-DEV-01 with the name of your domain or computer (if you are not currently a member of a domain), replace Student with your username, and replace Pa$$w0rd with your password:

8.  ProductsServiceClient proxy = new

  1. ProductsServiceClient(“BasicHttpBinding_IProductsService”);

10.proxy.ClientCredentials.UserName.UserName = “LON-DEV-01\\Student”;

11.proxy.ClientCredentials.UserName.Password = “Pa$$w0rd”;

The ClientCredentials property of a WCF proxy object provides a mechanism for a client application to provide the credentials to send to the service. The UserName property of ClientCredentials can hold a username and password. Other properties are available, such as ClientCertificate, which enable you to supply different types of credentials information as required by the service configuration.

Warning This code is for illustrative purposes in this exercise only. In a production application, you should prompt the user for their name and password. You should never hard-code these details into an application.
  1. Start the solution without debugging.
  2. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

A message box appears, displaying the user name sent by the client application. This time, the user name appears as expected, verifying that the operation is executing with the credentials of the user.

  1. Click OK, and verify that the client application still runs correctly.
  2. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.

Using Basic authentication, you can provide the username and password of the user, and the WCF runtime executing the service will check that these credentials are valid. If you provide an invalid username of password, the WCF runtime will reject the request and the client will receive another MessageSecurityException exception with the message “The HTTP request was forbidden… .”

Basic authentication is a good solution if the user running the client application is not currently logged into the security domain used by the service.

Note You can also configure the NetTCPBinding and WSHttpBinding bindings at the message level to require Username authentication. This is very similar to Basic authentication at the transport level as far as client application is concerned, although somewhat different as far as the service is concerned, as it takes responsibility for authenticating the user itself (typically using a custom database of usernames and passwords). However, usernames and passwords are not encrypted at the message level, so WCF insists that the underlying transport provide encryption to prevent the credential details being transmitted across an open network as clear text.

If the user is logged in to the domain, then you can make use of Windows Integrated Security to provide the user’s credentials automatically, rather than prompting the user for them again (or worse still, hard-coding them in your application!).

Configure the BasicHttpBinding binding for the WCF service and client to use Windows authentication

  1. Edit the  App.config file in the ProductsServiceHost project by using the WCF Service Configuration Editor.
  2. In the left pane, expand the Bindings folder, and click the ProductsServiceBasicHttpBindingConfig node.
  3. In the right pane, click the Security tab.
  4. Set the TransportClientCredentialType property to Windows.
  5. Save the configuration and close the WCF Service Configuration Editor.
  6. In Visual Studio 2005, edit the  app.config file in the ProductsClient project by using the WCF Service Configuration Editor.
  7. Repeat the process in steps 2 through 5, above and set the TransportClientCredentialType property of the ProductsClientBasicHttpBindingConfig binding configuration to Windows.
  8. Save the configuration, and close the WCF Service Configuration Editor.
  9. Edit the  Program.cs file in the ProductsClient project.
  10. In the Main method, comment out the two statements that add the username and password to the ClientCredentials property of the proxy object.
  11. Start the solution without debugging.
  12. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

The message box appears displaying your Windows username, which was sent by the client application. However, rather than you having to supply the username and password, the WCF runtime executing the client application picked this information up from the user’s process automatically.

Note If you omitted to comment out the lines that populated the ClientCredentials object, the solution still works; the credentials provided are simply ignored. However, note the ClientCredentials property has a Windows property that you can use to provide a domain, username, and password to the service if you want the service to run as a different Windows user. Any values that you specify in the Windows property override those retrieved from the user’s login process. The usual warnings about hard-coding usernames and password in your code still apply:

proxy.ClientCredentials.Windows.ClientCredential.Domain = “LON-DEV-01″;

proxy.ClientCredentials.Windows.ClientCredential.UserName = “Administrator”;

proxy.ClientCredentials.Windows.ClientCredential.Password = “P@ssw0rd”;

  1. Click OK in the message box, and verify that the client application still runs correctly.
  2. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.

When you use Windows Integrated Security, usernames and passwords are not transmitted as clear text. You can use Windows Integrated Security at the message level with the NetTCPBinding and WSHttpBinding bindings without needing to implement encryption at the transport level.

Examine the authentication mechanism used by the NetTcpBinding binding

  1. Edit the  App.config file in the ProductsServiceHost project by using the WCF Service Configuration Editor.
  2. In the left pane, expand the Bindings folder, and click the ProductsServiceBasicTcpBindingConfig node.
  3. In the right pane, click the Security tab.
  4. Verify that the MessageClientCredentialType property is set to Windows.

You have been using Windows Integrated Security without realizing it in earlier exercises!

Note The WSHttpBinding binding also defaults to using Windows Integrated Security.
  1. Close the WCF Service Configuration Editor without saving changes.
  2. Edit the  Program.cs file for the ProductsClient project and modify the statement that creates the proxy object to use the NetTcpBinding binding, as follows:

7.  ProductsServiceClient proxy = new

ProductsServiceClient(“NetTcpBinding_IProductsService“);

  1. Start the solution without debugging.
  2. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

The familiar message box appears, displaying your Windows user name, proving that the NetTcpBinding automatically picks up your identity from Windows.

  1. Click OK, and allow the client application to finish. Press Enter to close the client console window. Stop the service and close the ProductsServiceHost form.

Authorizing Users

After a service has established the identity of the user, it can then determine whether the service should perform the requested operations for the user. Different operations in a service could be considered more privileged than others. For example, in the ProductsService service, you might wish to let any staff who work in the warehouse query the product information in the AdventureWorks database but limit access to operations such as ChangeStockLevel, which modify data, to staff members who are stock controllers. WCF can use the features of the .NET Framework to enable a developer to specify which users and roles have the authority to request operations. You can perform this task declaratively (by using attributes) or imperatively (by adding code to the operations).

The authorization mechanism used by WCF requires access to a database defining users and the roles that they can fulfill. If you are performing authentication by using Active Directory, it makes sense to use the Active Directory database to hold the roles for each user as well. Therefore, the first step is to ensure that the WCF service is configured to retrieve roles from Active Directory by using the Windows Token Role Provider.

Configure the WCF service to use the Windows Token Role Provider

  1. Edit the  App.config file in the ProductsServiceHost project by using the WCF Service Configuration Editor.
  2. In the left pane, expand the Advanced folder, expand the Service Behaviors folder and then click the ProductsBehavior node.

The ProductsBehavior behavior currently contains the serviceDebug element. You added this behavior to the service in Chapter 3.

  1. In the right pane, click Add.
  2. In the Adding Behavior Element Extension Sections dialog box, select serviceAuthorization and then click Add.

The serviceAuthorization behavior is added to the list of behaviors.

  1. In the left pane, click serviceAuthorization under the ProductsBehavior node.
  2. In the right pane, verify that the PrincipalPermissionMode property is set to UseWindowsGroups.

By default, WCF uses the Windows Token Role Provider to authenticate users, so you don’t actually need to change anything. However, you can configure the serviceBehavior element to specify a different role provider, such as the SQL Role Provider or the Authorization Store Role Provider mentioned earlier in this chapter. (You will configure the service to use the SQL Role Provider in Chapter 5.)

  1. Save the configuration and close the WCF Service Configuration Editor.

The next step is to define the roles that can request the operations in the WCF service. When using the Windows Token Role Provider, Active Directory groups correspond to roles, so you define groups in the Active Directory database and add users to these groups.

Note The following exercise assumes you do not have access to the Active Directory database for your organization, so it uses the Windows local users and groups database instead. The principles are the same, however.

Create groups for warehouse staff and stock controller staff

  1. On the Windows Start menu, right-click My Computer, and then click Manage.

The Computer Management console appears.

  1. In the Computer Management console, under the System Tools node, expand the Local Users and Groups node, right-click the Groups folder, and then click New Group.
  2. In the New Group dialog box, enter WarehouseStaff for the Group name, and then click Create.
  3. Still in the New Group dialog box, enter StockControllers for the Group name, and then click Create.
  4. Click Close to close the New Group dialog box.

The two new groups should appear in the list of groups in right pane of the Computer Management console.

  1. In the left pane of the Computer Management console, right-click the Users folder and then click New User.
  2. In the New User dialog box, use the values in the following table to set the properties of the user and then click Create.
Open table as spreadsheet Property Value
User name Fred
Password Pa$$w0rd
Confirm password Pa$$w0rd
User must change password at next logon Unchecked
  1. Add another user by specifying the values in the following table, and then click Create again.
Open table as spreadsheet Property Value
User name Bert
Password Pa$$w0rd
Confirm password Pa$$w0rd
User must change password at next logon Unchecked
  1. Click Close the close the New User dialog box.
  2. In the left pane of the Computer Management console, click the Users folder.

The two new users should appear in the list in the right pane of the Computer Management console.

  1. In the right pane of the Computer Management console, right-click Bert and then click Properties.
  2. In the Bert Properties dialog box, click the Member Of tab and then click Add.
  3. In the Select Groups dialog box, type WarehouseStaff in the text box and then click OK.

Bert is added to the WarehouseStaff group.

  1. In the Bert Properties dialog box, click OK.
  2. In the right pane of the Computer Management console, right-click Fred and then click Properties.
  3. In the Fred Properties dialog box, click the Member Of tab and then click Add.
  4. In the Select Groups dialog box, type WarehouseStaff in the text box and then click OK.
  5. Click Add again. In the Select Groups dialog box, type StockControllers in the text box and then click OK.

Fred is added to the WarehouseStaff and StockControllers groups–he has two roles.

  1. In the Fred Properties dialog box, click OK.
  2. Close the Computer Management console.

You can now use the groups you have just defined to specify the roles that can request each of the operations in the ProductsService service. To show how to specify authorization declaratively and imperatively, you will use attributes to specify the role for the operations that simply query the AdventureWorks database, but you will write code to specify the role that can modify the database.

Specify the roles for the WCF service operations

  1. In Visual Studio 2005, open the  ProductsService.cs file in the ProductsService project.
  2. Add the following using statements to the list at the top of the file:

3.  using System.Security;

4.  using System.Security.Permissions;

using System.Security.Principal;

  1. Locate the ListProducts method in the ProductsServiceImpl class. Add the following attribute, shown in bold, to this method:

6.  [PrincipalPermission(SecurityAction.Demand, Role="WarehouseStaff")]

7.  public List<string> ListProducts()

8.  {

}

The PrincipalPermission attribute specifies the authorization requirements of the method. In this case, the SecurityAction.Demand parameter indicates that the method requires that the user meet the criteria specified by the following parameters. The Role parameter indicates that the user must be a member of the WarehouseStaff role.

You can identify specific users by using the optional Name parameter. However, if you specify Name and Role, then the user must match both criteria to be granted access (if the user is not a member of the specified role, they will not be allowed to execute the method). If you require users to be granted access to the method if they have a specific name or are a member of a specific group, you can use the PrincipalPermission attribute twice, like this:

[PrincipalPermission(SecurityAction.Demand, Role="WarehouseStaff")]

// LON-DEV-01\Student is not a member of the WarehouseStaff group

[PrincipalPermission(SecurityAction.Demand, Name="LON-DEV-01\\Student")]

public List<string> ListProducts()

{

}

You can also specify SecurityAction.Deny as the first parameter to the PrincipalPermission attribute. If you do this, the specified users and roles will be explicitly denied access to the method.

  1. Apply the PrincipalPermission attribute with the WarehouseStaff group to the GetProduct and CurrentStockLevel methods, as shown in bold below:

11.[PrincipalPermission(SecurityAction.Demand, Role="WarehouseStaff")]

12.public Product GetProduct(string ProductNumber)

13.{

15.}

16.[PrincipalPermission(SecurityAction.Demand, Role="WarehouseStaff")]

17.public int GetStockLevel(string ProductNumber)

18.{

}

  1. Locate the ChangeStockLevel method. Add the following code, shown in bold, to the start of this method:

21.public bool ChangeStockLevel(…)

22.{

  1. 23. // Determine whether the user is a member of the StockControllers role
  2. 24. WindowsPrincipal user = new WindowsPrincipal(
  3. 25. (WindowsIdentity)Thread.CurrentPrincipal.Identity);
  4. 26. if (!(user.IsInRole(“StockControllers”)))
  5. 27. {
  6. 28. // If the user is not in the StockControllers role,
  7. 29. // throw a SecurityException
  8. 30. throw new SecurityException(“Access denied”);
  9. 31. }

}

The first statement retrieves the identity information for the user and uses it to create a WindowsPrincipal object. Note that the identity returned by the current thread must be cast to a WindowsIdentity object. A WindowsPrincipal object is a representation of the user. It exposes the IsInRole method that this code uses to determine whether the user is a member of the StockControllers role. The IsInRole method returns true if the user is a member of the role, false otherwise. If the user is not a member of the role, the code throws a SecurityException exception with the message “Access Denied.”

Warning It is tempting to provide more detail in the SecurityException exception. This practice is not recommended, as it could provide an attacker with useful information that they might be able to use to try and infiltrate your system. Keep the exception message bland!

Test the authorization for the WCF service

  1. Start the solution without debugging.
  2. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

Assuming you are not currently logged in to Windows as Fred or Bert, the client application stops and reports the message “Access is denied” when attempting to invoke the ListProducts operation. This is because the authenticated Windows account for the client application must be a member of the WarehouseStaff role:

  1. Press Enter to close the client console window, and then stop the service and close the ProductsServiceHost form.
  2. In the ProductsClient project in Solution Explorer, open the  Program.cs file.
  3. In the Main method, add the following statements shown in bold immediately after the statement that creates the proxy object. Replace the value “LON-DEV-01” specified in the Domain property with the name of your computer:

6.  ProductsServiceClient proxy = new

  1. ProductsServiceClient(“NetTcpBinding_IProductsService”);

8.  proxy.ClientCredentials.Windows.ClientCredential.Domain = “LON-DEV-01″;

9.  proxy.ClientCredentials.Windows.ClientCredential.UserName = “Bert”;

10.proxy.ClientCredentials.Windows.ClientCredential.Password = “Pa$$w0rd”;

These statements explicitly set the Windows credentials for the user to those of Bert. The WCF runtime on the client will send these credentials to the service, rather than using those in the user’s login process.

  1. Start the solution again, without debugging.
  2. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

This time, Bert is a member of the WarehouseStaff role and is granted access to the ListProducts, GetProduct, and CurrentStockLevel operations.

  1. When the ListProducts method runs, it displays the message box confirming that the identity of the authenticated user is Bert. Click OK to continue execution. The first three tests run successfully, but when the client application attempts to perform test 4, which requires invoking the ChangeStockLevel operation, Bert has not been granted access to this method, and so the test fails with the “Access is denied” message:

  1. Press Enter to close the client console window, and then stop the service and close the ProductsServiceHost form.
  2. Return to the  Program.cs file in the code view window.
  3. In the Main method, change the Windows username of the user to Fred, like this:

17.proxy.ClientCredentials.Windows.ClientCredential.Domain = “LON-DEV-01″;

18.proxy.ClientCredentials.Windows.ClientCredential.UserName = “Fred”;

proxy.ClientCredentials.Windows.ClientCredential.Password = “Pa$$w0rd”;

  1. Build and start the solution again without debugging.
  2. In the ProductsServiceHost form, click Start. In the client console window, press Enter.

Fred is a member of the WarehouseStaff role and the StockControllers role, and so he is able to invoke all the operations in the ProductsService service.

  1. When the ListProducts method displays the message box with the name of the authenticated user, verify that the username is Fred and then click OK.
  2. The client application performs all four tests successfully. Press Enter to close the client console window, and then stop the service and close the ProductsServiceHost form.

Using Impersonation to Access Resources

Authenticating a user establishes the identity of the user to the WCF service, which can then perform authorization checks to verify that the user should be allowed to perform the requested operation. The method that implements the operation might require access to resources on the computer running the WCF service. By default, the service will attempt to gain access to these resources by using its own credentials. For example, when a method in the ProductsService service connects to the AdventureWorks database, it does so as the account running the service. When using Windows authentication, it is possible to specify that the WCF service should access resources by using the authenticated identity of the user instead. So, if Fred has been granted access to the AdventureWorks database, the WCF service can connect to SQL Server as Fred and will have access to all the database resources to which Fred has been granted access. If the user connects as Bert, the WCF service might be able to use a different set of resources in the database, depending on Bert’s access rights. The same principle applies to other resources, such as files, folders, and network shares. Using impersonation gives an administrator fine-grained control over the ability of a WCF service to read or write possibly sensitive information and can provide an additional degree of security–just because the user can connect to the WCF service, they might not be able to perform operations that retrieve or modify confidential data unless the administrator has explicitly granted the user access to this data.

You can enable impersonation for an operation by setting the Impersonation property of the OperationBehavior attribute, like this (shown in bold):

[PrincipalPermission(SecurityAction.Demand, Role="WarehouseStaff")]

[OperationBehavior(Impersonation=ImpersonationLevel.Required)]

public List<string> ListProducts

{

}

Specifying the value ImpersonationLevel.Required enforces impersonation. The client application must also agree to this requirement and specify the level of impersonation that the WCF service application can use (you will see how to do this shortly). You can also specify the ImpersonationLevel.Allowed, which enables the WCF service to impersonate the user if the client application permits, but executes as the identity running the service application if not, and ImpersonationLevel.NotAllowed, which disables impersonation.

If you need to specify an impersonation level setting for all operations, you can set the ImpersonateCallerForAllOperations attribute of the <serviceBehavior> element of the service behavior to true in the service configuration file, as shown in bold below:

<?xml version=”1.0″ encoding=”utf-8″ ?>

<configuration>

<system.serviceModel>

<services>

<service behaviorConfiguration=”ProductsBehavior” name=”Products.ProductsServiceImpl”>

</services>

<behaviors>

<serviceBehaviors>

<behavior name=”ProductsBehavior”>

<serviceAuthorization principalPermissionMode=”UseWindowsGroups”

impersonateCallerForAllOperations=”false” />

</behavior>

</serviceBehaviors>

</behaviors>

</system.serviceModel>

</configuration>

You configure the client application to indicate the level of impersonation that the service can use by defining a behavior for the endpoint and specifying the AllowedImpersonationLevel property. The following fragments of a client configuration file highlight the pertinent elements:

<?xml version=”1.0″ encoding=”utf-8″ ?>

<configuration>

<system.serviceModel>

<behaviors>

<endpointBehaviors>

<behavior name=”ImpersonationBehavior”>

<clientCredentials>

<windows allowedImpersonationLevel=”Impersonation” />

</clientCredentials>

</behavior>

</endpointBehaviors>

</behaviors>

<client>

<endpoint

address=”http://localhost:8010/ProductsService/ProductsService.svc”

behaviorConfiguration=”ImpersonationBehavior”

binding=”wsHttpBinding”

contract=”ProductsClient.ProductsService.IProductsService”

name=”WSHttpBinding_IProductsService” />

</client>

</system.serviceModel>

</configuration>

You can specify one of the following values for the AllowedImpersonationLevel property:

  • Impersonate. The service can use the user’s identity when accessing local resources on the computer hosting the service. However, the service cannot access resources on remote computers.
  • Delegation. The service can use the user’s identity when accessing local resources on the computer hosting the service and on remote computers. The service can pass the identity of the user on to remote services, which may authenticate the user and perform operations impersonating this user.
  • Identify. The service can use the user’s credentials to authenticate the user and authorize access to operations but cannot impersonate the user.
  • Anonymous. The service does not use the user’s identity to authenticate the user but can use the user’s credentials to perform access checks against resources accessed by the service. This setting is only valid for transport mechanisms such as named pipes that connect a client application to a service executing on the same computer. If the service is running on a remote computer, the setting is handled in the same way as the “Identify” option.
  • None. The service does not attempt to impersonate the user.
| Leave a comment