CTP3 Update of the Microsoft Enterprise Service Bus Guidance

Well….the project is humming a long….more cool things we’re doing.  Here’s an email I sent out to some folks in the community


 











Announcing  – August 2007 Community Release (CTP3) of ESB Guidance  – http://www.codeplex.com/esb


By Marty Wasznicky
Field Program Manager, Connected Systems Division



As a result of our ongoing partnership with Patterns & Practices, we’ve released a new August Community (CTP3) build of the ESB Guidance on ESB Guidance community site, where all future iterations will be released until our final release in October later this year. 


 


The CTP3 build introduces some new and augmented features such as:


 


       New Resolver and Adapter Provider Framework provides “messaging” level end point resolution support for


       UDDI


       WS-MetaDataExchange


       Business Rules Engine


       XPath


       STATIC


       Messaging level Transformation services (uses new Resolver Framework).  Allows BizTalk Maps to be executed in pipelines based on the following resolution methods


       UDDI


       WS-MetaDataExchange


       Business Rules Engine


       XPath


       STATIC


       Request-Response support for on and off ramps (partial)


       WCF Adapter integration


       UDDI publishing and query service


       BizTalk runtime query service


       New Dynamic Resolution Sample


       Third party SOA Management and Governance integration:


       SOA Software Integration


       ESB Guidance documentation in CHM format J


 


The August 2007 CTP3 release focuses on the incorporation of Windows Communication Foundation (WCF), Request-Response Messaging, and the introduction of the Resolver and Adapter Provider Framework. The latter provides the runtime resolution and transformation support to enable both one-way and request-response pure messaging scenarios. The former (specifically the BizTalk WCF adapter) makes it all possible. Hence, key to this release, is the continued refactoring and integration into BizTalk Server 2006 R2-scheduled for release in September 2007. Additionally, we are releasing several infrastructure-based services to support our ongoing development work for the ESB Management Portal, as well as for two key SOA Governance partners, Amberpoint and SOA Software.


Our first goal was simply to ship WCF Adapter versions of our existing On-Ramps and Services, so that-over time-we could retire the older ASMX versions. WCF offers many advantages over ASMX, with the separation of interface and implementation being just one. WCF, specifically the WCF Adapter within BizTalk, goes a long way towards providing full Web Service WS* support for customers, without the need to write significant code. The WCF adapter makes WS-Security and WS-AtomicTransactions as easy as enabling a checkbox. More importantly, its loosely typed nature enables the use of true dynamic-resolution Web Services with BizTalk. This removes the requirement for generating and referencing SOAP Proxies compiled into .NET assemblies for routing to every resolved end-point (as was the case prior to the introduction of the BizTalk WCF Adapter).


Our second goal was to develop a robust architecture for high performance yet flexible runtime resolution and transformation at the messaging level, without the need for the existing Orchestration-based services developed in previous releases of the ESB Guidance. This architecture is required to support full Request-Response pure messaging scenarios. It must also support customers who want to develop their own resolution methods and plug them into our architecture, without having to rewrite our existing code.


The result is the Resolver and Adapter Provider Framework, which supports dynamic loading, caching, and invocation of registered Resolvers. The Resolver determines the end-point configuration and URI, given certain facts. The Adapter Providers then set the specific properties of a BizTalk Adapter. Adapter Providers leverage the same dynamic loading, caching and invocation mechanisms as Resolvers. This framework goes a long way towards enabling us to provide simple messaging scenarios, such as “transform-validate-route”, with all the configuration and information externally driven by policy from a registry or custom repository. Our primary goal with the framework was to develop an architecture that could separate the consumer from the service, enabling us to move towards more policy-driven messaging scenarios.


Our third goal was to develop and introduce some comprehensive, Web-based infrastructure services that both our ESB Management Portal and other third parties can query and leverage. The first of these services, the BizTalk Query Service, exposes BizTalk application, service, messaging, and health information. This service provides users with the ability to ask questions such as:


       “What applications are deployed?”


       “Where are they deployed?”


       “What servers are they running on?”


       “Which services are running and which are stopped?”


       “Which host is the service running under?”


       “What server is the host running on?”


       “Is the host started on server B or server A?”


       “Give me a list of the services deployed since 1/1/2007.”


 


The second of the new services, the UDDI Service, supports querying and modifying the registration information stored in UDDI based registries. 


Finally, we pursued the development of tighter integration with key SOA Governance vendors such as Amberpoint and SOA Software. Customers should not be forced to regard these, as well as our, technologies as isolated “black boxes” with one not able to leverage the features and functions of the other. A seamless integration experience, where one leverage the assets of the other, provides greater synergy, reduces complexity, and will lower the total operational cost of the solution. This can provide immediate benefits to our customers. For example:


       SOA Governance tools and analytics can extend, and provide end-to-end visibility and tracking for the BizTalk native messaging subsystem and solutions; providing customers with a “one management view” of the solution.


       BizTalk can enable SOA Governance vendors to become “transport-agnostic”; providing a functional transport bridge, rules, and orchestration technologies for customer solutions.  


       Integration of these technologies can provide centralized enforcement and management of end-points and policy across the entire solution, regardless of the transport or technology (such as WS*, FTP, FILE, MQSeries, JMS, SAP, Tibco, Peoplesoft, or Siebel) it uses.


                                         


We have been working with Amberpoint and SOA Software for several months and are now starting to see the results of our efforts. In fact, SOA Software has almost completed development of their integration code that demonstrates end-to-end SOA governance monitoring and policy enforcement within BizTalk. In this release, we include some of the documentation regarding the new SOA Software Management Point for BizTalk, as well as some screenshots and the URL of their web site where you can obtain more information.


Ultimately, I believe that the team accomplished the goals we set out for this release. We look forward to active feedback from all our users. 


 


A more thorough description and screen shots of the SOA Software integration with BizTalk can be found below.


 


Cheers!


 


 


SOA Governance Integration


Enterprise-level applications must support robust and reliable management features in order to comply with business requirements, Government legislation, service level agreements (SLAs), and customer and trading partner expectations.


The SOA Software Management Point for BizTalk Server 2006 is an extension to SOA Software’s Web Services Management Point, applied specifically to the BizTalk Server 2006 environment, providing run-time governance for any BizTalk application regardless of transport.


The Management Point integrates natively with SOA Software Service Manager and Workbench products. Unlike the typical Web Services Management Point, this implementation is associated with services provided by BizTalk environment, expressed in terms of BizTalk server Receive Locations and Send Ports. Due to the arbitrary nature of Receive and Send Ports (configured against a variety of BizTalk Adapters) these services  are not necessarily associated with Web Services, but can be treated as such in terms of the SOA Service Manager and SOA Workbench.


Figure 1 shows the SOA Service Manager Web application displaying the Workbench page for an example application. The left-hand tree view allows users to navigate through the applications and services installed within BizTalk, while the right-hand pane allows users to view application details, operations, access ports, categories, rules, and monitoring information.


 


 


Figure 1


The SOA Service Manager showing the monitoring features available in the Workbench page


You can monitor all the operations within an application (all Send Ports and Receive Locations), or specific operations, and the Workbench shows a list of the messages passing through the selected Send Ports and Receive Locations. When you double-click on a message in the list, the Workbench displays details of the message, and its context properties (provided that recording is enabled). Alternatively, you can select a specific service and monitor in real time messages passing through that service.


BizTalk Integration


The SOA Service Manager provides Wizards that help you set up the SOA Service Manager for use with BizTalk Server. For example, Figure 2 shows Wizard that helps you install and configure the BizTalk Integration Point that links BizTalk Send Ports and Receive Locations to the SOA Service Manager.


 


 


Figure 2


The SOA BizTalk Integration Point installation and configuration Wizard


After installation, the Service Manager can display details of the Send Ports and Receive locations configured by the Wizard. Figure 3 shows the Operations page displaying the name, interface, policy, and number of virtual operations for three Receive Locations and a Send Port.


 


 


Figure 3


A list of BizTalk Send Ports and Receive Locations displayed by the SOA Service Manager


Monitoring Policies and Usage Information


The SOA Service Manager provides a mechanism that allows you to create and edit monitoring policies. For example, Figure 4 shows the screen for applying a policy template and activating monitoring for an application.


 


 


Figure 4


The SOA Service Manager showing the monitoring features available in the Workbench page


The SOA Service Manager also provides usage information for applications, services, and individual Send Ports and Receive Locations. This information includes charts displaying the relative usage of each operation and usage over time, service usage, and response time information. Figure 5 shows some example.


 


 


Figure 5


A selection of the charts that the SOA Service Manager can generate to assist in monitoring server and application behavior and performance


In addition, SOA Service Manager includes features that allow you to view details of individual messages, including the size, response time, operation name, and the associated SOAP messages, as well as any exceptions that may occur in the BizTalk runtime environment, as shown in Figure 6.


 


 


Figure 6


The SOA Service Manager showing details of an individual message


 


SOA Software Service Manager and Workbench products are products from SOA Software, Inc. that integrate with BizTalk Server 2006. For more details of SOA Software and their products, and to download the latest installation and operational instructions, see http://www.soa.com/


 


 


 


 

BizTalk Map Add-In

BizTalk Map Add-In is a Visual Studio 2005 (professional/team) add-in for BizTalk 2006 developers. It adds two functions to the context menu of map files in the solution explorer:
Debug BizTalk Map XSLT Generate the Xslt for a map and start debugging it. This command honours extension objects, it is possible to use and debug external […]

PipelineTesting 1.1 Released

PipelineTesting 1.1 Released

I’m please to announce the release of Version 1.1 of my PipelineTesting library for
BizTalk Server 2006. PipelineTesting can be used with your favorite unit testing
framework to create automated, repeatable tests for the following BizTalk artifacts:

  • Custom Pipeline Components
  • Custom Pipelines
  • XML and Flat File Schemas

Version 1.1 adds the following features:

  • Improved XML documentation (it actually builds the XML documents without warnings!)
  • Bug fixes
  • A new, streamlined and more intuitive API, which also includes wrappers for easy configuration
    of standard XML and Flat File assembler and disassembler components. The original
    API is still available, for backwards compatibility.

As usual, the library can be downloaded here.
The package includes all source code for the library itself and its unit tests, and a
pre-compiled binary and XML doc comments file.

Using the library

To use the library, you need to reference the following assemblies:

  • Winterdom.BizTalk.PipelineTesting.dll
  • Microsoft.BizTalk.Pipeline.dll
  • Microsoft.BizTalk.Pipeline.Components.dll

You will need to include the following namespaces:

using Winterdom.BizTalk.PipelineTesting; using Winterdom.BizTalk.PipelineTesting.Simple;

Introduction to the API

I won’t cover all the API, however, let me introduce the basic mechanics of how the
library can be used.

The general way in which the library is used is:

  1. Create a send or receive pipeline. Pipelines are represented in the API as instances
    of either the ReceivePipelineWrapper or SendPipelineWrapper classes.

    PipelineTesting provides ways to create an instance of a pre-compiled BizTalk pipeline
    (including the built-in pipelines in BizTalk), or creating an empty pipeline.
  2. Configure the pipeline, by adding any components you require (if needed) in the proper
    stages of the pipeline, as well as providing it with any document specifications (schemas)
    that will be required by assembler or disassembler components in the pipelines.

    This allows the library to run completely independent of your BizTalk configuration,
    so you don’t even need to deploy your stuff to the server before taking advantage
    of the library; providing a very quick feedback cycle!
  3. Create input messages to provide to the library. You can create messages with any
    shape or characteristics that BizTalk allows, such as multi-part messages, adding
    context properties and so on.
  4. Execute the pipeline: Just pass in the input messages and validate the resulting messages!

Example: A simple XML Send Pipeline

The following example shows how to create a standard XMLTransmit pipeline, provide
a schema to use and execute the pipeline with an input message:

string msgBody = "...";
SendPipelineWrapper pipeline = Pipelines.Xml.Send() .WithSpec<Schema1_NPP>();
IBaseMessage output = pipeline.Execute( MessageHelper.CreateFromString(msgBody) ); 

Example: Batching messages in a Send Pipeline

Here’s a more interesting test for a send pipeline. This one will create an empty
Send pipeline, add a standard XML Assembler component to it, configured with an Envelope
and a Document schema and then feed multiple input messages to be assembled into a
single one, encoded with S/MIME:

XmlAssembler xml = XmlAssembler.Xml()
   .WithDocumentSpec<SimpleBody>()
   .WithEnvelopeSpec<SimpleEnv>();
SendPipelineWrapper pipeline = Pipelines.Send()
   .WithAssembler(xml)
   .WithEncoder(new MIME_SMIME_Encoder()); //
Create the input message to pass through the pipeline string body
= @"<o:Body xmlns:o='http://SampleSchemas.SimpleBody'>
this is a body</o:Body>"; // Execute the pipeline,
and check the output // we get a single message
batched with all the  // messages grouped into the
envelope's body IBaseMessage outputMessage = pipeline.Execute( MessageHelper.CreateFromString(body),
MessageHelper.CreateFromString(body), MessageHelper.CreateFromString(body) ); Assert.IsNotNull(outputMessage); 

Notice that, in this example, we didn’t explicitly add the schemas to the pipeline
itself; that’s because when they are configured on the XML assembler, the pipeline
picks it up automatically.

Example: Parse a flat file

In this example, I’ll create a new receive pipeline and add a Flat File disassembler
to it to parse a flat file from a BizTalk schema:

FFDisassembler ff = Disassembler.FlatFile()
   .WithDocumentSpec<Schema3_FF>();
ReceivePipelineWrapper pipeline = Pipelines.Receive()
   .WithDisassembler(ff);

IBaseMessage input = MessageHelper.CreateFromStream(
   DocLoader.LoadStream("CSV_FF_RecvInput.txt")
); MessageCollection output = pipeline.Execute(input); Assert.AreEqual(1,
output.Count);

Conclusion

This brief introduction should give you an idea of the capabilities of the PipelineTesting
library. As you can see, the new API is fairly intuitive and simple to use
and everyone should be able to use it with minimal effort.

If you have any questions, comments or run into a bug, do let me know; I’ll do my
best to answer and fix any issues!

Harry sticks up for the magic method

Harry sticks up for the magic method

Here 
– I can certainly understand his points.  For me it comes down to two things:

1) The design of ServiceHostBase isn’t as clean as I think it should given its intended
purpose (to allow WCF Services to be exposed w/o a .NET Type associated with it).

2) The exception.  I wouldn’t hate the design as much if a) the exception wasn’t
a blatant lie, and b) they actually documented that you need to call InitializeDescription
from your constructor.



Check out my BizTalk
R2 Training.

In Tech.Ed Spirit Rowan has posted last years keynote on slideshare!

http://rowansimpson.com/2007/08/08/teched-2006-keynote/

Remember that if you are in Auckland and have missed out on a ticket to Tech.Ed you are welcome to come to the keynote dress rehearsal tonight at Microsoft.

We are hosting Lou Carbone (our Tech.Ed Keynote Speaker) for a special UPA event tonight. Lou will be doing a “dress rehearsal” of next Monday’s keynote speech.

There is more about Lou on this page – http://www.microsoft.com/nz/teched07/keynote.aspx

RSVP by sending an email to [email protected] using a subject line such as:

RSVP yes for (1/2/3/4) people for Lou Carbone.

  • Event starts at 6pm for drinks and nibbles, and finish around 8pm.
  • Cost: $10 cash at the door. Please bring correct change.

Location: Microsoft, Level 5, 22 Viaduct Harbour Ave, Westhaven (Map)

Hope to see you there,

Nigel

Introduction to Visual Basic 9.0 Features

Alright, so I’ve spent a lot of my time this summer (and more this fall) going to

various groups and talking about the features in C# 3.0. This is something of

a thorn in the side of my good friend Cory Smith,

who despite the fact that he is a “Visual Developer” MVP, is the staunchest Visual

Basic advocate that I’m aware of. I swear this man dreams VB, I know he blogs

VB over at AddressOf.com. As such, I thought

it was time to give all of my friends who prefer Visual Basic their fair time, or

at least some time, so this post details the new features and shows the syntax for

things. There is not exact parity to the C# feature list, but its a close thing,

so here we go.

Automatic Properties

We’ll start of with the biggest exclusion. VB does not get automatic properties,

so they are left with the more verbose version of the syntax.

Partial Methods

Partial Methods are very useful for light weight event handling in generated code.

For instance, lets assume that you had a generated class that looked like this:

Partial Class NewFeatures
    Partial PrivateSub BeforeTextChange(ByVal oldText AsString, ByVal newText AsString)

              End

              Sub

            

    Partial PrivateSub AfterTextChange(ByVal oldText AsString, ByVal newText AsString)

              End

              Sub

            


              Private _text AsString

              Public

              Property Text() AsString

              Get

            

              Return _text

              End

              Get

            

              Set(ByVal value AsString)
            BeforeTextChange(_text, value)
            _text = value
            AfterTextChange(_text, value)

              End

              Set

            

              End

              Property

            

              End

              Class

            

The

partial methods BeforeTextChange and AfterTextChange are convenient extension points

should the person using your generated code needs to hook into them, but the magic

is that any of these methods which are not given implementations (both in our case

above) get compiled away.On the right you can see the Reflector disassembly

for Text property. Note that there are no calls to the partial methods, because

the compiler did not emit IL for them since there were no implementations.

Now let’s add the following short code-snippet into our project:

Partial Class NewFeatures

              Private

              Sub BeforeTextChange(ByVal oldText AsString, ByVal newText AsString)
        newText += oldText

              End

              Sub

            

              End Class

With

this added, we can go examine the Reflector disassembly again, and this time we see

something very different. Now we see the call to BeforeTextChange but still

no AfterTextChange because it still has no implementation.

Now, some important notes about this feature. Partial Methods must be Subs and

they must be Private. This is to avoid them being compiled away either changing

your interface (private) or breaking other code which depends on its results (hence

no functions).

Implicitly Typed Variables

Implicitly typed variables are not variants, this is very important so I’ll repeat

myself, Implicitly typed variables are not variants. These are strongly typed

variables which you simply forgo the need to type (as in press keys) the type (as

in the class name).

The restrictions? You must initialize the object on the same line it is declared,

so that the compiler can infer the type. Here is an example:


              Dim myString

= "This is a string, I swear"

Now myString is a System.String, not a System.Object or anything else.

Object Initializers

This is a minor tweak to something which VB has always been better at than C#.

It makes a more compact version of the With syntax, at the cost of adding curly braces

into VB, so you can judge if it’s worth it for yourself.


              Sub Main()

              Dim ds

= New SqlClient.SqlConnection() _

              With {.ConnectionString

= "Blah"}

              End

              Sub

            

For C# this feature is a god send, but C# didn’t always have With, so it’s your call

if this is truly a great feature.

Anonymous Types

Now, the addition of With as part of an object initializer is a little ho-hum, but

this is not. Enter Anonymous Types, a strongly typed object where the type is

not explicitly declared, but rather implicitly declared.


              Sub Main()

              Dim ds

= NewWith {.FirstName

= "Tim", _
                       .LastName = "Rayburn"}

              End

              Sub

            

Ok,

have I blown your mind yet? No? Well, then try this in for size… On the right is

the Intellisense you receive when you type “ds.” with this variable in scope.

The compiler has converted out simple syntax above into a full type with two properties

: FirstName and LastName. Pretty darned sexy if you ask me.

Restrictions? Of course there are restrictions. These can only be used

as private or local variables. If any other type will ever see this object them

you have to convert this to a full class. The VB compiler will let you make

these public, but it emits the type as System.Object and you loose intellisense.

Embedded Xml

This is a feature that C# 3.0 does not have, it is solely the province of Visual Basic

and I must admit, it kind of rocks. But it will also break your head the first

time you read it:


              Sub CreateCityXml(ByVal name AsString, ByVal lat AsDouble, ByVal lon AsDouble)

              Dim cityXml As XElement

= _
    <City>
        <Name><%= name %></Name>
        <Latitude><%= lat %></Latitude>
        <Longitude><%= lon %></Longitude>
    </City>

    cityXml.<City>.<Longitude>.Value = "XXX"

              End

              Sub

            

This feature has to do with LINQ to XML, the basic object of which is the XElement

class we are declaring above. You can with this embed XML directly in your VB

code. Notice there are no line continuation characters after the root node opens,

this is because it is assumed that the declare will end when the root node is closed.

Also note the use of the <% and %> like ASP and ASP.NET use to embed code into

the XML. This simple example is simply outputting variables, but there is no

reason why this couldn’t just as easily have contained a For loop or some other more

complex code.

The final line before the end of the sub shows how you can also use the XML node syntax

as if they were an object model. Now this does not include Intellisense support

for the .<tag> names, but it is still pretty slick.

Lambda Expressions

I know that Visual Basic has a tradition of being a less terse, more verbose language,

but I personally feel that VB got the short end of the stick on Lambda Expression

syntax. A Lambda expression is supposed to be a terse syntax for anonymous delegates

which also happens to be able to be explored via code if you’re using Expression Trees

(which we will not discuss here). For instance, let’s assume that you wanted

to select items from an List(of Integer) where the value was greater than 50.

You could write code like this:


              Function GreaterThan50(ByVal inputList As List(Of Integer)) As List(Of Integer)

              Return inputList.Where(Function(i)

i > 50)

              End

              Function

            

This is much more verbose than the C# syntax for that Lambda Expression “i => i

> 50” but I will grant you it is more readable so hopefully people who prefer VB

will prefer the VB syntax.

Extension Methods

The best feature of the .NET Framework 3.5, hands down, is extension methods.

If anyone has sold you on LINQ as the best feature, laugh at them and remind them

that LINQ is entirely based on extension methods.

What are they? Simple : The ability to add a new method to an existing type which

is only visible to those who implement your extension library.

Restrictions? Some. The biggest is that you do not get access to anything you

wouldn’t have had access to already. So creating an extension method is not

going to allow you to get access to private or internal types for a class.

Benefits? Huge! As cool as being able to add new methods to classes is,

you’ll please note I said you could extend types! This means

you can create an Interface and then provide implementation for that

interface via extension methods. In fact, that’s how LINQ is done in great part.

The .NET Framework now contains extension methods such as “Where” and “First” and

“GroupBy”for the IEnumerable interface. As such any IEnumerable can use

these, without changing the interface at all.

Very important note to those who try to stay fluent in both languages, the VB syntax

for extension methods is very different than the C# syntax, you’ll

want to pay very close attention to this.

Here are two examples, one extends a class, the other an interface:

<Extension()> _

              Function ToStringNullSafe(ByVal inObj AsObject) AsString

              If inObj IsNothingThen

              Return

              String.Empty

              Else

            

              Return inObj.ToString()

              End

              If

            

              End

              Function

            

<Extension()> _

              Sub Dispose(ByVal inObj As IDisposable)

              If inObj

IsNot NothingThen
        inObj.Dispose()

              End

              If

            

              End Sub

The first of these extension methods is something every UI developer has wished for,

a ToString function which does not blow up just because the variable is Nothing.

The second is an ingenious (if I say so myself) and beautiful hack of the IDisposable

interface. Most, but importantly not all, objects which implement IDisposable

implement a public Dispose method. Some however do not, even though they implement

it explicitly. This method will add a public Dispose method to any object which

implements IDisposable.

What if they already have one you ask? The actual method on an object always

wins out, and if there is a danger to extension methods, that is it. Should

the person who controls that type add a method which has the same name as your extension

method, your extension method becomes uncallable. A minimal risk for the incredible

power of being able to provide implementation to interfaces.

WCF LOB Adapter SDK is Released

 


We are delighted to announce the release of the WCF Line-of-Business Adapter SDK.   This SDK for Windows Communication Foundation provides the tools to quickly develop adapters to business applications.  Adapters built using this SDK can be consumed by any .NET application, including Microsoft’s BizTalk, SQL, and SharePoint Servers, and your own custom .NET applications.


Regards,


Marjan

Magic Methods (or the basics of deriving from ServiceHostBase)

Magic Methods (or the basics of deriving from ServiceHostBase)

Considering my history using ASP
and COM – you can imagine I’ve always been a fan of interface-based design.  Of
course, I’m not a religious zealot of any sort, so I’ve always been comfortable with
the idea of abstract base classes as another perfectly valid way to create pluggable,
extensible systems.  This
post is about one such pluggable system which utilizes abstract base classes – and
how that kind of design can just be stupid (not based on the concept of abstract base
classes, but just based on dumb design of such a system).

Harry has
been bugging me to post about creating classes that derive from ServiceHostBase, which
I have done quite a few times in the past year or so.  The
next technical post I make after this one will be about the ins and outs of creating
a class that derives from ServiceHostBase (specifically to host workflows as WCF Endpoints),
but I’ve had this post on my chest for a while and I just had to let it out (although
as I am writing the post I am finding that it is a pretty decent introduction to ServiceHostBase
– interspersed with slight vitriol). 

One of the things I strive for
whenever I design an abstract base class is to make sure that it is as simple as possible
to derive from and implement that base class.  One
of the great features in Visual Studio (VS) is that via reflection VS can determine
what methods *must* be implemented for a particular base class when you build a derived
class.

Let’s take a simple example.  Imagine
a base class named “Base” which is marked as abstract and which has one method, named
“VirtualMethod”. (I know this is pretty simplistic, but I feel it may be the only
way to get the WCF team at MS to understand the issue).

 public abstract class Base

{

    public abstract string VirtualMethod(string param);

}

Now
imagine you want to derive from that base class and create a class named “Derived”
which implements all the abstract methods of this base class.  Here
is an example implementation:

public class Derived : Base

{

 

    public override string VirtualMethod(string param)

    {

Console.WriteLine(“This
should work: {0}”
,param);

        return “Implemented
VirtualMethod”;

    }

}

 

A
cool feature related to abstract base classes in Visual Studio 2005 is that once you
type “public class Derived : Base”, there is smart tag hovering over the Base keyword.  If
you select that smart tag with the mouse (or use the Alt-Shift-F10 keyboard shortcut
as I like to do), you get a context menu which states that it will “Implement abstract
class ’Base’” for you.

>

I
personally find the Alt-Shift-F10 shortcut to be super useful (it can also be used
to implement an interface).  I also think
from a *moral* point-of-view that, when I derive from an abstract base class and use
Alt-Shift-F10 (or just manually implement *all* the abstract methods), my derived
class should *work* in whatever context the base class is supposed to work (which
is really the point of abstract base classes right?).  The
whole point of marking methods “virtual” is to force the derived class implementor
to provide an override of those methods.   Whatever
code uses the base class methods should work with a complete, correct implementation
of the base class (of course the C# or VB.NET compiler won’t let you complie an incomplete
implementation, but it certainly will let you compile an incorrect one).

So
what would you think  if you downloaded
some library from some company which was based on some OO language which supported
abstract base classes, and you did the above steps (implementing all the abstract
methods), and then when you plugged your class into the framework for that class,
your class didn’t work?  What would you
think if it didn’t work
*and* the exception
you got was a blatant lie about why your nicely implemented dervied class didn’t work?

In
fact, WCF provides such a framework (and has such an exception – you’ll just have
to keep reading for that) for creating derived classes that can plug into its framework.  ChannelListeners
are the channel manager used to provide service Endpoints – that is Endpoints which
listen for incoming messages in WCF. The way you load up ChannelListeners in WCF,
in the general case,  is to use a class
named ServiceHost.  ServiceHost is a useful
class that enables you to associate one or more endpoints with a .NET class which
implements one or more contracts, and thus hosts one or more contracts on one or more
endpoints.  ServiceHost is a really useful
class in WCF (fairly essential actually).

In
the ASP.NET/WPAS hosting scenarios, you don’t actually get to create your own ServiceHost
type – the ServiceHost is created implicitly based on your .svc file (with help from
your web.config file for the binding and potential behaviors). To create the ServiceHost,
the WCF HttpHandler actually uses a class called ServiceHostFactory, which is a fairly
typical generic Factory pattern implementation (handing out ServiceHost objects to
requestors).  This features is a really
cool extensibility point of WCF, one that can be used for things ranging from controlling
Behaviors on your ServiceHost (i.e. not relying on configuration for features like
ServiceMetadataBehavior or ServiceDebugBehavior) to replacing the ServiceHost/.NET
Type pairing paradigm with some other paradigm.  Steve
Maine has some good info on ServiceHost/ServiceHostFactory 
here.

So
more than a year ago I ventured to write my first custom ServiceHost/ServiceHostFactory
pairing.  Here’s my story of that adventure.  Just
to make it a little more interesting, and to see how the plumbing is put together
in WCF,  I chose to derive from ServiceHostBase
and ServiceHostFactoryBase (see Steve’s article above about the choices between deriving
from ServiceHost or ServiceHostBase).  So
I fired up Visual Studio and created classes that derived from ServiceHostFactoryBase
and ServiceHostBase. Using my Alt-Shift-F10 trick – this is what I end up with (after
removing the throw clauses that Alt-Shift-F10 place inside of each overriding method):

public class MyServiceHostFactory : ServiceHostFactoryBase

{

public override ServiceHostBase CreateServiceHost(string constructorString, Uri[]
baseAddresses)

    {

    }

}

 

public class MyServiceHost : ServiceHostBase

{

protected override ServiceDescription CreateDescription(out IDictionary<string,ContractDescription>
implementedContracts)

    {

 

    }

}

Of
course at this point the code won’t compile, since I haven’t actually provided implementations.  The
implemenation of CreateServiceHost is pretty easy – all I need to do there is create
an instance of ServiceHostBase.  In the
typical case, your ServiceHostBase implementation will have a constructor that takes
both of the arguments passed to CreateServiceHost.  The
OOB implementation (ServiceHost) uses the first argument to figure out what .NET Type
should be used to implement the service Endpoints around, and uses the second argument
as list of base Uris that relative Uri’s can hang off of the base addresses (assuming
the Endpoint’s transport channel matches the scheme of the base Uri).  So
that’s pretty easy.  I’ll store those
two parameters in instance fields on the MyServiceHost Type, as we’ll need them later.

The
interesting part here is implementing ServiceHostBase::CreateDescription.  CreateDescription
is really the key to making your ServiceHostBase implementation work within the WCF
infrastructure.  From the look of the
return value (ServiceDescription) you might get the mistaken idea that the ServiceDescription
is only used by WCF to publish metadata (assuming metadata publishing is enabled on
your Service).  This is really pretty
far from the truth.  The instance of ServiceDecription
returned from your ServiceHost (as well as the out parameter – the generic dictionary
of strings and ContractDescriptions) is used for more than just metadata publishing.   It
is used by the WCF dispatching layer to route messages received via the Channel layer
down to the Service layer (the piece we are trying to implement).  Creating
a valid ServiceDescription and returning the list of implemented contracts is essential
for making your ServiceHostBase-derived class work.

So
let’s assume I create a valid return value and out parameter for CreateDescription
(the next post will get into the necessary detail on how exactly to accomplish that).  Once
I do so, notice that there are no more virtual method to implement from ServiceHostBase.

Next,
I need to get my custom ServiceHostBase derived class loaded by WCF.  In
the typical WCF hosting scenario in IIS there is a .svc file.  The
.svc links to the “Service Type” – the .NET Type that WCF will use as the basis for
the endpoints exposed via the Uri ending in .svc.  Here
is a typical example:

<%
@ServiceHost Language=C# Debug=”true” Service=”MyService” CodeBehind=”~/App_Code/Service.cs”
%>

In
the IIS hosting case, the value of the Service attribute from the ServiceHost directive
is passes as the parameter to the ServiceHostFactory:CreateServiceHost and to the
typical contstructor of ServiceHost. 

To
load your own custom ServiceHostFactory all you need to do is add a Factory attribute
to the ServiceHost directive.  Like this:

<%
@ServiceHost Service=”MyService” Factory=”MyServiceHostFactory” %>

When
I do all this and browse to the URL for the Service, I get this lovely exception in
the browser:

 

For search engine purposes – the exception/lie is “InitializeRuntime requires that
the Description property be intialized” (this part isn’t a lie) – “Either provider
a valid ServiceDescription in the CreateDescription method or override the InitializeRuntime
method to provide an alternate implementation”. 

So
I begin to scratch my head (this is me retelling the story when I first wrote this
code oh-so-long-ago).   I
generally always assume that when something like this happens, *I’ve* done something
wrong.  So I assume my instance of ServiceDescription
must be invalid, since I *definitely* implemented the abstract methods from ServiceHostBase.

Here
is where things get ugly. I spent an afternoon looking through Reflector  to
figure out where I had gone wrong.  I
even went to the trouble to delegate to an instance of ServiceHost to get what I knew
to be a valid ServiceDescription.  Once
I had done that and I was still getting the same exception, I began to think it wasn’t
*my* implementation of CreateDescription, but something else.  This
of course (about 4 hours later) led me down another Reflector expedition into what
ServiceHost was doing that I wasn’t.

Finally
after another hour or so – I stumbled upon it.  In
the *constructor* of ServiceHost (not ServiceHostBase mind you – but WCF’s OOB implementation
of ServiceHostBase) there is a call to InitializeDescription.  InitializeDescription
calls another method, which in turn sets the ServiceHostBase.description field (which
is *private* BTW so I couldn’t set the value myself) to the  return
value of the call to CreateDescription.

So
the *only* way to make a ServiceHostBase derived class work inside of this infrastructure
is to call a “magic” method inside of your ServiceHostBase constructor.  Failure
to call IntializeDescription will lead to complete failure when implementing a derived
class of ServiceHostBase.

So
now that I have all my pent-up frustration out – what are the key points here?

1)      This
is a stupid design – if I implement all the abstract methods of an abstract base class
my class should work.  Period.  Unless
there is some super compelling reason – this should also be the case with interfaces
(see ISerializable for what I would consider to be a valid exception to this rule
where you must implement a special constructor for deserialization purposes).

2)      WCF
has no such special reason.  In fact,
if you look at the implemenation of InitalizeRuntime, all it does is check to see
if the value of the Description property is null or not (the Description property
is a public read-only property on top of the ServiceHostBase.description field).  If
it is null, the stupid exception I showed above is displayed.   Are
you telling me ServiceHostBase:InitializeRuntime couldn’t reasonably add one line
of code to call CreateDescription after discovering that the property is null.  And
*then* throw this exception after that call returns null?  Or
the Description property itself could be responsible for calling InitializeDescription
if the field was null (this was Harry’s suggestion).

So
basically this means the exception I got is a blatant lie.  I
did provide a perfectly valid ServiceDescription from my CreateDescription method.  It’s
just that ServiceHostBase never calls CreateDescription.  Instead
– in my derived class – in my constructor – I have to call another method (InitializeDescription)
which then in turn will cause the description field to be properly filled in with
the return value of my totally correct/valid ServiceDescription (which I have to rely
on since the description filed on ServiceHostBase is private).  Which,
mind you,  I had created 6 hours before
I discovered the magic InitializeDescription method.

Please
folks (at MS and elsewhere) don’t design abstract base classes that rely on magic
methods to work correctly.  It makes me
testy.  It’s dumb.  What
else can be said about it? How about – IT’S DUMB (ahh – I feel  better
already).

Alt-Shift-F10
plus actually implementing all the methods correctly should be enough (barring some
real circumstance which might make making a magic method necessary – and if that’s
the case – document the hell out of it).

 



Check out my BizTalk
R2 Training.

Paul Andrew : What to use Windows Workflow Foundation for?

Paul Andrew has a nice write up on why you would use Windows Workflow Foundation. There are some excellent arguments for the use of the rules component: the visibility into the business logic and the ability to change this business logic.

That is exactly the reason why I’m currently designing a Windows Workflow Foundation architecture for a very large client. Performance will become critical…