• mwinkle.blog

    WCF and WF in "Orcas"

    • 15 Comments

    The wheels of evangelism never stop rolling.  Just a few months ago I was blogging that .NET 3.0 was released.  I've been busy since then, and now I can talk about some of that.  Today, the March CTP of Visual Studio "Orcas" was released to the web.  You can get your fresh hot bits here.  Samples will be coming shortly. Thom has a high level summary here.

    UPDATE: Wendesday, 2/28/2007 @ 11pm.  The readme file is posted here, a few minor corrections have been made to the caveats below.

    More updates... corrections to another caveat (a post-build event is required to get the config to be read).

    A Couple of Minor Caveats

    Since this is a CTP, it's possible that sometimes the wrong bits end up in the right place at the wrong time. Here are a few things to be aware of (not intended to be a comprehensive list):

    • Declarative Rules in Workflows:  There is an issue right now where the .rules file does not get hooked into the build process correctly.
      • Solution: Use code conditions, or load declarative rules for policy activiites using the RulesFromFile activity available at the community site
    • WF Project templates are set to target the wrong version: As a result, trying to add assemblies that are 3.0.0.0 or greater will not be allowed.
      • Solution: Right click the project, select properties, and change the targeted version of the framework to 3.0.0.0 or 3.5.0.0
    • A ServiceHost may not read config settings because the app config does not get copied to the bin (update: only on server 2003):  You will get an exception that "no application endpoints can be found"
      • Add the following Post Build Event "copy “$(ProjectDir)\app.config” $(TargetName).config "
      • Solution: For the time being, configure the WorkflowServiceHost in code (using AddServiceEndpoint() and referencing the WorkflowRuntime property to configure any services on the workflow runtime
      • This also means that a number of the workflow enabled services samples will not work out of the box.  Replace the config based approach with the code based approach and you will be fine.  I will try to post modified versions of these to the community site shortly.
    • WorkflowServiceHost exception on closing: You will get an exception that "Application image file could not be loaded... System.BadImageFormatException:  An attempt was made to load the program with an incorrect format"
      • Solution: Use the typical "These are not the exceptions you are looking for" jedi mind trick.  Catch the exception and move along in your application, as if there is nothing to see here.
    • Tools from the Windows SDK that you've come to know and love, like SvcConfigEditor and SvcTraceViewer are not available on the VPC. 
      • Solution: Copy these in from somewhere else and they will work fine. The SvcConfigEditor will even pick up the new bindings and behaviors to configure the services for some of the new functionality.

    The CTP is not something that is designed for you to go into production with, it's designed to let you explore the technology. There is no go-live license associated with this, it's for you to learn more about the technology. Since most of these issues have some work around, this shouldn't prevent you from checking these things out (because they are some kind of neat).

    New Features In WF and WCF in "Orcas"

    Workflow Enabled Services

    We've been talking about this since we launched at PDC 2005.  There was a session at TechEd 2006 in the US and Beijing that mentioned bits and pieces of this.  One of the key focus areas is the unification of WCF and WF.  Not only have the product teams joined internally, the two technologies are very complementary.  So complementary that everyone usually asks "so how do I use WCF services here?" when I show a workflow demo.  That's fixed now! 

    Workflow enabled services allow two key things:

    • Easily consume WCF services inside of a workflow
    • Expose a workflow as a WCF service

    This is accomplished by the following additions built on top of v1:

    • Messaging Activities (Send and Receive)
      • With designer support to import or create contracts
    • WorkflowServiceHost, a derivation of ServiceHost
    • Behavior extensions that handles message routing and instantiation of workflows exposed via services.
    • Channel extensions for managing conversation context.

     The Send and Receive activites live inside of the workflow that we define.  The cool part of the Receive activity is that we have a contract designer, so you don't have to dive in and create an interface for the contract, you can just specifiy it right on the Receive activity, allowing you a "workflow-first" approach to building services. 

    Once we've built a workflow, we need a place to expose it as a service.  We use the WorkflowServiceHost which is a subclass of ServiceHost in order to host these workflow enabled services.  The WorkflowServiceHost takes care of the nitty-gritty details of managine workflow instances, routing incoming messages to the appropriate workflow and performing security checks as well.  This means that the code required to host a workflow as a WCF service is now reduced to four lines of code or so.  In the sample below, we are not setting the endpoint info in code due to the issue mentioned above.

       1:  WorkflowServiceHost wsh = new WorkflowServiceHost(typeof(MyWorkflow));
       2:  wsh.Open();
       3:  Console.WriteLine("Press <Enter> to Exit");
       4:  Console.ReadLine();
       5:  wsh.Close();

    To support some of the more sophisticated behavior, such as routing messages to a running workflow, we introduce a new channel extension responsible for managing context.  In the simple case, this context just contains the workflowId, but in a more complicated case, it can contain information similar to the correlation token in v1 that allows the message to be delivered to the right activity (think three receives in parallel, all listing on the same operation).  Out of the box there is the wsHttpContextBinding and the netTcpContextBinding which implicitly support the idea of maintaining this context token.  You can also roll your own binding and attach a Context element into the binding definition.

    The Send activity allows the consumption of a service, and relies on configuraiton to detemrine exactly how we will call that service.  If the service we are calling is another workflow, the Send activity and the Receive activity are aware of the context extensions and will take advantage of them. 

    With the Send and Receive actiivty, it gets a lot easier to do workflow to workflow communicaiton, as well as more complicated messaging patterns. 

    Another nice feature of the work that was done to enable this is that we know have the ability to easily support durable services.  These are "normal" WCF services written in code that utilize an infrastructure similar to the workflow persistence store in order to provide a durable storing of state between method calls.

    As you can imagine, I'll be blogging about this a lot more in the future.

    JSON / AJAX Support

    While there has been a lot of focus on the UI side of AJAX, there still remains the task of creating the sources for the UI to consume.  One can return POX (Plain Old Xml) and then manipulate it in the javascript, but that can get messy.  JavaScript Object Notation (JSON) is a compact, text-based serialization of a JavaScript object.  This lets me do something like:

    var stuff = {"foo" : 78, "bar" : "Forty-two"};
    document.write("The meaning of life is " + stuff.bar);

    In WCF, we can now return JSON with a few switches of config.  The following config:

       1:  <service name="CustomerService">
       2:      <endpoint contract="ICustomers"
       3:        binding="webHttpBinding"
       4:        bindingConfiguration="jsonBinding"
       5:        address="" behaviorConfiguration="jsonBehavior" />
       6:  </service>
       7:   
       8:  <webHttpBinding>
       9:          <binding name="jsonBinding" messageEncoding="Json" />
      10:  </webHttpBinding>
      11:   
      12:  <behaviors>
      13:     <endpointBehaviors>
      14:          <behavior name ="jsonBehavior">
      15:            <webScriptEnable />
      16:          </behavior>
      17:      </endpointBehaviors>
      18:   </behaviors>

    will allow a function like this:

       1:  public Customer[] GetCustomers(SearchCriteria criteria)
       2:  {
       3:     // do some work here
       4:     return customerListing;
       5:  }

    to return JSON when called.  In JavaScript, I would then have an instance of a CustomerOrder object to manipulate.  We can also serialize from JavaScript to JSON so this provides a nice way to send parameters to a method.   So, in the above method, we can send in the complex object SearchCriteria from our JavaScript.  There is an extension to the behavior that creates a JavaScript proxy.  So, by referencing /js as the source of the script, you can get IntelliSense in the IDE, and we can call our services directly from our AJAX UI.

    We can also use the JSON support in other languages like Ruby to quickly call our service and manipulate the object that is returned.

    I think that's pretty cool.

    Syndication Support

    While we have the RSS Toolkit in V1, we wanted to make syndication part of the toolset out of the box.  This allows a developer to quickly return a feed from a service.  Think of using this as another way to expose your data for consumption.  We have introduced a SyndicationFeed object that is an abstraction of the idea of a feed that you program against.  We then leave it up to config to determine if that is an ATOM or RSS feed (and, would it be WCF if we didn't give you a way to implement a custom encoding as well?)  So this is cool if you just want to create a simple feed, but it also allows you to create a more complicated feed that has content that is not just plain text.  For instance, the digg feed has information about the submission, the flickr feed has info about the photos.  Your customer feed may want to have an extension that contains the customer info that you will allow your consumers to have access to.  The SyndicationFeed object allows you to create these extensions and then the work of encoding it to the specific format is taken care of for you.  So, let's seem some of that code (note, this is from the samples above):

       1:  public SyndicationFeed GetProcesses()
       2:  {
       3:      Process[] processes = Process.GetProcesses();
       4:   
       5:      //SyndicationFeed also has convenience constructors
       6:      //that take in common elements like Title and Content.
       7:      SyndicationFeed f = new SyndicationFeed();            
       8:   
       9:      //Create a title for the feed
      10:      f.Title = SyndicationContent.CreatePlaintextTextSyndicationContent("Currently running processes");
      11:      f.Links.Add(SyndicationLink.CreateSelfLink(OperationContext.Current.IncomingMessageHeaders.To));
      12:   
      13:      //Create a new RSS/Atom item for each running process
      14:      foreach (Process p in processes)
      15:      {
      16:          //SyndicationItem also has convenience constructors
      17:          //that take in common elements such as Title and Content
      18:          SyndicationItem i = new SyndicationItem();
      19:   
      20:          //Add an item title.
      21:          i.Title = SyndicationContent.CreatePlaintextTextSyndicationContent(p.ProcessName);
      22:   
      23:          //Add some HTML content in the summary
      24:          i.Summary = new TextSyndicationContent(String.Format("<b>{0}</b>", p.MainWindowTitle), TextSyndicationContentKind.Html);
      25:          
      26:          //Add some machine-readable XML in the item content.
      27:          i.Content = SyndicationContent.CreateXmlSyndicationContent(new ProcessData(p));
      28:   
      29:          f.Items.Add(i);
      30:      }
      31:   
      32:      return f;
      33:  }

    And the config associated with this would be:

     

       1:  <system.serviceModel>
       2:    <services>
       3:      <service name="ProcessInfo">
       4:         <endpoint address="rss"
       5:             behaviorConfiguration="rssBehavior" binding="webHttpBinding"
       6:             contract="HelloSyndication.IDiagnosticsService" />
       7:        <endpoint address="atom"
       8:             behaviorConfiguration="atomBehavior" binding="webHttpBinding"
       9:             contract="HelloSyndication.IDiagnosticsService" />    
      10:      </service>
      11:    </services>
      12:    <behaviors>
      13:      <endpointBehaviors>
      14:        <behavior name="rssBehavior">
      15:          <syndication version="Rss20"/>
      16:        </behavior>
      17:        <behavior name="atomBehavior">
      18:          <syndication version="Atom10"/>
      19:        </behavior>
      20:      </endpointBehaviors>
      21:    </behaviors>  
      22:  </system.serviceModel>

    This config will actually create an RSS and an ATOM endpoint.  The feed returned would have the process information embedded as: (in this case in ATOM)

       1:  <entry>
       2:    <id>fe1f1d2e-d676-417d-85bf-b7969dd07661</id>
       3:    <title type="text">devenv</title>
       4:     <summary type="html">&lt;b&gt;Conversations - Microsoft Visual Studio&lt;/b&gt;</summary>
       5:     <content type="text/xml">
       6:       <ProcessData xmlns="http://schemas.datacontract.org/2004/07/HelloSyndication" 
       7:              xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
       8:              <PeakVirtualMemorySize>552157184</PeakVirtualMemorySize>
       9:              <PeakWorkingSetSize>146124800</PeakWorkingSetSize>
      10:              <VirtualMemorySize>456237056</VirtualMemorySize>
      11:        </ProcessData>
      12:     </content>
      13:  </entry>

    We can also use the Syndication support to consume feeds!

       1:  SyndicationFeed feed = new SyndicationFeed();
       2:  feed.Load(new Uri("http://blogs.msdn.com/mwinkle/atom.xml"));
       3:  foreach (SyndicationItem item in feed.Items)
       4:  {
       5:     // process the feed here
       6:  }

    In the case where there have been extensions to the feed, we can access those as the raw XML or we can attempt to deserialize into an object.  This is accomplished in the reverse of the above:

       1:  foreach (SyndicationItem i in feed.Items)
       2:  {
       3:      XmlSyndicationContent content = i.Content as XmlSyndicationContent;
       4:      ProcessData pd = content.ReadContent<ProcessData>();
       5:   
       6:      Console.WriteLine(i.Title.Text);
       7:      Console.WriteLine(pd.ToString());
       8:  }
     

    HTTP Programming Support

    In order to enable both of the above scenarios (Syndication and JSON), there has been work done to create the webHttpBinding to make it easier to do POX and HTTP programming.

    Here's an example of how we can influence this behavior and return POX.  First the config:

       1:  <service name="GetCustomers">
       2:    <endpoint address="pox" 
       3:              binding="webHttpBinding" 
       4:              contract="Sample.IGetCustomers" />
       5:  </service>

    Now the code for the interface:

       1:  public interface IRestaurantOrdersService
       2:  {
       3:     [OperationContract(Name="GetOrdersByRestaurant")]
       4:     [HttpTransferContract(Method = "GET")]  
       5:     CustomerOrder[] GetOrdersByRestaurant();  
       6:  }

    The implementation of this interface does the work to get the CustomerOrder objects (a datacontract defined elsewhere).  And the returned XML is the datacontract serialization of CustomerOrder (omitted here for some brevity).  With parameters this gets more interesting as these are things we can pass in via the query string or via a POST, allowing arbitrary clients that can form URL's and receive XML to consume our services.

    Partial Trust for WCF

    I'm not fully up to date on all of the details here, but there has been some work done to enable some of the WCF functionality to operate in a partial trust environment.  This is especially important for situations where you want to use WCF to expose a service in a hosted situation (like creating a service that generates an rss feed off of some of your data).  I'll follow up with more details on this one later.

    WCF Tooling

    You now get a WCF project template that also includes a self hosting option (similar to the magic Visual Studion ASP.NET hosting).  This means that you can create a WCF project, hit F5 and have your service available.  This is another are where I will follow up later on.

    Wrap Up

    So, what now? 

    • Grab the bits
    • Explore the new features
    • Give  us feedback (through my blog or a channel9 wiki I am putting together now)! What works, doesn't work, what do you like, not like, etc.
    • Look forward to more posts, c9 videos and screencasts on the features in Orcas.
  • mwinkle.blog

    WF, BPEL and the Dark Side of the Moon

    • 0 Comments

    There are a few common questions I usually get when I talk about workflow:

    • That's great, but I can't use SQL Server, can I use foo ?
    • How can I use it to re-unite Pink Floyd for one last tour?
    • What about BPEL support?

    Question 1: Check out the Persistence Service sample in the SDK.

    Question 2:  Man I wish I could say yes, but that's probably a feature that might show up after Orcas if I have my way.

    Question 3: We've done some dancing around this on timelines when it has been brought up in the past, but Paul has the scoop here.  I think this is a great thing for our customers, the support for BPEL not only allows the use of additional process defintion artifacts in the enterprise, but is a great demonstration of the flexibility and extensibility of WF.

    Paul also talks about how this also impacts BPEL in BizTalk Server.

    I'm going to be filming a Channel9 video with the team behind this in the next week or so.  It's Vista Week on Channel9, once that's done I will try to get it posted quickly.

  • mwinkle.blog

    WF, WCF and CardSpace training materials posted

    • 2 Comments

    We've put a fair amount of content out on the community site.  4 days worth of presentations, labs and demos to be specific.  Check it out here.  It's about 50MB worth of downloads, the page shows 11.4kb in errror, that's just the size of the license page.

    The content breaks down like this:

    • Demos
    • Labs
    • Presentations
      • Day 1
        • Overview on the technologies
      • Day 2 - WCF
        • Contracts
        • Bindings and Behaviors
        • Security, Reliability and Consistency
      • Day 3 - WF
        • Custom Activities
        • Hosting
        • Workflow and Communication
        • State Machine Workflows
      • Day 4 - Identity and CardSpace
        • Identity Metasystem
        • CardSpace

    Download the content and let us know what you think!

  • mwinkle.blog

    Mechanical Turk Activities

    • 1 Comments

    Mark Blomsma has put together some activities and an article which shows how to interact with Amazon's Mechanical Turk with WF activities.

    I've linked to the sample on here.

    Cool, cool, cool

  • mwinkle.blog

    DinnerNow, the other thing shipping

    • 3 Comments

    One of the things my team has been working on for the last few months has finally been released.  It started with a discussion in James' office and has come pretty far from there.  You may have seen it at some of the launch events, but unlike a lot of traditional demos, we're releasing all of the code with a great installer that David Aiken wrote in order to make sure all of the moving pieces and parts get put in the right place.

    What is it?

    DinnerNow demo
    DinnerNow demo

    Check out the video on soapbox

    Pieces and Parts, what do you mean by that?

    The only thing we couldn't get into v1 of this thing is the ability for it to flush toilets remotely.  Never fear though, we are working hard to get this into a future release :-)  Here's a list of the technologies that we have in this thing:

    • Vista and Longhorn Server platform API's (things like the transactional file system)
    • IIS 7 modules
    • ASP.NET Ajax extensions
    • Linq
    • Windows Communication Foundation
      • Queued Services using MSMQ
      • "Normal" WS-* web services
      • POX and RSS over WCF
    • Windows Workflow Foundation (bunch of details on this to follow)
      • State Machine and Sequential
      • Correlation
      • Use of the ReplicatorActivity to execute in parallel
      • Designer Rehosting
      • Communication between parent and child workflows
    • Windows Presentation Foundation (even us server guys figured out a way to make it look pretty)
    • Windows Powershell (David's life wouldnt' be complete if it wasn't in there)
      • Powershell commandlets that query the workflow tracking store!
    • Windows CardSpace
    • .NET Compact Framework (because we don't want our mobile folks to feel left out)
    • Incredibly cool installation experience (we worked really hard to make sure all of the above pieces are configured properly)

    Where can I get it?

    Check out the website and you can get the code from codeplex.  If you find something you don't like, file a work item in codeplex, it leads right into our TFS system.

    What now?

    Go, get the code and install it on a Vista or Longhorn Server machine.  Let us know what you think!  We're going to be pushing out some additional information in the upcoming weeks, let us know what you think!

Page 1 of 1 (5 items)