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).
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):
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).
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:
This is accomplished by the following additions built on top of v1:
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.
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.
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()
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>
14: <behavior name="rssBehavior">
15: <syndication version="Rss20"/>
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"><b>Conversations - Microsoft Visual Studio</b></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)
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: }
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"
4: contract="Sample.IGetCustomers" />
5: </service>
Now the code for the interface:
1: public interface IRestaurantOrdersService
3: [OperationContract(Name="GetOrdersByRestaurant")]
4: [HttpTransferContract(Method = "GET")]
5: CustomerOrder[] GetOrdersByRestaurant();
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.
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.
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.
So, what now?
There are a few common questions I usually get when I talk about workflow:
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.
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:
Download the content and let us know what you think!
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
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
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:
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!