Zulfiqar's weblog

Architecture, security & random .Net

Archive for the ‘WF’ Category

WF Security Pack Update

Posted by zamd on March 13, 2013

Quite a few folks have asked me about updating WF Security Pack to .NET 4.5 as WIF is now integrated into .NET 4.5.

Today I manage to spare sometime to upgrade the WFSP to .NET 4.5/WIF 4.5.  I have also pushed the updated source code to github which you can pull down from https://github.com/zamd/wfsp/

Please note github version of the codebase is different from codeplex, which was refactored by a WF team member. The github version of the source code came straight from laptop. I intend to create a Nuget package and potentially a Visual Studio Extension as well. Stay tuned…

Posted in WF4.5, WFSP | Leave a Comment »

Enabling ‘Import Service Contract’ menu option

Posted by zamd on January 2, 2013

WF 4.5 introduced contact first development using which you can generate messaging activities from your existing WCF contracts. Out of box, this feature is only enabled for ‘WCF Workflow Service Application’ project type and is exposed using the ‘Import Service Contract’ context menu.

image image

This is quite useful feature and is certainly required in other project types as well. For example, a workflow hosted using WorkflowServiceHost in a windows service or a console application. You can easily enable the context menu option for other project types by including an additional GUID in the <ProjectTypeGuids> element in csproj file.

  <ProjectTypeGuids>{32f31d43-81cc-4c15-9de6-3fc5453562b6};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

  • Unload the project in VS and open the csproj file using the xml editor.
  • Locate the <ProjectTypeGuids> element and insert this {349c5851-65df-11da-9384-00065b846f21} as the content of element along with other GUIDs.
  • Make sure to put a semicolon at the end of your newly inserted GUID.
  • Reload the project in VS and you should now see the ‘Import Service Contract’ menu option.

Posted in WF4.5 | Tagged: , , | Leave a Comment »

Duplex communication with .Net 3.5 Workflow Services

Posted by zamd on June 5, 2009

Workflow Services was introduced as part of .Net 3.5 and enables us to use WF workflows as implementation of our WCF services. Workflows are long running by nature so the usual WCF duplex messaging constructs (where correlation between client & server is done based on actual physical connection/socket) are not suitable for most cases. Primarily because it is simply not possible or practical to keep a socket open until workflow finishes its processing (which could potentially take days to produce any meaningful response).

So channel based WCF duplex messaging is not good for long running scenarios. So how can we achieve duplex messaging in long running world?

The general guidance is to use an explicit callback channel (sometime known as “back channel”) for notifications. You can argue that addressability of the client (who may be behind NAT/Firewall) is a real blocker for explicit back channel & I totally agree. However with Relay technologies like .Net Service Bus, reaching to the client endpoints is not an issue anymore hence explicit back channel is much more practical/feasible option now.

Anyways in this post I will show you, how we can achieve durable duplex messaging using Workflow Services. Here is a basic scenario:

Frond end service (orange box) is a long running workflow service – actual service implementation is a WF workflow so it can go idle, persist, sit in the database & brought back into memory if and when needed (all the usual stuff).

Now with above setup if we do usual request-reply messaging – Send activity will simply wait for the reply, workflow will stay in memory & ultimately underlying WCF call will timeout and bad things will happen (workflow might terminate etc).

So first change we have to do is to move the “wait for reply logic” out of the workflow into the host. With this change workflow can go idle, persist and ultimately gets unloaded while host is still listening for the response. On the response, host can bring workflow back into memory and resume the execution.  Important takeaway is that we don’t have to do all this ourselves. Workflow Services & associated “context-exchange protocol” can do most of this for us.

Following is the implementation of front end service…

Dowork is a one-way call. As part of Dowork I’m also passing instanceId of the current workflow along with a callback address (using the standard WS-Addressing ReplyTo header – for protocol purists: this might not be the correct use of ReplyTo header but I’m using it here to keep things simple). So essentially I’m saying “please call me back on this number, when you are done.” J

 Dowork call returns immediately by triggering long running work in the Backend service. Workflow will become idle & can potentially persist.

To override the value of default replyTo header, I have created a simple message inspector.

class ReplyToInspector : IClientMessageInspector

{

    EndpointAddress replyTo;

    public ReplyToInspector(EndpointAddress replyTo)

    {

        this.replyTo = replyTo;

 

    }

    #region IClientMessageInspector Members

 

    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)

    {

       

    }

 

    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)

    {

        request.Headers.ReplyTo = replyTo;

        return null;

    }

 

    #endregion

}

And this can be configured in config file as:

        <endpointBehaviors>

          <behavior name=reply>

            <replyTo address=http://localhost:43211/Callback//>

          </behavior>

        </endpointBehaviors>

Backend service is standard WCF service – doing callbacks using the usual ChannelFactory stuff. The important bit (highlighted) is the explicit context management.

public void Dowork(Guid instanceId)

{

    Console.WriteLine(“Doing long running work…”);

    for (int i = 0; i < 10; i++)

    {

        Console.Write(“…”);

        Thread.Sleep(1000);

    }

    Console.WriteLine();

  

 

    try

    {

        Console.WriteLine(“Sending response…”);

        SendResults(instanceId, OperationContext.Current.IncomingMessageHeaders.ReplyTo);

    }

    catch (Exception exp)

    {

        Console.WriteLine(“Failed: “ + exp.ToString());

    }

}

 

private void SendResults(Guid instanceId, EndpointAddress remoteAddress)

{

    var binding = new BasicHttpContextBinding();

    var cf = new ChannelFactory<IBackendCallback>(binding, remoteAddress);

    var proxy = cf.CreateChannel();

    var cc = proxy as IContextChannel;

 

    using (new OperationContextScope(cc))

    {

        var cmp = new ContextMessageProperty();

        var cm = cc.GetProperty<IContextManager>();

 

        cm.Enabled = false;

        cmp.Context[“instanceId”] = instanceId.ToString();

 

       

        OperationContext.Current.OutgoingMessageProperties.Add(ContextMessageProperty.Name, cmp); 

 

        proxy.LongRunningOperationCompleted(new OperationOutput { Id = 22, Status = “Done..” });

    }

}

In Dowork, I’m passing instanceId as method’s signature however you can easily pass this data as part of context header (remmeber context header is property bag — IDictionary<string,string>)

In the SendResults – I’m creating approparite context header – so that WorflowServiceHost can connect this callback to the correct instance & correct activity inside that instance. WorkflowServiceHost will also load the workflow if it got persisted.

I’m attaching complete solution with this. In next post, I will talk about durable messaging enhancements added in .Net 4.0 Beta 1.

Stay tuned…

 

Download: DurableMessaging.zip

Posted in WF | 1 Comment »

XAML Schema Language

Posted by zamd on November 16, 2008

As mentioned in previous post WF v4.0 is enhanced in many ways and one of those is “Complete workflow/activity authoring in XAML”.

A key enhancement to support this feature is the addition of Schema support in XAML. While  XAML is used to represent objects but there was no way to specify type information in XAML. Schema support provides exactly this functionality using XAML vocabulary. Let’s explore this feature. In the  PDC bits XAML Schema functionality is available in System.XAML.Runtime.dll assembly in (System.Runtime.Xaml.Schema) namespace.

Let’s create a simple type in c#.

public class Employee

{

    public string Email { get; set; }

    public bool SendEmail() { return true; }

    public event EventHandler NewMessage;

}

Now this same type can be created in XAML using XAML Schema language. But here I will use a slightly different approach and will convert above type to its XAML schema representation using following simple code.

static void Main(string[] args)

{

1.  var resolver = new XamlSchemaTypeResolver();

2.  SchemaType st =resolver.GenerateSchemaTypes(Assembly.GetExecutingAssembly()).First();

3.  string xaml = XamlServices.Save(st);

}

What I get back is this:

<p:SchemaType BaseType="p:Object" Name="p1:Employee"

              xmlns:p="http://schemas.microsoft.com/netfx/2008/xaml/schema"

              xmlns:s="clr-namespace:System;assembly=mscorlib"

              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <p:SchemaProperty Name="Email" Type="p:String" />

  <p:SchemaMethod Name="SendEmail">

    <p:Signature ReturnType="p:Boolean" />

  </p:SchemaMethod>

  <p:SchemaEvent Name="NewMessage">

    <p:SchemaEvent.Signature>

      <p:Signature ReturnType="{x:Null}">

        <p:SignatureParameter Direction="In" Name="sender" Type="p:Object" />

        <p:SignatureParameter Direction="In" Name="e" Type="s:EventArgs" />

      </p:Signature>

    </p:SchemaEvent.Signature>

  </p:SchemaEvent>

</p:SchemaType>

 

The SchemaType object on line 2 has an attached property which link it back to the type from which this object was generated.

This exactly same language is used to declare arguments/data flow when defining workflow/activities in XAML. Schema language provided the solution to construct new types in XAML without falling back to code which was one of major hurdle in  the authoring of  XAML only workflows in V1.

 

Posted in WF | Leave a Comment »

What’s new in WF v4.0

Posted by zamd on November 3, 2008

At the PDC .net Framework 4.0 was announced which will be released along with Visual Studio 2010. Along with .Net Framework 4.0, a new version of Windows Workflow Foundation (WF v4.0) will also be released. This version of WF is greatly improved and enhanced compared to the 1st version (released with .net Framework 3.0). These enhancements address performance and scalability issues along with few key customer scenarios (XAML only workflows, transaction flow etc).

Here are some of the highlights of WF v4.0

·         First class support for authoring XAML only workflows.

·         Rich Activity Data Model which eliminates the need for falling back to code.

·         Simplified Activity Authoring: In this new model there are two ways to author activities:

o   WorklfowElement based authoring mechanism: Exposes the richness and breadth of workflow runtime to the activities.

o   Activity based authoring: Enables a declarative activity authoring (primarily by encapsulating other activities as part of activity definition).

·         Several WorkflowRuntime enhancements:

o   Much better support for high frequency dispatch scenarios. This is done by updating the internal scheduler’s machinery.

o   Support for no-persist zones. This is extremely useful and much demanded feature for Asynchronous scenarios.

o   Support for transaction flow into workflow runtime. E.g If when a transaction is flown as part of a WCF call, WF now can use that transaction in its workflow logic.

o   Support for both Text and Binary serialization for the Persistence service. (WCF DataContract Serializer is now used for Serialization).

§  Support for extracting workflow state as part of persistence and store in a query able relational form.

·         Distributed compensation using the WS-BussinessActivity.

·         Partial Trust support

·         Rules are now tightly integrated with activities and are executed in the same way as activities (no more CodeDom statements/expressions).

·         New WPF based workflow and activity designers. (Writing a custom designer is now a breeze – killer GDI+ expertise not needed anymore J)

·         Rich set of new activities (Database access, PowerShell etc)

·         Support of FlowChart workflow type.

·         Programming Model Alignment with WCF. (Support for WCF extension model as a replacement for WF Service Provider/ Service Container).

·         Better integration among WF,WCF & WPF for writing composite application.

·         Support for new enhanced Expression syntax (derived from VB).

·         Dependency Properties are removed and new Activity Data Model is the preferred way to represent state and argument in activities.

·         Plus much more …

All of this goodness come with cost which is: WF 4.0 is not backward compatible with WF 1.0. However WF v4.0 will support side by side execution with WF v1.0 and there will be an Interop activity which will let you execute any WF 1.0 activity inside a WF v4.0 workflow.

In next few weeks I will talk more about these enhancements as I explore so stay tuned …

Posted in WF | Leave a Comment »

Setting UserName ClientCredentials in WF SendActivity

Posted by zamd on June 2, 2008

I was recently asked if there is a way to set custom UserName credentials in a SendActivity. I did some investigation and couldn’t find any OOB way do achieve this. So the next step was to look into WCF’s awesome extensibility mechanism **Bahaviors**. Turns out you can achieve this functionality quite easily by writing a custom endpoint behavior.

Step 1 would be to create a custom endpoint behavior:

public class UserNameBehavior : IEndpointBehavior

{

    #region IEndpointBehavior Members

    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

    {}

    public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

    {

        var cc = endpoint.Behaviors.Find<ClientCredentials>();

        cc.UserName.UserName = “zahmed”;

        cc.UserName.Password = “password”;

    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

    {}

    public void Validate(ServiceEndpoint endpoint)

    {}

    #endregion

}

In the ApplyClientBehavior method, find the appropriate behavior object and override its properties to your desired values. Now you have to specify this behavior in the endpoint configuration of the SendActivity.

To use your custom behavior from config you have to create a BehaviorElementExtension(Step 2)

    public class UserNameBehaviorElement : BehaviorExtensionElement

    {

        protected override object CreateBehavior()

        {

            return new UserNameBehavior();

        }

        public override Type BehaviorType

        {

            get { return typeof(UserNameBehavior); }

        }

    }

Step 3 would be to register your behavior as an extension in the config file:

<extensions>

  <behaviorExtensions>

    <add name=userName type=WorkflowConsoleApplication1.UserNameBehaviorElement, WorkflowConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null/>

  </behaviorExtensions>

</extensions>

At this point your custom behavior is ready to be used in the endpoint configuration used by the SendActivity. Here is the complete config file.

<configuration>

  <system.serviceModel>

    <bindings>

      <basicHttpBinding>

        <binding name=BasicHttpBinding ICalcultor>

          <security mode=Transport>

            <transport clientCredentialType=Basic />

          </security>

        </binding>

      </basicHttpBinding>

    </bindings>

    <client>

      <endpoint address=https://localhost:7000/Calc binding=basicHttpBinding

          bindingConfiguration=BasicHttpBinding ICalcultor contract=ServiceReference1.ICalcultor

          name=BasicHttpBinding ICalcultor behaviorConfiguration=userNameBehavior />

    </client>

    <behaviors>

      <endpointBehaviors>

        <behavior name=userNameBehavior>

          <userName/>

        </behavior>

      </endpointBehaviors>

    </behaviors>

    <extensions>

      <behaviorExtensions>

        <add name=userName type=WorkflowConsoleApplication1.UserNameBehaviorElement, WorkflowConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null/>

      </behaviorExtensions>

    </extensions>

  </system.serviceModel>

</configuration>

Posted in WF | 2 Comments »

ReceiveActivity authorization/security

Posted by zamd on March 25, 2008

ReceieveActivity shipped as part of .net Framework 3.5 enables you to receive data in your workflows by using web services. RecieveActivity also provides a way to enable Role based authorization so you can specify who can send data into your workflows.

By default, RBAC is done against windows principal and you can change this using the serviceAuthorizationBehavior

<serviceAuthorization principalPermissionMode=Custom“/>

There is a small bug in the current UI. If you enter the value in Role field to a “Windows Group” i.e Administrators and leave the Name field blank then everything works fine.

However if you enter a value in the name field say “zuahmed” and click Ok and now come back to this dialog and clear the Name field. Now if you run the application, you will always get an “Access Denied” exception.

 

So what’s happening in the background is:

When you clear the value in the Name field and hit Ok this will set the value of PrincipalPermissionName property to an empty string(“”) rather than a null (the default). Now if you only want to authorize access on group membership, an identity value of null must be used otherwise you will access denied. Currently there is no way to fix this using the UI. You have go into the designer generated code and reset the value of typedoperationinfo1.PrincipalPermissionName = null.

This is now a known issue and will be hopefully fixed in next SP.

Posted in WF | Leave a Comment »