Tuesday, 31 May 2011

Handling Events with the Microsoft Reactive Extensions

The Microsoft Reactive Extensions (RX) are a library of methods and types that extend the LINQ standard query operators to encompass event-based data sources and asynchronous operations. RX extends the ability of LINQ to handle dynamic observable collections.

In the traditional LINQ model, you define an enumerable collection of objects, and then iterate over that collection and process each item in turn. The collection that you iterate over must provide a means of enumerating elements in that collection, and so it commonly implements the IEnumerable interface (either directly or indirectly, possibly via the IQueryable interface). The IEnumerable interface defines the GetEnumerator method which returns an IEnumerator object. This object actually does the work of retrieving elements from the collection, providing a property called Current which returns the current item from the collection, and a method named MoveNext which is used to move on to the next item in the collection (returning true if there is such an item, or false if there are no more items). LINQ enables you to write code that looks like this, where customers is an enumerable collection of customer objects:
var customersAgedOver30 = from cust in customers
where cust.Age > 30
select cust;

foreach (var customer in customersAgedOver30)
{
ProcessCustomer(customer);
}

This much is “old hat”, and most .NET Framework developers are familiar with this model. However, the scheme specified by implementing the IEnumerable interface is focused on explicitly pulling data, on-demand, from the data source. If there is no data left, the MoveNext method of the enumerator returns false, and the application processing the data assumes that that is no more data to fetch so it stops trying to retrieve any more.

RX takes the view that not all collections match this behavior. Instead, RX enables you to define an observable collection. An observable collection is a dynamic set containing a potentially infinite number of elements; new elements may be added to the collection at any time. If you want to examine the data in this collection, then merely attempting to enumerate the elements that it contains is no longer an appropriate strategy (enumerating an infinite collection will take a very long time!). The Observer pattern provides an ideal solution to this problem, based on pushing data out to parties that are interested in it. This pattern has been around for years, and is well-documented by Gamma et al in their Design Patterns book.

The Observer pattern defines two types of entity: subjects that expose data, and observers that need to know when this data changes. A subject provides a means to enable observers to register their interest, and then notifies these observers when data is updated. In the past, the .NET Framework has supported the Observer pattern through the ObservableCollection class, but RX enables a more generalized implementation through the Observer and Notification types, together with a number of extension methods that make the functionality of these types accessible through LINQ. Using RX, you can easily convert an enumerable collection into an observable one simply by applying the ToObservable extension method, and then you can create an observer by using the Subscribe method of the observable collection; this method expects you to provide a delegate to a method that runs as each element in the collection is observed.

In its simplest form, you might simply consider RX as a simple recasting of code to iterate through enumerable collections. However, the real power of RX lies in being able to apply LINQ semantics to data that was previously non-enumerable. Consider a device capturing data such as the locations and magnitude of seismic waves caused by an earthquake and raising an event each time a new shock was detected. If you were writing a Windows program to capture and process this data, you would typically add a handler that listens to the corresponding events emitted by the device with code similar to this:

EventDataSource earthQuakeDataSource = new EventDataSource();
...
earthQuakeDataSource.EarthquakeDetected += (source, eventArgs) => ProcessData(eventArgs);


Now suppose that you wanted to filter the data so that it only detected earthquakes of magnitude 5 or more. You might amend the code in this way.

earthQuakeDataSource.EarthquakeDetected += source, eventArgs) =>
{
if (eventArgs.Magntitude >= 5)
ProcessData(eventArgs);
};

Additionally, consider what you might need to do if the eventArgs object contains a lot of information that is superfluous to the ProcessData method, and that you only want to pass the data in the Location property (specifying the coordinates of the epicenter of the earthquake) of this object to the ProcessData method:

earthQuakeDataSource.EarthquakeDetected += (source, eventArgs) =>
{
if (eventArgs.Magntitude >= 5)
ProcessData(eventArgs.Location);
};

Each of these coding changes is arguably quite small, but each one starts to obscure the information that you are passing to the ProcessData method. As you add more conditions (for example, suppose you wanted to refine the data further and only capture the details of earthquakes recorded in Alaska), the code could quickly become much more complicated. If you need to change the magnitude and location requirements at a later date, you could quite easily miss the code that implements them.

If you think about it, what you are actually doing is applying a predicate to filter the data, and then performing a projection operation. This is exactly the sort of thing that LINQ is good at with its where and select operators. However, events are not an enumerable data source, and applying LINQ to them was quite tricky. RX fixes this.

With RX you can observe events using the static FromEventPattern method of the Observable class. This is a generic method that takes the event source and the name of the event as arguments. You can then subscribe to this observable collection and arrange for a piece of code to be run to be run each time a new event is detected, as follows.

var earthquakeEvents = Observable.FromEventPattern<QuakeEventArgs>(earthQuakeDataSource, "QuakeDetected");

var subscription = earthquakeEvents.Subscribe(args => ProcessData(args.EventArgs.Location));

Note: Although it exhibits some collection behavior, the earthquakeEvents variable is not really a true collection; the data defined for each event is not retained in any form of queryable structure, and once the corresponding notification to call the ProcessData method has been fired the data that defines the event is discarded.

The Observable class provides extension methods that enable you to apply LINQ operators, so to filter and project the earthquake event data as specified earlier you can simply add the appropriate where and select clauses:

var earthquakeEvents = from evt in Observable.FromEventPattern<QuakeEventArgs>(earthQuakeDataSource, "QuakeDetected")
where evt.Magnitude >= 5
select evt.EventArgs.Location;

var subscription = earthquakeEvents.Subscribe(args => ProcessData(args));

At first glance it might seem that the FromEventPattern really does little more than provide an alternative syntax for handling events, but as soon as you adopt this approach you can quickly start to gain from many of the other benefits that RX provides. To extend the earthquake device scenario, suppose that you wanted to stop monitoring for earthquake events if the user pressed the Escape key on the keyboard. In the traditional approach, you might add another event handler to listen for keyboard events, filter these events to determine whether the user had pressed the Escape key, and then unsubscribe the earthquakeDataSource from the EarthquakeDetected event. You can achieve the same results with RX by observing the KeyDown event, and then applying the TakeUntil method to combine the two event observations together, as follows:
var earthquakeEvents = from evt in Observable.FromEventPattern<QuakeEventArgs>(earthQuakeDataSource, "QuakeDetected")
where evt.Magnitude >= 5
select evt.EventArgs.Location;

var escapeKeyPressed = from key in Observable.FromEventPattern<KeyEventArgs>(this, "KeyDown")
where key.EventArgs.Key == Key.Escape
select key;

var dataUntilEscPressed = earthquakeEvents.TakeUntil(escapeKeyPressed);

var subscription = dataUntilEscPressed.Subscribe(args => ProcessData(args));

The TakeUntil method causes the subscription to the first observable event to be canceled if an instance of the event defined by its parameter occurs.

Using RX to subscribe events enables you to separate the code that handles the events from the definitions of those events, leading to more easily readable and maintainable code. Additionally, the ability that RX provides for composing and combining events together makes for a very elegant solution to many common event-handling problems.

Friday, 20 May 2011

SQL Server in the Private Cloud

Damadi Komo's session from TechEd discusses how to implement a virtualized private cloud solution for database servers. The demo scenario for the session was designed and developed by Content Master - watch out for future posts discussing the demo infrastructure and how we created it!

Wednesday, 18 May 2011

Implementing Customizable Claims-Based Authorization with Windows Identity Foundation

Windows Identity Foundation (WIF) provides the basis for adding claims-based authentication to your Web services (and also to Web applications). It achieves this by adding the necessary plumbing and configuration to your solutions that enable them to interact with a Security Token Service (STS), following the WS-Federation specification. The Windows Identity Foundation SDK includes utilities and assemblies that developers can employ for integrating an STS into a solution, and it also provides a wizard for Visual Studio 2010 that can automate many of the tasks associated with using an STS, including building a simple STS for testing purposes.

The key rationale behind using an STS is to decouple the authentication mechanism from the Web service that requires users to be authenticated. By following the WS-Federation protocol, a Web service can detect whether a user’s session has been authenticated, and if not it can transparently redirect the user’s request via an STS to perform the necessary authentication processing. How the STS actually authenticates the user is up to the STS and is essentially of little concern to the Web service. When authentication is complete, the STS directs the user’s request back to the Web service, but adds a security token to the request that contains information about the identity of the user. The Web service can then examine this token to determine whether or not to authorize access. Now, although the mechanics of the authentication mechanism are of minimal interest to the Web service, determining the privileges of an authenticated user definitely is an important issue.

If you are using WIF, the information in the security token is passed to the code in the Web service that implements each operation via the static Thread.CurrentPrincipal.Identity property. This property is a Microsoft.IdentityModel.Claims.IClaimsIdentity object that contains a collection called Claims. Each item in this collection is an authenticated claim concerning the identity of the user. You can iterate through this collection to find the claim that you are interested in and verify that it matches a selected value before allowing the operation to continue. For example, if you wish to ensure that only users who reside in a particular country can perform the operation, you can check the Claims collection for the Country claim and verify that the value of this claim is appropriate; if not, you can throw a SecurityException and deny access to the user. The following code shows an example that restricts the user to being located in the United Kingdom (the ListProducts method implements an operation that retrieves product names from a database and returns them as a list):

public List<string> ListProducts()
{
// Authz without using WIF infrastructure
ClaimsIdentity id = Thread.CurrentPrincipal.Identity as ClaimsIdentity;

Claim countryClaim = (from claim in id.Claims
where claim.ClaimType == ClaimTypes.Country
select claim).Single();

if (String.Compare(countryClaim.Value, "United Kingdom") != 0)
{
throw new SecurityException("Access Denied");
}
...
}
Note: If you have previously implemented claims-based authentication and authorization with WCF by using technologies such as Windows CardSpace, you will have queried the claims that identify the user through the ServiceSecurityContext property of the OperationContext. WIF reverts to the more standardized technique of examining the Identity property of the Thread.CurrentPrincipal property.

However, although this approach is reasonably straightforward and easy to understand, it does suffer from some issues. Primarily, the authorization code is too tightly integrated into the operation, so if the authorization requirements change (such as expanding the list of countries that a valid user can lives in, or you need to authorize users based on a different claim such as their email address or date of birth), then you need to modify this method and rebuild the service. To counter these concerns, WIF enables you to decouple authorization from the code that needs to be authorized; you can implement a custom authorization manager and insert it into the WIF pipeline.

To build a custom authorization manager, you extend the Microsoft.IdentityModel.Claims.ClaimsAuthorizationManager class and override the CheckAccess method. This method takes an AuthorizationContext object as a parameter, which contains the authenticated claims and which also describes the resource being accessed. This resource might be a Web page (in the case of an ASP.NET Web application), or an operation (in the case of a Web service). You provide logic in the body of the CheckAccess method that retrieves the authenticated claims that identify the user and matches them against the resource or operation, returning true if the user should be permitted to access the resource or operation, but returning false to deny access. The key benefit of this approach is that you can supply the authorization manager as a separate assembly, and then configure the Web service to load this assembly at runtime and integrate it into the WIF infrastructure. To do this, you specify the assembly and type information in the claimsAuthorizationManager element in the microsoft.identityModel section of the configuration file. The following example assumes that the authorization manager is called ProductsServiceAuthorizationManager in the ProductsServiceAuthorization assembly:

<microsoft.identityModel>
<service>
...
<claimsAuthorizationManager type="ProductsServiceAuthorization.ProductsServiceAuthorizationManager,ProductsServiceAuthorization" />
...
</service>
</microsoft.identityModel>
This task can be performed by an administrator without requiring that the code for the Web service itself is modified. If the authorization requirements change, a developer can simply provide an updated version of the authorization manager assembly.

Another important advantage of this strategy is that the authorization manager is able to support run-time customization. An administrator can provide custom configuration information which gets passed to the authorization manager object via a constructor when it is initialized. There is no defined XML schema for this information, and it is up to the code in the authorization manager to validate and parse this information using whatever technique is most appropriate. The following configuration shows one possible example scheme (strongly influenced by Vittorio Bertocci in his book “Programming Windows Identity Foundation”). In this example, the Web service exposes operations named ListProducts, GetProduct, CurrentStockLevel, and ChangeStockLevel; all operations require the user to be resident in the United Kingdom, but in addition the ListProducts operation is also available to users in the United States.


<microsoft.identityModel>
<service>
...
<claimsAuthorizationManager type="ProductsServiceAuthorization.ProductsServiceAuthorizationManager,ProductsServiceAuthorization">
<policy operation="http://contentmaster.com/IProductsService/ListProducts">
<claim claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country" country="United Kingdom"/>
</policy>
<policy operation="http://contentmaster.com/IProductsService/ListProducts">
<claim claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country" country="United States"/>
</policy>
<policy operation="http://contentmaster.com/IProductsService/GetProduct">
<claim claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country" country="United Kingdom"/>
</policy>
<policy operation="http://contentmaster.com/IProductsService/CurrentStockLevel">
<claim claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country" country="United Kingdom"/>
</policy>
<policy operation="http://contentmaster.com/IProductsService/ChangeStockLevel">
<claim claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country" country="United Kingdom"/>
</policy>
</claimsAuthorizationManager>
...
</service>
</microsoft.identityModel>
The constructor for the ProductsServiceAuthorizationManager class shown below parses the configuration information provided with the claimsAuthoriationManager element, and uses it to populate a Dictionary object listing each operation and the claims (countries) required to access the operation. When a user attempts to invoke an operation, WIF first authenticates the user by using an STS, and then authorizes the request by calling the CheckAccess method. If this method returns true, then WIF allows the operation to run, otherwise it causes a SecurityAccessDeniedException to be thrown and returned to the client:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.IdentityModel.Claims;
using System.Xml;
using System.IO;

namespace ProductsServiceAuthorization
{
public class ProductsServiceAuthorizationManager : ClaimsAuthorizationManager
{
private static Dictionary<string, List<string>> policy =
new Dictionary<string, List<string>>();

// Parse nodes with the following format and populate the policy Dictionary
// with the details specifying the requirements for each operation
//
// <policy operation="OperationName">
// <claim claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/country" country="CountryName" />
// </policy>
public ProductsServiceAuthorizationManager(object policyConfiguration)
{
try
{
XmlNodeList policyData = policyConfiguration as XmlNodeList;

foreach (XmlNode policyItem in policyData)
{
XmlTextReader policyReader =
new XmlTextReader(new StringReader(policyItem.OuterXml));
policyReader.MoveToContent();
string operationName = policyReader.GetAttribute("operation");

policyReader.Read();
string claimType = policyReader.GetAttribute("claimType");

if (claimType.CompareTo(ClaimTypes.Country) == 0)
{
string countryName = policyReader.GetAttribute("country");
List<string> countries;
if (policy.ContainsKey(operationName))
{
countries = policy[operationName];
}
else
{
countries = new List<string>();
policy[operationName] = countries;
}
countries.Add(countryName);
}
}
}
catch (Exception ex)
{
}
}

// Check the claim provided in the AuthorizationContext,
// and verify that it matches the requirements for the
// operation specified in the Resource property of the AuthorizationContext
public override bool CheckAccess(AuthorizationContext context)
{
bool result = false;
try
{
string requestedOperation = context.Action.First().Value;
if (policy.ContainsKey(requestedOperation))
{
IClaimsIdentity id = context.Principal.Identity
as IClaimsIdentity;

Claim countryClaim = (from claim in id.Claims
where claim.ClaimType == ClaimTypes.Country
select claim).Single();

result = (from country in policy[requestedOperation]
where String.Compare(countryClaim.Value, country) == 0
select country).Count() > 0;
}

return result;
}
catch
{
return false;
}
}
}
}
Note: For clarity, this code performs minimal error checking. If you are writing code for a production environment you should adopt a more robust approach.

WIF provides a very powerful framework for implementing claims-based authentication quickly and easily. Implementing claims-based authorization can be equally straightforward, and the WIF infrastructure enables you to decouple the authorization process from the resources and operations that require it.

Monday, 16 May 2011

List Relationships and Cascading Dropdowns in SharePoint and InfoPath

Cross-posted from Jason Lee's Blog

Here's the situation. I have two lists on a SharePoint 2010 site – let's call them Product Categories and Products. The Products list includes a lookup column that points to the Product Categories list, so users can associate a category with a product. I need to use these lists to provide choices that users can select from within an InfoPath 2010 form. This is how I want the form to work:
  • The user selects a product category from a dropdown list.
  • The form filters the list of products based on the selected category.
  • The user selects a product from the filtered list of products.
This might sound trivial, but it took me a while to work out the nuances and it doesn't seem to be particularly well documented anywhere, so I figured I'd share it. Essentially, InfoPath 2010 includes a new feature that allows you to specify query fields when you connect to a SharePoint list. This allows you to create cascading dropdowns without resorting to custom code, custom data sources or Web services.

Here's a walkthrough of the process. Remember that Product Categories is our "master" list and Products is our "details" list. I'll assume a rudimentary knowledge of InfoPath in that you're familiar with data connections, binding controls to fields and so on.

First, create a secondary data connection to the Product Categories list. This is straightforward, the list only contains one field. Ensure that you leave the Automatically retrieve data when form is opened option selected.


Next, create a data connection to the Products list. When you select the fields you want to include, ensure you select the Category (lookup) field as well as the Product field.


On the last page of the wizard, ensure you clear the Automatically retrieve data when form is opened option, and then click Finish. We don't want the form to retrieve a list of products until we've specified the category value we want to use as a filter.


Build your form template. I've used dropdown lists to represent the product category and the product. Both controls are bound to simple text fields in the main data source.



In the properties for the Product Category control, configure the dropdown to retrieve choices from the Product Categories data source that you created in step 1.


Ensure that you select the ID column as the Value field. (Lookup columns only store the ID field from the related list, so we'll need to match these ID values to the category lookup in the Products list).

In the properties for the Products control, configure the dropdown to retrieve choices from the Products data source that you created in step 2. (Note that the data source is actually called PLC Products in my screen captures.)



At this point, the controls are set up to:
  • Retrieve choices from our SharePoint lists.
  • Store the user selections in the main data source.
We can now use InfoPath rules to set up the cascade filtering we're looking for. Select the Category control. On the Home tab, on the Add Rule dropdown, click This Field Changes, and then click Set a Field's Value. This launches the Rule Details dialog.

Click the button to the right of the Field text box. In the Select a Field or Group dialog, select the Products data connection, expand queryFields, select the Category field, and then click OK.



By setting the value of this field, we are configuring the Products data connection to only return product records where the product category matches our specified value.

Click the function button to the right of the Value text box, and then click Insert Field or Group. Ensure the Main data connection is selected, select the field that stores the product category value selected by the user, and then click OK.



We have now set the value of our query field to the ID of the category selected by the user. The Rule Details dialog should resemble the following.


Click OK to close the Rule Details dialog. Now that we've set our query field, we can call on the Products data connection to populate the Products dropdown list. In the Rules pane, on the Add dropdown, click Query for data.


Under Data connection, select Products, and then click OK.


Now, when the user selects a category from the Product Category dropdown, the products list is automatically restricted to those products with a matching category value. It's easy once you know how…


If I could emphasise one key point, it's this... ensure you set the value of your query field before you retrieve the data :-)