Aug 022012
 

Introduction

Recently, I started building up a WCF Service Application from scratch to implement a specific set of operations from an existing WSDL.

This was a little cumbersome, but gave me an excellent opportunity to extend and play around with a concept I’ve been trying to perfect for a couple of years now.  In a nutshell, what I wanted was the ability to just focus on implementing the specific functionality of a Web Service operation, yet reuse common validation, logging and exception handling.

This required each web service to inherit from a common base class.  Each request is a class which inherits from a base class also (containing properties which are required for every request).

Class Object View

Let’s take a look at my web service:

image

As you can see, the FormsManager class derives from the obviously named ServiceBase.  Now, as I stated previously, my intention was to move as much “common functionality” into the base as possible.  To do this, let’s take a look at one of the operations:

A Sample Web Service Operation

/// 
/// Submit a form (i.e. lodge a form)
/// 
/// 
/// 
public SubmitFormResponse SubmitForm(SubmitFormRequest request)
{
    return base.ExecuteRequest<SubmitFormRequest, SubmitFormResponse>
	(request, delegate
    {
        AuthoriseAccountId(request.AccountId, request.FormType, 
				FormTypeAuthorisationEnum.Submit);

        if (!String.IsNullOrEmpty(request.ReferenceId))
        {
            AuthoriseAccountId(request.AccountId, 
				request.ReferenceId, 
				FormAuthorisationEnum.Manage);
        }
     
        FormsProvider.SubmitForm(request);

        SubmitFormResponse response = new SubmitFormResponse();
        response.Reference = request.ReferenceId;
        return response;
    });
}

In this scenario, SubmitFormRequest inherits from RequestBase and SubmitFormResponse inherits from ResponseBase.  This will make more sense in the next block of code.

As you can see, this operation only has to worry about implementing functionality specific to it’s requirements – common validation, exception handling and logging can be moved into the ‘ExecuteRequest’ function in the base class like so:

The Base Class

        
/// 
/// Execute a Request where the delegate returns a value
/// 
/// 
protected Z ExecuteRequest<T, Z>(T request, Func<Z> operation)
    where T : RequestBase
    where Z : ResponseBase 
{
    try
    {
        TraceLogger.Log.Trace(
		String.Format("Execute Request: {0}", 
				TraceHelper.GetPreviousMethod()));

        if (request == null)
        {
            throw new 
	    ArgumentNullException("Specified Request Parameter was NULL");
        }
        if (String.IsNullOrEmpty(request.AccountId))
        {
            throw new 
            RequiredArgumentException("Account ID was not specified");
        }

        // Validate the identity of the request
        ValidateAccountId(request);

        return operation();
    }
    catch (Exception ex)
    {
         //Log the exception
        if (ex is ICustomException)
        {
            throw ex;
        }
        throw ex; //TODO: Sanitise the Exception
    }
}

This is still a work in progress, but what it does demonstrate is how to embed a consistent and reusable set of functionality into a base class (reducing code duplication) and allowing you to add code to each web service operation which is specific to the nature of the operation; without the need to explicitly add try/catch or logging.

How does this work?

We’re making use of the Func<> (and in other base functions where no return value is required, Action<>) delegate functionality.  In this instance, Func<Z> defines a delegate which returns a value of type Z.  In the example here, Z is defined as SubmitFormResponse.

Therefore, the pseudo code for executing a SubmitForm request is as follows:

  • Call base class
  • Try
    • Trace (calling function name)
    • Is Request NULL?
    • Is AccountId Null or Empty?
    • Is AccountId Valid?
    • return Call delegate()
      • Is AccountId Authorised?
      • Is ReferenceId Null or Empty?
      • Is AccountId Authorised to Manage this Reference?
      • SubmitForm
      • Create new SubmitFormResponse
      • return response
  • Catch
  • Log exception
  • Is Custom Exception? (throw)
  • Sanitise Exception (throw)

The try/catch block in the ExecuteRequest implementation will also catch any unhandled exceptions thrown by the delegate.  This gives you the potential for automatic exception management – no more uncaught exceptions thrown back to the caller.  You can also make use of standardised logging as well.

Note that the type restriction on the base class function could easily have been defined as the following:

        
/// 
/// Execute a Request where the delegate returns a value
/// 
/// 
protected Z ExecuteRequest<T, Z>(T request, Func<Z> operation)
    where T : RequestBase
    where Z : class
{

Which would allow the delegate to return any class.  Alternatively, you could remove the restriction altogether if you wanted to return value types as well, for example:

/// 
/// Execute a Request where the delegate returns a value
/// 
/// 
protected Z ExecuteRequest<T, Z>(T request, Func<Z> operation)
    where T : RequestBase

//-------------------------------------------------------------------------

return base.ExecuteRequest<SaveDraftFormRequest, int>(request, delegate
{
    return -1;
});

Should your base class be required to handle a delegate which does not return a value, simply replace Func<> with Action<>.

Summary

What I’ve covered off here is just some simple usages of generics and delegates which may help to improve the maintainability and consistency of your WCF web service operations. 

There are limitations (such as the granularity of properties you would be compelled to put into a base class), but the wins are (IMHO) worth the time to implement.

Perhaps you have designed or implemented something similar? 

Please leave a comment.

Oct 122011
 

Hi All.

Engineering FlowchartI’m debating a new article.

I’m currently debating whether to spend some time documenting an interesting solution to a fairly esoteric scenario.  I’m not sure if it is worth the investment (in my time), so I’m going to throw it open to the community. 

Give me feedback – if you have an interest in seeing this solution, please leave a comment.  The only reason I mention this is because the solution is really quite interesting, and a good lesson in the rarer binding types (and message & transport security) in Windows Communication Foundation (WCF).

Here’s the premise:

We have a .NET 2.0 client (which can not be upgraded to 3.5 or 4.0) which must consume a web service by providing a Web Service Extension (WSE) 3 policy file – which stipulates a separate set of credentials (username/password/domain) for authentication in a downstream legacy system.

Presently, this client calls a series of legacy ASMX services (also .NET 2.0).  However, there is a desire to upgrade these services to WCF (for more widespread use) and so we can take advantages of .NET 4.0 in the service implementation and beyond.  The challenge is to provide the same functionality (policy file attached to the transport) for later authentication. 

The information would be transmitted by HTTPs or via HTTP under a VPN (so, ultimately, encrypted).  This is obviously a fairly intriguing paradigm, made more interesting by the prospect of actually not using the WSE3 policy information for handshake authentication.

The original design, from my understanding, was to make the passing of credentials transparent to the service calls themselves (hence, not passing username, password and domain per service call explicitly).  I could be wrong about that, but in any case this is the scenario we have today.

Here’s where you fit in:

So, I repeat – who’d be interested in seeing the solution?  Please leave a comment to indicate an interest.  Depending on how much interest there is, I’ll put together both a long article and a sample, demonstrative, solution.

Cheers, R

Jun 242011
 

Hi There,

So chances are if you’ve read my subsequent posts, you’ll get the feeling that I’m working with some legacy web service applications.  You’d be right, and the challenge of Web Service Extensions (WSE) 3.0 is figuring out how to upgrade them to WCF (.NET 3.5/4.0) without harming the legacy clients who consume them.  We’ll call it a 1-2 punch combination – update the services, then we can worry about the consuming applications.

However.. there are a few challenges.  As it turns out, you don’t need to wrap WCF services with a WSE web application as I first suspected.  This will work, but it gives you an extra set (of legacy) web services and you don’t really need an extra set of bindings and configuration which could cause you trouble down the stretch.

The solution is somewhat straightforward, in that WCF (in .NET 3.5/4.0) supports WSE 3.0 compatible bindings.  Trouble is, you have to use a custom binding, and it has a tendency to require a secure transport (out of the box) which can throw you.

Here’s what MSDN has to say about using a backwards compatible binding with WCF:

To enable a WCF service to interoperate with WSE 3.0 clients

Define a custom binding for the WCF service.

To specify that the August 2004 version of the WS-Addressing specification is used for message encoding, a custom binding must be created.

  1. Add a child customBinding Element to the <Bindings> of the service’s configuration file.
  2. Specify a name for the binding, by adding a binding element to the customBinding Element and setting the name attribute.
  3. Specify an authentication mode and the version of the WS-Security specifications that are used to secure messages that are compatible with WSE 3.0, by adding a child Security element to the binding element.
    To set the authentication mode, set the authenicationMode attribute of the Security element. An authentication mode is roughly equivalent to a turnkey security assertion in WSE 3.0. The following table maps authentication modes in WCF to turnkey security assertions in WSE 3.0.

    WCF Authentication Mode = WSE 3.0 turnkey security assertion

    AnonymousForCertificate  = anonymousForCertificateSecurity

    Kerberos = kerberosSecurity

    MutualCertificate = mutualCertificate10Security*

    MutualCertificate = mutualCertificate11Security*

    UserNameOverTransport = usernameOverTransportSecurity

    UserNameForCertificate = usernameForCertificateSecurity

    * One of the primary differences between the mutualCertificate10Security and mutualCertificate11Security turnkey security assertions is the version of the WS-Security specification that WSE uses to secure the SOAP messages. For mutualCertificate10Security, WS-Security 1.0 is used, whereas WS-Security 1.1 is used for mutualCertificate11Security. For WCF, the version of the WS-Security specification is specified in the messageSecurityVersion attribute of the Security element.

    To set the version of the WS-Security specification that is used to secure SOAP messages, set the messageSecurityVersion attribute of the Security element. To interoperate with WSE 3.0, set the value of the messageSecurityVersion attribute to WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10.

  4. Specify that the August 2004 version of the WS-Addressing specification is used by WCF by adding a textMessageEncoding element and set the messageVersion to its value to Soap11WSAddressingAugust2004.

    ms730049.note(en-us,VS.90).gifNote: When you are using SOAP 1.2, set the messageVersion attribute to Soap12WSAddressingAugust2004.

  1. Specify that the service uses the custom binding.

    1. Set the binding attribute of the Service Endpoint element to customBinding.
    2. Set the bindingConfiguration attribute of the Service Endpoint element to the value specified in the name attribute of the binding element for the custom binding.

Example:

The following code example specifies that the Service.HelloWorldService uses a custom binding to interoperate with WSE 3.0 clients. The custom binding specifies that the August 2004 version of the WS-Addressing and the WS-Security 1.1 set of specifications are used to encode the exchanged messages. The messages are secured using the AnonymousForCertificate authentication mode.

<configuration>
  <system.serviceModel>
    <services>
      <service 
        behaviorConfiguration="ServiceBehavior" 
        name="Service.HelloWorldService">
        <endpoint binding="customBinding" address=""
          bindingConfiguration="ServiceBinding"
          contract="Service.IHelloWorld"></endpoint>
      </service>
    </services>

    <bindings>
      <customBinding>
        <binding name="ServiceBinding">
          <security authenticationMode="AnonymousForCertificate"
                  messageProtectionOrder="SignBeforeEncrypt"
                  messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                  requireDerivedKeys="false">
          </security>
          <textMessageEncoding messageVersion ="Soap11WSAddressingAugust2004"></textMessageEncoding>
          <httpTransport/>
        </binding>
      </customBinding>
    </bindings>
    <behaviors>
      <behavior name="ServiceBehavior" returnUnknownExceptionsAsFaults="true">
        <serviceCredentials>
          <serviceCertificate findValue="CN=WCFQuickstartServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName"/>
        </serviceCredentials>
      </behavior>
    </behaviors>
  </system.serviceModel>
</configuration>

So after defining your WCF services, instead of using a basicBinding or a wsHttpBinding, all you need to do is define a customBinding, like the one below:

<!– WSE 3 compatible binding –>

      <!– http://msdn.microsoft.com/en-us/library/ms730049%28v=VS.90%29.aspx –>

     
      <customBinding>

        <binding name="customWseBinding"> 
         <security messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"

                    authenticationMode="UserNameOverTransport"

                    allowInsecureTransport="true">

          </security>

          <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />

         <httpTransport authenticationScheme="Anonymous" />          
        </binding>     
      </customBinding>

Now, assuming all your other settings are set correctly, you might get excited when the page.. almost.. loads:

image

However, what is this?

Error: Security policy export failed. The binding contains a TransportSecurityBindingElement but no transport binding element that implements ITransportTokenAssertionProvider. Policy export for such a binding is not supported. Make sure the transport binding element in the binding implements the ITransportTokenAssertionProvider interface. ----> System.InvalidOperationException: Security policy export failed. The binding contains a TransportSecurityBindingElement but no transport binding element that implements ITransportTokenAssertionProvider. Policy export for such a binding is not supported. Make sure the transport binding element in the binding implements the ITransportTokenAssertionProvider interface.

Not what we were expecting?  Basically, httpTransport doesn’t implement the ITransportTokenAssertionProvider which is what is being expected by the customBinding.  To work around this you have to, unfortunately, implement your own custom transport.  It’s nasty, but it works.

To take a look at the classes you’ll need, please read this article or this article.

After implementing the custom handler, the binding looks like this:

<customBinding>

        <binding name="customWseBinding">

          <security messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"

                    authenticationMode="UserNameOverTransport"

                    allowInsecureTransport="true">

          </security>

          <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />

          <!–<httpTransport authenticationScheme="Anonymous" />–>

          <CustomHttpTransport authenticationScheme="Anonymous" />

        </binding>     
      </customBinding>

Which results in the following screen:

image

 

References

How to: Configure WCF Services to Interoperate with WSE 3.0 Clients

http://msdn.microsoft.com/en-us/library/ms730049%28v=VS.90%29.aspx

http://social.msdn.microsoft.com/forums/en-US/wcf/thread/ea0ff7b6-12c4-487d-a983-c07e06260acf/

Mar 302011
 

Hi there.

Renamed in the .Net Framework 4.0 from “ADO.net Data Services” to the new – more snappy – “WCF Data Services”, today I’m going to take a closer look at what drives this latest version.  If you look at the release notes there are a number of additions (as well as obviously using the much better Entity Framework v4):

  • Data binding,

  • Counting entities in an entity set,

  • Server-driven paging,

  • Query projections,

  • Custom data service providers,

  • Streaming of binary resources.

To find out what else is new check out What’s New in WCF Data Services.  Also you might want to look at Getting Started with WCF Data Services http://msdn.microsoft.com/en-us/library/cc668810.aspx

To start, I am going to take a look at the server-driven paging since paging has typically been one of those areas of functionality where, if implemented poorly, can really degrade performance of a database or website.

What you’ll need:

  • Visual Studio 2010 Service Pack 1
  • SQL Server 2008 R2 [any edition] with Service Pack 1 – although this should in theory work fine with SQL Server 2005 and 2008.
  • AdventureWorks Sample Database

We’ll be using the old favourite AdventureWorks sample database so that we have some data preloaded.  You can obtain the latest version for SQL Server 2008 R2 from Codeplex at the following location: http://msftdbprodsamples.codeplex.com/releases/view/55926.  The installer does a great job of installing the samples for you, for this article we’re just going to use the OLTP demo database, so you can ignore the others for now.  See the screenshot below, which is how it should look after it is installed (via SSMS):

If you’re not too sure how to go about setting up an Entity Framework data source with AdventureWorks, check out this article from MSDN.com – though please note it is written for use with Visual Studio 2008, not Visual Studio 2010 Service Pack 1: http://blogs.msdn.com/b/adonet/archive/2008/06/18/tutorial-entity-data-source-control.aspx

image image

What we’re going to do is create a new Solution with an ASP.net Web Application.  Once it is created, add a Class Library to the solution and then add a new Entity Framework data model.  I’ve called mine ‘AdventureWorksModel’ as you can see in the screenshot.  Choose to generate it from a database, and select the AdventureWorks2008R2 database.

When I tried to generate the Model, I received the following error message: ‘Unable to generate the model because of the following exception: ‘The table ‘AdventureWorks2008R2.Production.Document’ was referenced by a relationship, but was not found.’

To work around it, I unselected all the tables in the ‘Production’ schema, and just added the remaining tables instead.  I’ll take a look at this error later to see if I can find out where the errant relationship is causing problems.

At any rate, you should now have a half decent model to play with:

image

..moving on.  In your ASP.net Web Application project, make sure you add a reference to the DataAccess class library.  Then, it’s time to create the data service:

  1. In Solution Explorer, right-click the name of your ASP.NET project, and then click Add New Item.

  2. In the Add New Item dialog box, select WCF Data Service.

  3. For the name of the service, type AdventureWorksDataServices.

image

Visual Studio will show you some generated code.  You’ll need to add the name of your Entity Framework Data Context in the definition of the WCF Data Service, like below:

public class AdventureWorksDataServices : DataService<AdventureWorksModelContainer>

In Part 2, we’ll be looking at how to configure the WCF Data Service and then how to use some of the new features. 

Part 2 will be coming soon.

Dec 162010
 

Hello everyone,

Well, I’m back from holidays and about to get my teeth stuck into some more interesting technology.  For the next week, I’ve decided to focus on a concept involving the serving of static (cachable) content – typically straight HTML – combined with AJAX and Windows Communication Foundation (WCF) services using a RESFTful approach.  So far everything has gone according to plan.

WCF has some exciting built-in support for directing REST requests to web service methods and handling formatting both in and outbound.  Combined with some AJAX based user interface, I’m hoping to be able to facilitate a very, very well performing and scalable solution using minimal resources.  As I said earlier.. time will tell.

I’ll also be toying with a few different approaches to data access, I’ll keep the details mum for now until I’ve had a chance to evaluate the performance impact of the designs I’m considering.  So stay tuned.. I know it has been quite a while since the last decent technical entry.. but something decent will be along soon enough!

While I’m putting this together.. I’m still on the hunt for a new opportunity, so if you (or someone you trust) is in the market for decent IT talent, please get in touch.  My operators are standing by.

R