TCP Federation with Windows Identity Foundation

by Chad 25. March 2010 12:00

Windows Identity Foundation (WIF) makes it very easy to build basic federated scenarios. The WIF SDK offers Visual Studio templates for building simple Security Token Services (STS) and Relying Party (RP) services. The SDK also has an excellent help file with information about customizing the basic scenarios.

However, being as new as it is, there isn’t much guidance yet for building your own STSs and RPs from scratch. Also, the deployment and securirty best practices information is difficult to find or non-existent.

Lately, I’ve been researching WIF and discovered that I have a specific scenario that isn’t covered in the guidance. It seems to me that this would be a common scenario, but I was unable to find many resources online that offered help. In fact, I only found one blog post that was useful in solving this problem. You may want to check it out before going through all of the steps in this post.

imageMy scenario included a Claims Aware Relying Party WCF service that that exposed its endpoints over net.tcp bindings. The STS could be accessed through wsHttp endpoints.

I built this scenario but had a really difficult time updating the XML binding configurations for the RP and Client. This post includes my step by step notes for building the scenario described here. I’ve included the source code for download too, but it will NOT work on your computer because you will not have the same certificates or URIs. The steps and source code are provided for demonstration purposes and should not be used in production applications.

WIFSample.zip (99.74 kb)

How To: Implement Federated Security over TCP

The steps below are pasted directly from my OneNote notebook so I have to apologize for the quality – that said, they should be clear enough to follow along. This process creates a functional federated solution, but it is far from being production-ready. I’m sure that there is a more direct way to accomplish this, but I’ve found that this process is a reliable way to build the appropriate bindings for TCP Federation.

**Before you start, you should have installed the WIF SDK (be sure that you’re on a supported OS – Vista or higher) and that you have a good ~30 minutes to finish these steps.

Note: You can click any of these images for a larger version

  1. Open Visual Studio 2008 as an Administrator (this is important because VS will need to create and install certificates in certmgr.msc)
    1. Create a new Blank Solution
    2. clip_image001
    3. In Solution Explorer: Right-click the WIFSample Solution
    4. Create your Relying Party Service (WCF Service Library)
    5. clip_image002
    6. Open the App.config, copy the base address for your RP service
    7. clip_image003
    8. In Solution Explorer: Right-click SampleRP project > Add STS Reference
    9. clip_image004
    10. clip_image005
    11. clip_image006
    12. clip_image007
    13. Right-click SampleRP project > Properties
      1. Choose the debug tab
      2. Remove /client:"WcfTestClient.exe" from the Command line arguments field – it will annoy you.
  2. Create HttpClient Console Application
    1. clip_image008
    2. Right-click HttpClient project > Add Service Reference
    3. clip_image009
    4. Right-click solution > Set startup projects
      1. Set all projects to start with the STS starting first, RP second and Client last
      2. clip_image010
    1. Call the RP Service from your Console Application
    2. clip_image011
    3. Add a reference to System.IdentityModel & Microsoft.IdentityModel to the RP service project
    4. Update Service1's implementation to output the claims identity
    5. clip_image012
  3. Test that the Http Bindings are correct
    1. clip_image013
  4. Add netTcp Binding to RP
    1. Open RP's App.config
    2. clip_image014
    3. Add endpoints for net.tcp bindings
    4. clip_image015
    5. Add the netTcp customBinding (you may want to copy this from the source code.)
    6. clip_image016
    7. And the binding for the STS
    8. clip_image017
    9. Lastly add the net.tcp endpoint to the audienceUris
    10. clip_image018
  5. Test that haven't broken your RP - Run the solution (note that you’re still using http endpoints on the RP)
    1. clip_image019
  6. Lastly, let's add a TcpClient
    1. Right-click solution > Add New Project > Console Application
    2. clip_image020
    3. Right-click TcpClient project > Add Service Reference
    4. clip_image021
    5. Open TcpClient's app.config and comment the http endpoint
    6. clip_image022
    7. Implement the TcpClient
    8. clip_image023
    9. clip_image024
  7. Success
  8. clip_image025

Tags:

WCF | WIF

Large Lists in WPF and WCF – Part Four

by Chad 1. February 2010 06:00

Wrapping Up
This is the final post of this series. In the previous post, I showed you how to add paging to your WCF service’s message contracts. I then showed a strategy for consuming paged results on the client asynchronously. This strategy will increase your end user’s perception of your application’s performance.

In this post, I will show you a client-side abstraction for consuming paged service operations. We’ll create a PagedRequestManager class that can be used to manage the requests of any paged service operation. The responsibility of this class is to keep track of the current page, request the next page, and publish notifications on the UI thread.

IPagedRequest and IPagedResponse
The first step in this process is to have Visual Studio create classes for your message contracts. To do this right-click your service reference and choose Configure Service Reference. In the Data Type section of the Service Reference Settings dialog, check the “Always generate message contracts” option. Visual Studio will now rebuild the proxy classes – this will likely break your client code so you’ll need to correct any build errors at this point.

Now we need to make all of our message contracts implement the same interfaces. For this we create two client-side interfaces: IPagedRequest and IPagedResponse. It’s important to realize that these are purely client-side interfaces who’s implementations simply map the interface properties to the appropriate message contract fields. This keeps the client-side paging requirements separate from the service’s.

public interface IPagedRequest

{

    PagingContext PageInfoState { get; set; }

}

public interface IPagedResponse

{

    PagingContext PageInfoState { get; }

    IEnumerable ResultItems { get; }

}

Below is a sample implementation for a paged response. The proxies generated for us by Visual Studio are partial classes, which enables us to extend them at design-time. To do this, create a new class with the same name (and namespace) as a message contract class and add the partial keyword to the class declaration. We’ll do this for the request and response message contracts for each service operation that supports paging. Notice that the ResultItems property is a loosely-typed IEnumerable; this keeps the interface simple so that it can be applied to responses that return any type of object – not just Foods.

public partial class GetAllFoodsResponse : IPagedResponse

{

    public PagingContext PageInfoState

    {

        get { return PageInfo; }

    }

 

    public System.Collections.IEnumerable ResultItems

    {

        get { return Results; }

    }

}

PagedRequestManager 
Next, we will create a class that knows how to process IPagedRequest and IPagedResponse messages.image I named this class the PagedRequestManager. At the heart of the PagedRequestManger is the AsyncOperationManger. The AsyncOperationManager class is a class that lives in System.ComponentModel (System.dll) and helps you manage concurrency in multithreaded applications. We’ll be using it to reliably dispatch updates from our worker thread back to the UI thread.

PagedRequestManager is a simple class that takes an IPagedRequest and IList. It then executes the request for all pages, adding the results from the paged response to the specified IList. After it’s loaded the last page, it fires an event to notify the UI that the operation has finished. Additionally, it supports cancelling the asynchronous operation at any time.

The sample below shows the paged request loop inside of the PagedRequestManager. This loop executes on a non-UI thread so that the UI isn’t waiting for the response to come back from the service. The asyncOp.Post(…) statement, uses the AsyncOperation class to load the results into the specified IList. The asyncOp object was created by the AsyncOperationManager and is smart enough to execute it’s delegate on the UI thread. This is important because the _asyncProcessResults delegate will add the ResultItems to a user-specified IList. In our example, this WPF list is an ObservableCollection. When the ObservableCollection fires it’s CollectionChanged events, we want to make sure those are fired on the UI thread.

do

{

    IPagedResponse response = client.ExecutePagedRequest(request);

 

    itemCount = response.ResultItems.OfType<object>().Count();

    asyncOp.Post(_asyncProcessResults, new object[]

        {

            response,

            resultsList,

            asyncOp

        });

 

    request.PageInfoState.Skip += itemCount;

    isCancelled = IsCancelled(asyncOp.UserSuppliedState);

} while (!isCancelled

    && request.PageInfoState.IsFullPage(itemCount));

Using the PagedRequestManager
Using the paged request manager is simple. In this example we create a Form-level PagedRequestManager object.

_pageRequestManager = new PagedRequestManager();

_pageRequestManager.ExecutePagedRequestAsyncCompleted += new EventHandler<ExecutePagedRequestAsyncCompletedEventArgs>(_pageRequestManager_ExecutePagedRequestAsyncCompleted);

When the Load Async button is clicked, we cancel any active requests, rebind our list, and execute a new request.

private void LoadWCFAsync_Click( object sender, RoutedEventArgs e)

{

    // Cancel any pending requests

    _pageRequestManager.CancelAsync(_searchTaskId);

 

    // Initialize and bind our ObservableCollection

    _fo odItems = new ObservableCollection<Food>();

    ((ObservableCollection<Food>)_foodItems).CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Window1_CollectionChanged);

    FoodList.ItemsSource = _foodItems;

 

    // Begin a new request

    _searchTaskId = new object();

    StartFirstResultTimer();

    _pageRequestManager.ExecutePagedRequestAsync(

        new GetAllFoodsRequest(new PagingContext() { Skip = 0, Take = 100 })

        , _foodItems, _searchTaskId);

}

Because the PagedRequestManager accepts any IPagedRequest object we can use this exact same pattern to execute a text search.

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)

{

    // Cancel any pending requests

    _pageRequestManager.CancelAsync(_searchTaskId);

 

    // Initialize and bind our ObservableCollection

    _foodItems = new ObservableCollection<Food>();

    FoodList.ItemsSource = _foodItems;

 

    // Begin a new request

    string partialDesc = ((TextBox)sender).Text;

    if (!string.IsNullOrEmpty(partialDesc))

    {

        SearchForFoodRequest request = new SearchForFoodRequest()

        {

            PageInfo = new PagingContext() { Skip = 0, Take = 100 },

            PartialDescription = partialDesc

        };

 

        _searchTaskId = new object();

        _pageRequestManager.ExecutePagedRequestAsync(request, _foodItems, _searchTaskId);

    }

}

About time... 
This has been a lengthy example, but hopefully it illustrates that a little planning upfront can go a long way for improving the end user experience for your application. User’s no longer expect to click and wait – they want instant results or at least a responsive application while they wait for results.

The patterns shown in this series of posts make consuming large lists of data a manageable task. On my local machine, retrieving 7539 food objects synchronously took 0.7 seconds. When paged asynchronously, 100 objects per page, the first 100 results were displayed and useable in 0.03 seconds with the 7539th object displayed 1.6 seconds after the button was clicked. Although the time to display the last object took more that twice as long when paged, the first 100 objects were displayed 23 times faster. These numbers become even more revealing when consuming the service over a network or the internet.

I hope that this series of posts was useful to you and your projects. The source code can be downloaded here.

Tags:

WCF | WPF

Large Lists in WPF and WCF – Part Three

by Chad 25. January 2010 09:37

Paging Your Results
In part one of this series I gave an overview of data binding lists in WPF. In part two, I showed how to asynchronously consume a WCF service so that your WPF user interface remained responsive. In this post, I’m going show an example for paging your results to control the message size and to get results to the client faster.

Let’s Get Started
In the last post, I mentioned that eventually your result set will grow large enough that the default WCF configuration will prevent your message from being received. With the default settings, once the size of the message exceeds ~65K, you will receive this exception:

“The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.”

The simplest fix is to increase the quota for MaxRecievedMessageSize in the client’s service configuration. This is only a temporary fix as eventually your message size may exceed the new limit. To help control the message size, a service should allow the client to page large sets of data.

Update the Service
To enable the client to page data, we need to allow them to specify a record offset and a page size. I prefer the LINQ to SQL terms “Skip” and “Take”. Skip is the zero-based record offset and Take is the maximum number of records per page. An alternative would be to specify a page size and page index, but I prefer the Skip-Take approach because it allows me to dynamically change the page size to control perceived performance.

So the first change to our NutrientDB service is to add a data contract to describe paging context.

[DataContract(Namespace=ServiceConstants.NAMESPACE)]

public class PagingContext

{

    [DataMember]

    public long Skip { get; set; }

    [DataMember]

    public int Take { get; set; }

}

Next we add the PagingContext to our GetAllFoodsRequest.

[MessageContract(WrapperNamespace=ServiceConstants.NAMESPACE)]

public class GetAllFoodsRequest

{

    [MessageBodyMember]

    public PagingContext PageInfo { get; set; }

}

Then we add the PagingContext to GetAllFoodsResponse. This allows a consumer of the service to know which page of results are being returned.

[MessageContract(WrapperNamespace = ServiceConstants.NAMESPACE)]

public class GetAllFoodsResponse

{

    [MessageBodyMember]

    public IEnumerable<Food> Results { get; set; }

    [MessageBodyMember]

    public PagingContext PageInfo { get; set; }

}

And finally, update our service operation to implement the paging.

public GetAllFoodsResponse GetAllFoods(GetAllFoodsRequest request)

{

    if (request == null) { throw new ArgumentNullException("request"); }

 

    PagingContext ctx = request.PageInfo

        ?? new PagingContext() {Skip = 0, Take = int.MaxValue};

 

    return new GetAllFoodsResponse()

    {

       Results = NutrientDataAccess.GetAllFoods(ctx.Skip, ctx.Take),

       PageInfo = ctx

    };

}

Update the Client
In the WPF client project, I right-click my service reference and choose “Update Service Reference”. This will break my existing code since the message contracts for my service changed. I now have to specify a PagingContext to the GetAllFoods methods. Also, I removed the 100 record limit from the database – it now returns the full ~7500 records.

Returning ~7500 Food objects in one request would throw the MaxReceivedMessageSize quota exception mentioned above. To prevent this (without having to update the client service configuration,) I update the client to retrieve all Food objects from the service 100 records at a time. I want to do this asynchronously so that the UI remains responsive.

private void LoadWCFAsync_Click(object sender, RoutedEventArgs e)

{

    NutrientDBClient client = new NutrientDBClient();

    client.GetAllFoodsCompleted +=

        new EventHandler<GetAllFoodsCompletedEventArgs>(

            client_GetAllFoodsCompleted);

 

    // Assign a new ObservableCollection to the ListView;

    // When items are later added to the ObservableCollection,

    // the ListView will automatically display them.

    _foodItems = new ObservableCollection<Food>();

    FoodList.ItemsSource = _foodItems;

 

    // Request the first 100 Food objects

    var pageInfo = new PagingContext() {Skip = 0, Take = 100};

    client.GetAllFoodsAsync(pageInfo);

}

 

void client_GetAllFoodsCompleted(object sender, GetAllFoodsCompletedEventArgs e)

{

    NutrientDBClient client = (NutrientDBClient)sender;

    if (e.Error == null)

    {

        // Use the PagingContext from the response to determine

        // if this is the last page of results

        PagingContext pageInfo = e.Result;

        if (e.Results.Length < pageInfo.Take)

        {

            client.Close();

        }

        else

        {

            // Request the next 100 Food objects asynchronously

            pageInfo.Skip += e.Results.Length;

            client.GetAllFoodsAsync(pageInfo);

        }

 

        // Update the ObservableCollection<Food> that has been

        // data bound to the ItemsSource property of the ListView.

        // Because _foodItems is an ObservableCollection, WPF will

        // automatically update the ListView with the new items.

        foreach (var food in e.Results)

        {

            _foodItems.Add(food);

        }

    }

    else

    {

        MessageBox.Show(e.Error.Message);

        client.Close();

    }

}

image image image

 

 

 

 

Now, instead of waiting for all 7539 records to load before beginning their work, a user can begin to browse the Food items after the first 100 results are returned. I load all pages at once, but this code could be easily modified to only request the next page when the user scrolls near the bottom of the list. Another modification that you might want to make is to request a smaller first page and larger subsequent pages. This would improve the perceived performance since the user will nearly instantly see their first page of results.

Summary
In this post I showed how you can add paging to your services to give clients better control over message size. At the end I touched on how paging can enable you to solve our third problem with large lists - “A noticeable delay to load data will begin to slow your users down.”

In the final post of this series, I will take this example to the next level to show how to abstract the paging logic out of your UI code, making it easily usable from anywhere in your client application.

Source code for this post can be downloaded here.

Tags:

WCF | WPF

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

About the author

Chad

Meeeee!!!

Hi, my name is Chad Boschert and I'm a software developer in Springfield, Missouri. I've been developing .NET applications in C# since 2002.

Recent Comments

Comment RSS

Calendar

<<  May 2013  >>
MoTuWeThFrSaSu
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar