Frank's profileFrank de GrootBlogLists Tools Help

Frank de Groot

Occupation
Location
Interests
I'm a Microsoft .NET software developer.
I also play in a percussion band called Conga Lopes.

Frank de Groot

Developer & Percussionist
January 29

Using F#'s async workflows to invoke a WCF service

In addition to Ted Neward's posts on creating a WCF service in F# I'd like to share a howto on calling a WCF service asynchronously from F# using the infamous async workflows.
 
I'll start off with a simple data contract. This is not required, you could use only primitive type parameters, but I like data contracts. The easiest way is to create a record type. Unfortunately the serializer requires mutable fields, but I can live with that. Please note I'm skipping the open System.Runtime.Serialization and open System.ServiceModel.
 

[<DataContract>]
type public MyRequest = {
    [<DataMember>]
    mutable MyParameter:string;
}

[<DataContract>]

type public MyResult = {
    [<DataMember>]
    mutable MyResultParameter:string;
}

Then I'll define an interface for my service in F#:

[<ServiceContract>]

type public IMyService =
    [<OperationContract>]
    abstract MyOperation: Request:MyRequest -> MyResult

Now to invoke a service asynchronously I need to create a new interface with a slightly different signature. For WCF this new interface is equivalent to the one above, except that it allows asynchronous invocation. Because they need to have the same name I put them in a different assembly so I have one assembly for the contract at the server side and another assembly for the client side. We can reuse the data contract though.

[<ServiceContract>]

type public IMyService =
    [<OperationContract>]
    abstract MyOperation: Request:MyRequest -> MyResult
    [<OperationContract(AsyncPattern =
true)>]
    abstract BeginMyOperation: Request:MyRequest * AsyncCallback * obj -> IAsyncResult
    abstract EndMyOperation: IAsyncResult -> MyResult

Notice the Begin... and End... methods. By adding the AsyncPattern = true to the OperationContract WCF assumes that it's the asynchronous version of MyOperation. As you can see the signature is slightly different: BeginMyOperation expects an additional callback delegate and an optional state object and returns a 'handle' that is passed to EndMyOperation to get the result of invoking MyOperation.

Note that here too I need to supply a name for the first parameter, in this case 'Request'. As Ted described WCF requires a name for the parameters specified in the interface definition. This is common in C# and VB so that's probably the reason why it wasn't noticed by the WCF team. Luckily it's easy to add in F#.

The above code is enough to invoke a service asynchronously. But if we want to use it in async workflows we require another method named AsyncMyOperation. I decided to create an extension method that adds this method to the interface we just created:

module

public Async =
    type IMyService with
    member s.AsyncMyOperation(request) =
        Async.BuildPrimitive(request, s.BeginMyOperation, s.EndMyOperation)

Essentially I'm creating a new method named AsyncMyOperation by calling Async.BuildPrimitive. Async.BuildPrimitive requires the Begin... and End... methods that are common in the .NET Framework for asynchronous operations. It then creates an Async<'a> that we can use in an async workflow. UPDATE: I previously created a local function to capture the request and handed that to Async.BuildPrimitive but I just noticed the overloads of BuildPrimitive that take additional arguments. You can supply up to three arguments. When you need to pass more (unlikely I'd say) you can always create a local function to capture additional arguments.

Mind you, the module name I'm using in the code above really doesn't matter as long as you add an open Async where you want to use it.

Right, now all we need to do is to create the async workflow to actually invoke the service:

let CallMyService =
    async {
        let request = { MyParameter = "Test" }
        use factory = new ChannelFactory<IMyService>(new BasicHttpBinding(), new EndpointAddress("http://localhost:12345/MyService.svc"))
        let channel = factory.CreateChannel()
       
let! result = channel.AsyncMyOperation(request)
        printf "%A" result.MyResultParameter
   
}

Please notice the exclamation mark in let! result = ... If you add a Debug.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString()) before and after the call you'll see that the code below the service call runs on a different thread than the lines above it.

Then, finally, you can run your async workflow with Async.Spawn CallMyService. You can use Async.Run but it would still block to wait for the result so that's probably not what you want.

Well, please let me know if this code works for you or not or any comments and questions you might have.

January 04

Combining WCF and AzMan authorization using EntLib

The code below is a class that authorizes a WCF web service call using EntLib's AzMan authorization provider:

public sealed class AzManAuthorizationManager : ServiceAuthorizationManager
{
    private const string OperationContextPrefix = "O:";

    protected override bool CheckAccessCore(OperationContext operationContext)
    {
        try
        {
            // Obtain the requested action from the context.
            string action = operationContext.RequestContext.RequestMessage.Headers.Action;
            // Remove the namespace part from the action.
            action.Substring(action.LastIndexOf('/') + 1);

            // Get the windows claim set that contains the windows identity
            // and use that to authorize.
            foreach (ClaimSet claimSet in operationContext.ServiceSecurityContext.AuthorizationContext.ClaimSets)
            {
                WindowsClaimSet windowsClaimSet = claimSet as WindowsClaimSet;
                if (windowsClaimSet != null)
                {
                    WindowsPrincipal principal = new WindowsPrincipal(windowsClaimSet.WindowsIdentity);
                    IAuthorizationProvider provider = AuthorizationFactory.GetAuthorizationProvider();
                    return provider.Authorize(principal, OperationContextPrefix + action);
                }
            }
        }
        catch (Exception exception)
        {
            if (ExceptionPolicy.HandleException(exception, "Exception in Security"))
            {
                throw;
            }
        }
        return false;
    }
}

Notes:

  • This won't work with basicHttpBinding, you'll at least have to use wsHttpBinding.
  • I simply remove the namespace portion of the SOAP action. This is because AzMan doesn't allow characters like : and / in an operation name.
  • When calling Authorize prefix operations with "O:". Without prefix it will instead try to find a task of the supplied name.
  • EntLib's WCF Exception Shielding won't work here, any exception is converted to a SecurityAccessDeniedException so you probably want a specific exception policy that also logs the actual exception (which is what I did).

I hope you find this useful, if not let me know!

November 15

Combining Validation and Exception with WCF and EntLib integration

Both WCF/EntLib integration for Validation and Exception handling are cool, but combining them is a bit tricky.

EntLib's Exception handling allows you to send a generic SOAP fault to a client if any Exception occurs within your service. This allows you to hide exception details from the client. Unfortunately a ValidationFault also gets translated to this generic service fault.

The solution: in the EntLib configuration, under your exception policy for your WCF service (usually named "WCF Exception Shielding" add an entry for the System.ServiceModel.FaultException and set it to NotifyRethrow besides catching System.Exception and throwing a custom SOAP fault in its place. The specific exception to rethrow would be FaultException<ValidationFault> but I'm not sure how to configure EntLib for this.

Fortunately the order is not important: the EntLib configuration tool orders the added exception types alphabetically so it automatically puts the FaultException after the generic Exception handler, but it works just the same.

November 09

WCF, EntLib Exception Application Block and SecurityException

Today I tried to handle a SecurityException through EntLib's Exception Application Block. I though it would be useful to rethrow it as a custom type name SecurityFault. Silly me, apparently a SecurityException gets translated to a System.ServiceModel.Security.SecurityAccessDeniedException.

Lessen: don't try this at home (or at work for that matter)...

November 08

WCF & EntLib's Validation Application Block MessageContract Caveat

I've seen some blog entries of people having trouble using VAB in WCF when a web service has a message contract. Apparently any contained DataContracts aren't validated.

After some fidgeting I found the problem: apparently the validation starts at the MessageContract. Just decorate the message body property (decorated with [MessageBody]) with [ObjectValidator].

The ObjectValidator is a validator that allows you to validate properties of a class containing properties decorated with validators. In other words; it allows validation of subtypes.

October 27

Virtual Machine steps

Here's my list of things I do when I create a new virtual machine. Or at least I should do but I generally forget to do at least one of them:
 
* Install CCleaner to remove log files and other junk.
* Disable the annoying beep: net stop beep, sc config beep start= disabled
* Disable shutdown event tracker: gpedit.msc / Computer COnfiguration / Administrative Templates / System / Display Shutdown Event Tracker / Disabled
* Enable Shutdown without logon: Administrative Tools / Local Security Policy / Local Policies / Security Options / Shutdown: Allow system to be shut down without having to log on / Enabled.
* Install TweakUI and enable Logon / Autologon
* Disable screen saver
* Install Bginfo and show the computer name on the desktop.
 
There! Now I should stop forgetting these steps.
 
June 03

Microsoft Popfly

Yay! I've been invited to Microsoft Popfly! Popfly is an experimental site allowing you to build web sites and mash-ups. Especially the way mash-ups can be created interactively is quite stunning.
 
Unfortunately my web site building skills have been in the fridge since some time. At least I have a good sample case, redesigning our percussion band's web site.