There is a serious limitation present in the RTM version of WCF 3.0/3.5 regarding control of WS-RM retry messages during a reliable session saga.

Let me try to explain the concept.

We have a sender (communication initiator) and a receiver (service). When a reliable session is constructed between the two, every message needs to come to the other side. In a request-reply world, the sender would be a client during the request phase. Then roles would switch during the response phase.

The problem arises when one of the sides does not get the message acknowledgement in time. WCF reliable messaging implementation retries the sending process and hopes for the acknowledgement. All is well.

The problem is that there is no way for the sending application to specify how long the retry timeout should be. There is a way to specify channel opening and closing timeouts, acknowledgement interval and more, but nothing will define how long should the initiator wait for message acks.

Let's talk about how WCF acknowledges messages.

During a request-reply exchange every request message is acknowledged in a response message. WS-RM SOAP headers regarding sequence definition (request) and acknowledgements (response) look like this:

Request phase defines a sequence and sends the first message (a3). In response, there is the appropriate acknowledgement present, which acks the first message (b3) with Lower and Upper attributes. Lines b4-b6 define a benign and super useful WCF implementation of flow control, which allows the sender to limit the rate of sent messages if service side becomes congested.

When the session is setup, WCF will have a really small time waiting window for acks. Therefore, if ack is not received during this period, the infrastructure will retry the message.

Duplex contracts work slightly differently. There, the acknowledgement interval can be set. This configuration option (config attribute is called acknowledgementInterval) is named inappropriately, since it controls the service and not the client side.

It does not define the time limit on received acknowledgements, but the necessary time to send the acknowledgments back. It allows grouping of sent acks, so that multiple incoming messages can be acked together. Also, the infrastructure will not necessarily honor the specified value.

Now consider the following scenario:

The client is on a reliable network

Network bandwidth is so thin that the sending message takes 20s to come through [1]

[1] It does not matter whether the initiator is on a dial up, or the message is huge.

What happens?

Service initiator sets up a reliable session, then:

First message is being sent

Since the retry interval is really small [2], the message will not get to the other end and the acknowledgement will not bounce back in time

First message is retried, now two messages are being transported

No acks received yet

First message is retried again

Network bandwidth is even thinner

First message is acknowledged

First message retry is discarded on the service side

Second message retry is discarded on the service side

[2] Under 3s.

The number of retry messages depends on the bandwidth and message size. It can happen that tens of messages will be sent before first acknowledgement will be received.

Adaptability algorithms

A good thing is that there are undocumented algorithms implemented for retry timeout. The implementation increases the reply timeout exponentially when the infrastructure detects that the network conditions demand more time (slow throughput) and allows reliable delivery (no losses). If loses are present the reply timeout decreases.

Retry timeout is actually calculated when establishing an RM session. It is based on the roundtrip time and is bigger if the roundtrip time is long.

So, when first messages in a session are exchanged, don't be too surprised to see a couple of message retries.

In WCF, collection data that is passed through the service boundary goes through a type filter - meaning you will not necessarily get the intrinsic service side type on the client, even if you're expecting it.

No matter if you throw back an int[] or List<int>, you will get the int[] by default on the client.

The main reason is that there is no representation for System.Collections.Generic.List or System.Collection.Generic.LinkedList in service metadata. The concept of System.Collection.Generic.List<int> for example, actually does not have a different semantic meaning from an integer array - it's still a list of ints - but will allow you to program against it with ease.

Though, if one asks nicely, it is possible to guarantee the preferred collection type on the client proxy in certain scenarios.

Unidimensional collections, like List<T>, LinkedList<T> or SortedList<T> are always exposed as T arrays in the client proxy. Dictionary<K, V>, though, is regened on the client via an annotation hint in WSDL (XSD if we are precise). More on that later.

Let's look into it.

WCF infrastructure bends over backwards to simplify client development. If the service side contains a really serializable collection (marked with [Serializable], not [DataContract]) that is also concrete (not an interface), and has an Add method with the following signatures...

public void Add(object obj);public void Add(T item);

... then WCF will serialize the data to an array of the collections type.

[OperationContract] Coin[] GetCoins();}Note: Coin class should be marked either with a [DataContract] or [Serializable] in this case.

So what happens if one wants the same contract on the client proxy and the service? There is an option in the WCF proxy generator, svcutil.exe to force generation of class definitions with a specific collection type.

In Visual Studio 2008, you will even have an option to specify which types you want to use as collection types and dictionary collection types, as in the following picture:

On the other hand, dictionary collections, as in System.Collections.Generic.Dictionary<K, V> collections, will go through to the client no matter what you specify as a /ct parameter (or don't at all).

If you define the following on the service side...

[OperationContract]Dictionary<string, int> GetFoo();

... this will get generated on the client:

[OperationContract]Dictionary<string, int> GetFoo();

Why?

Because using System.Collections.Generic.Dictionary probably means you know there is no guarantee that client side representation will be possible if you are using an alternative platform. There is no way to meaningfully convey the semantics of a .NET dictionary class using WSDL/XSD.

So, how does the client know?

In fact, the values are serialized as joined name value pair elements as the following schema says:

The meaningful part of type service-to-client-transportation resides in <xs:annotation> element, specifically in /xs:annotation/xs:appinfo/IsDictionary element, which defines that this complex type represents a System.Collections.Generic.Dictionary class. Annotation elements in XML Schema are parser specific and do not convey any structure/data type semantics, but are there for the receiver to interpret.

This must be one of the most excellent school cases of using XML Schema annotations. It allows the well-informed client (as in .NET client, VS 2008 or svcutil.exe) to utilize the semantic meaning if it understands it. If not, no harm is done since the best possible representation, in a form of joined name value pairs still goes through to the client.

This contract defines a simple method, called Process, which processes the input document. The idea is to define the document schema and validate inbound XML documents, while throwing exceptions on validation errors. The processing semantics is arbitrary and can support any kind of action, depending on the defined invoke document schema.

A simple instance document which validates against a version 1.0 processing schema could look like this:

Note that the default XML namespace changed, but that is not a norm. It only allows you to automate schema retrieval using the schema repository (think System.Xml.Schema.XmlSchemaSet), load all supported schemas and validate automatically.

The main benefit of this approach is decoupling the parameter model and method processing version from the communication contract. A service maintainer has an option to change the terms of processing over time, while supporting older version-aware document instances.

This notion is of course most beneficial in situations where your processing syntax changes frequently and has complex validation schemas. A simple case presented here is informational only.

So, how do we validate?

We need to check the instance document version first. This is especially true in cases where the document is not qualified with a different namespace when the version changes.

We grab the appropriate schema or schema set

We validate the inbound XML document, throw a typed XmlInvalidException if invalid

We process the call

The service side is quite straightforward.

Let's look at the client and what are the options for painless generation of service calls using this mechanism.

Generally, one can always produce an instance invoke document by hand on the client. By hand meaning using System.Xml classes and DOM concepts. Since this is higly error prone and gets tedious with increasing complexity, there is a notion of a schema compiler, which automatically translates your XML Schema into the CLR type system. Xsd.exe and XmlSerializer are your friends.

If your schema requires parts of the instance document to be digitally signed or encrypted, you will need to adorn the serializer output with some manual DOM work. This might also be a reason to use the third option.

The third, and easiest option for the general developer, is to provide a local object model, which serializes the requests on the client. This is an example:

The main benefit of this approach comes down to having an option on the server and the client. Client developers have three different levels of complexity for generating service calls. The model allows them to be as close to the wire as they see fit. Or they can be abstracted completely from the wire representation if you provide a local object model to access your services.

WCF includes support for establishing a security session through a simple configuration attribute. The primary reason of a security session is a shared security context which enables clients and services to use a faster, symmetric cryptographic exchange.

WCF sessions should not be thought of in terms of HTTP based sessions, since the former are initiated by clients and the latter by the servers. In other terms, WCF sessions are there to support some kind of shared context between a particular client and a service. This context can be anything, and is not limited to security contexts.

The attribute that establishes a security session and shared context is called, well, establishSecurityContext and is present in binding configuration. An example of such a binding would be:

This binding allows HTTP based communication, demands message based security (think WS-Security) and uses certificates to sign/encrypt the message content. The attribute establishSecurityContext is set to true, which actually enforces a WS-SecureConversation session between the client and the service.

The following is a simplified version of what is going on under the covers:

Client instantiates the service proxyNo message exchange is taking place yet.

Client requests a SCT (Secure Context Token)This is done by the infrastructure, when the first service method is called. SCT (again simplified) represents a secure context, which includes the symmetric key. The message which demands it is (per WS-SecureConversation spec) called RST (Request Secure Token).

Service responds with RSTR (Request Secure Token Response) messageSession bootstraps and is ready to piggyback all further message exchanges.

What is not well known is that there is a very low limit on the number of sessions a service is willing to accept. The default is set to 10 sessions and this was changed (from 64) late in the WCF development cycle (summer 2006). So RTM ships with this default.

Service session count is greatly influenced by the instancing scheme the service is using. Since instancing is a completely different beast, let's leave this for another post (uhm, I already wrote something here). Let's just say that hitting the session problem is a non-issue when using singleton instancing (InstanceContextMode = InstanceContextMode.Single).

The main issue is, that most developers think of Indigo WCF services in terms of simple request-response semantics and forget that such sessions get queued up on the service side if you do not terminate them appropriately.

This is the default service throttling behavior in the shipping version of WCF:

Every service is throttled, even if you don't specify it. You can, of course, override all three throttling parameters.

Sessions can only be initiated by the client. They can be explicitly terminated only by the client. There are three ways a session can get terminated:

Explicitly by the client

Implicitly by a timeout

Implicitly by errors

Timeout can pass on a client or a service and, if the timeout happens, the transport channel that ensured communication gets faulted (Channel.State = CommunicationState.Faulted). Session is also terminated if an error is detected, thus invalidating the possibility to continue.

Remember that every service proxy you use will demand a new session on the service side (when using sessionful services). If you spawn 11 threads and use a non-singleton proxy you will cause 10 sessions on the service side. The 11th will not get setup and will block the client thread until the timeout expires. In this case, the WCF infrastructure on the service side will issue a warning in the trace log, but nothing will be returned to the client. It seems as if the service would stop working. Nada.

There is a method on every service proxy and it's there for a reason. The method is called Close(). It closes the transport channel graciously and terminates the security session, thus freeing up service resources. The same happens for reliable messaging session or a combination of both.

Note: Another message (pair) is exchanged on Close(). This message is saying "We are done." to the service. Thus, one should be cautious when calling Close() for any exceptions, like CommunicationObjectFaultedException.

The best practice is to catch any CommunicationException exceptions when closing the channel.

To illustrate this, consider the following. You call a single method on a sessionful service. Then hang on to the service proxy instance for an hour. The inactivity timeout (attribute inactivityTimeout on a RM binding) is set to 10 minutes. So, ten minutes after the first call the channel gets faulted. Then you call Close(). This call will fail and throw an exception.

The following is the expected way of communication with sessionful services:

Note that using the using statement is not recommended. The problem of using statement in this case is that CLR automatically calls Dispose() method on the using variable when exiting the statement. Since Close() can fail (remember, another message is exchanged), you can miss this important exception.

Everything in this post is true for all kinds of WCF sessions. It is not limited to security or RM sessions only.

I'm thinking about reliable messaging these days (isn't itevident?). There are a couple of specific reasons for that. First, I can imagine a wonderful world of seamless message delivery. Second, currently there are technology limitations that prohibit what most of the industry would like to see.

This is conditionally true. There are built-in bindings that support MSMQ integration and use MSMQ transport as a delivery mechanism, thus making the message exchange durable. Limitations of this approach include platform dependence, durable store dependence and more importantly, one-way messaging. To implement a durable duplex session one would need to implement two one-way service contracts. Downside? Forget about clients sitting behing a NAT without poking holes in your firewalls.

There are multiple uses for having durable messaging, the most prominent being different client/service lifetimes. Why can't I dispatch a message to a service when the service is down or I have no network connectivity?

Reliable messaging support in WCF is designed to support reliable transport and does not make any assurances of what happens to messages when they hit both ends of the wire. The problem is not in the WCF implementation but rather the WS-RM spec, which does not imply on how and when a message should/must be persisted.

The industry (read WS-* stack) needs a specification which will cover interoperable + durable message delivery. BYODS ("bring your own durable store") concept would be efficient only when demanding a durable store on the other side of the wire, is governed by a messaging specification.

Everything about WCF is about keeping your service boundary intact. By default this also applies to exposing/publishing metadata. In ASMX days, one would need to opt-out of exposing metadata, while in WCF, one has to opt-in.

Let's say, for example, you have the following service config declaration:

This would host Exposing.Metadata service and define a single wsHttpBinding based endpoint listening at the base address.

So, the service endpoint address is http://localhost:123/MetadataService. If you would hit the endpoint URL with a web browser, a nice service page would be returned telling you that you have created a service, but there is no metadata exposed. So, hitting the endpoint with svcutil.exe would not allow you to grab metadata and generate the proxy code.

WCF, by default, does not expose any metadata. You have to ask for it nicely.

There are a couple of options to expose metadata of WCF services. The most basic way of doing it would be to expose it via HTTP based Get requests and retrieve WSDL. The following code fragment would do it, if you hosted the service using a ServiceHost class:

Lines 3-5 instantiate and add a service behavior that allows a simple HTTP Get request to succeed for metadata retrieval. Also, the mentioned service page would now render a link to the WSDL definition of the service.

We declared a behavior, called MetadataBehavior and assigned it to our Exposing.Metadata service.

There are a couple attributes in <serviceMetadata> element worth discussing:

externalMetadataLocation allows you to specify the path to your WSDL metadata file, so you can provide it out of band and not rely on the infrastructure to generate it for you.

httpGetEnabled exposes this metadata via HTTP transport.

httpGetUrl enables you to define a different relative WSDL metadata endpoint address. If 'wsdl' was used, our service would expose WSDL metadata at http://localhost:123/MetadataService/wsdl.

httpsGetEnabled allows you to expose metadata via HTTPS transport.

httpsGetUrl is analog to httpGetUrl but for HTTPS.

This nails down all options one would want for exposing HTTP based metadata endpoints.

Now, exposing metadata using the WS-MetadataExchange (WS-MEX or MEX) protocol is also opt-in. First, you have an option to include only HTTP based metadata, as described. Second, there is a way to expose all metadata only using WS-MEX.

Note: This is only the <serviceBehaviors> section, not the complete service config file.

You have to tell the hosting infrastructure to expose metadata by adding a service behavior with the <serviceMetadata> element. What this does, essentially, is add an interface called IMetadataExchange to your contract - but does not expose it yet. You have to add a metadata endpoint to your service and bind it to a transport of choice.

When this service is hosted, MEX metadata is exposed at http://localhost:123/MetadataService/mex and you can reach it with svcutil.exe or 'Add Service Reference' in Visual Studio. HTTP based WSDL access is not allowed since <serviceMetadata> element does not include the httpGetEnabled property with the value of true. It's false by default, which resonates nicely in terms of WCF's opt-in scenarios.

Remember, service orientation is about defining boundaries. And reaching metadata about your service should be confined to your choosing, not the platforms.

In the previous post we discussed possible scenarios and methods for configuring reliable message delivery in WCF. Let's look further into this great WCF feature.

Delivery assurances can have a large impact on the way your code processes incoming messages. Especially, ordering can be of importance if your code relies on ordered message delivery. Since configuration can be changed by any WCF service administrator there is a knob in WCF which lets you demand the appropriate binding. The knob is in a form of a declarative attribute, called DeliveryRequirementsAttribute.

DeliveryRequirementsAttribute can be set on any service interface or service class implementation. It has three properties:

QueuedDeliveryRequirements which has three possible values, Allowed, NotAllowed and Required. Setting NotAllowed or Required makes the binding either demand or prevent WS-RM usage. Setting Allowed does not make any requirements.

RequireOrderedDelivery demands a binding that supports and has ordered delivery turned on.

TargetContract property is applicable only when the attibute is applied to a class definition. Since WCF service interfaces can be implemented by multiple classes, one can specify a specific interface for which the queued delivery requirements are defined.

The specified contract interface would demand a WS-RM capable binding and thus prevent service administrators to turn reliable delivery off.

In case where an administrator would turn reliable delivery (or ordering, in this case) off, the service host would throw an exception while trying to host the service.

So, DeliveryRequirementsAttribute guards developers from wrongdoings of service administrators. It should set QueuedDeliveryRequirements = QueuedDeliveryRequirementsMode.Required or RequireOrderedDelivery = true, when there are objective reasons to demand guaranteed and/or ordered delivery of messages.

Windows Communication Foundation includes concepts which enable the developer to insist on reliably delivering messages in both directions. The mechanism is actually transport agnostic and allows messages to be flown reliably from client to service and replies from service to client.

WS-RM is based on a concept of a message sequence. You can think of it in terms of a session, although it does not carry HTTP session semantics (remember, it's transport agnostic). A communication initiator (RM source) sends a <CreateSequence> element inside the message body to establish a RM sequence. Service side (RM destination) responds with either <CreateSequenceReponse> or <CreateSequenceRefused>, in cases where new sequence is not welcome.

After the sequence is initialized, there is an additional SOAP Header in messages. It identifies the message number being transferred. The following is a simple example of headers of the first two messages:

After all messages have been exchanged and acknowledged, the RM destination sends a <SequenceAcknowledgement> inside the body of the message. RM source (communication initiator) then tears down the sequence with a <TerminateSequence> message.

So, how can this specification be implemented in various technology stacks? Well, WCF implements reliable messaging using the in-memory message buffers. There is no durable reliable messaging support in WCF.

Here's how it works:

Communication initiator (client) sends a <CreateSequence> message.

Service side responds with a <CreateSequenceResponse>.

Client sends 1..n messages and buffers them, while waiting for all acknowledgements.

Service side can and will dispatch the received messages as soon as possible. Now, there are two options:

Communication is configured for ordered deliveryFirst message will be dispatched to the service model as soon as it arrives, noting that it has been processed. Every other message is processed in order. If message number 5 has been processed and the next received message carries sequence number 7, it will not be dispatched until message 6 is received and processed by the service model.

Communication allows out-of-order deliveryFirst message will be dispatched to the service model as soon as it arrives, so will all the following messages. Since we did not demand ordered delivery the processing pipeline does not care on when to process the messages. It will process them as soon as they are received. They are acknowledged as soon as possible, but not before acknowledgement interval.

Service side sends a <SequenceAcknowledgement> message only when all messages have been acknowledged.

Initiator then stops the sequence with a <TerminateSequence> message.

So, how do we go about enabling WS-RM and realizable delivery in WCF? Simple. Here's the config file:

There are a couple of options available for anyone using the custom binding, in regard to reliable messaging behavior:

acknowledgementInterval specifies the time lapse duration of message acknowledgement. The default is two seconds, while always acknowledging the first message. This gives you an efficient way to group the acknowledgement messages, thus conserving network traffic.

flowControlEnabled enables message sender to acknowledge the receive buffer on the recipient side. It turns out that every acknowledgement message includes a service buffer status and if this attribute is set, sender will not send messages if the recipient buffer is full, thus not occupying network resources.

inactivityTimeout defines the absolute duration of a no-message (infrastructure and application messages) session. After the timeout, the session is torn down.

maxPendingChannels defines how many reliable channels the service can put in its waiting-to-open queue. If there's a significant load, the pending requests can queue up and the service refuses to open a reliable session (think <CreateSequenceRefused>).

maxRetryCount defaults to 8. It defines how many times the infrastructure retries with message delivery. If the limit is achieved, the channel will become faulted.

maxTransferWindowSize defines how many messages should be buffered. On service side all messages that have not been acknowledged increase the count. On the client side, all messages which have not received their acknowledgement pair are counted.

ordered defines in-order delivery. It's values are true and false.

There is some confusion in the wsHttpBinding's <reliableSession> config element. There's an enabled property in the Visual Studio config schema, which should not have any influence on reliable session establishment (and does not have a matching object model method/property). It does, however. There is a difference if you setup a reliable session by using a customBinding or wsHttpBinding.

This will enable reliable and ordered session support in any custom binding.

So, in general - WCF implementation of WS-ReliableMessaging gives you automatic message retries, duplicate detection, and ordering. It should be turned on for any multi-hop message paths, but can be very valuable even in high latency/packet loss network scenarios.

We had a nice discussion throughout the day today, together with around 50 attendees. It's hard to even cover feature changes of .NET 3.0 in a day, but we managed to cover the important things of WCF and WF, spending a complete day inside the Visual Studio.

Having the ability to call services from inside your workflows is a good thing. Things get a little obfuscated when one wants to expose a WCF based service to Windows Workflow Foundation (WF).

What it comes down to is that currently (beta 2 build of WF) we do not have any built-in workflow activities which would allow you to communicate with the WCF advanced services (meaning WS-Security enabled, TCP based, WS-RM enabled, WS-Tx enabled, ...).

Now, this is not enough. Our service exposes three different endpoints, each one has different message requirements. And what is more important, all three are based on SOAP 1.2 + WS-Addressing.

There is a 'Default' endpoint which is plain vanilla SOAP 1.2 endpoint, without any security (have to mention it: WCF services are secure by default, one has to turn off security to achive this). Second endpoint uses Windows based message security and third turns on WS-RM. Security wise, second and third endpoints are the same (remember, defaults?).

As said, WF is currently not able to communicate with any of the above endpoints. What needs to be done is adding another endpoint to your service, which would expose it in ASMX compatible way.

Due to the value of false, the specified config would mandate that the WCF clients need to obtain the service credential (in this case, an X.509 certificate) out of band. Out of band in this situation means that the client needs to have a service side certificate in one of its certificate stores.

If one would put negotiateServiceCredential="true" in the upper configuration file this would not be necessary. Indigo would start with a SPNego protocol to exchange the service credentials using startup messages. For the client side, this is good in certain situations, where you would not want to (or were unable to) store service side credentials on the client. The major drawback is that this forces you to use SPNego during initialization phase and it forces you to do it every time you start up the client.

If the clientCredentialType attribute equals to Anonymous, Username, or Certificate, setting this attribute to false implies that the client needs to define the serviceCertificate attribute. The following would be a valid config value for having clientCrendentialType="Certificate" (again, limiting it to only the behavior element:

This config file mandates that the client has service credentials available out of band. Specifically it should be available in the local machine certificate store. The certificate should have a substring of MyCertSubject inside its subject. If this is not the case, one would not be able to call the service successfully.

There's an option to host your workflow library inside a web service by using a "Publish as a Web Service" option inside Visual Studio 2005. This creates a separate ASP .NET Web Service project inside your current solution, which you can later manually or automatically publish as a web site to your IIS of choice.

The are two major downsides to this story. The first is that this gives you practically no control over how the web service is created. Second downside, while documented, is that the current implementation of System.Workflow.Runtime.WorkflowWebHostingModule works in particular ways with the workflow persistence story.

Let's assume we have to following interface defined for this web service:

At this time the workflow runtime (System.Workflow.Runtime.WorkflowRuntime instance) creates a workflow instance and runs it. Since workflow completes succesfully it destroys the instance at the end of execution.

Workflow runtime returns a cookie with the workflow instance back to the browser and since IE's default setting is to accept cookies, it is written to the client's disk

All good, right?

Actually, what happens during request number 2?

You hit the endpoint again

IE knows that the site has a persisted cookie, so it sends it bundled with the SOAP request

Workflow runtime sees it and tries to load the specified workflow instance

This instance is long gone, it does not exist in memory (it has been destroyed, remember?), so workflow runtime tries to rehydrate it from a persistence store. If there is a persistence store defined it goes there (most probably WorkflowPersistenceStore in SQL Server) and correctly identifies that the workflow instance is not present, so it fails with 'Workflow with id <GUID> not found in state persistence store.'. If the persistence store is not defined for this workflow it fails with 'The workflow hosting environment does not have a persistence service as required by an operation on the workflow instance <GUID>.'.

And all this is actually the expected behavior if you think hard enough. Workaround? Hit the endpoint with a newly loaded IE window. It works every time, since a cookie with an instance ID is not present.

Another thing to mention here is that this issue does not manifest itself if you hit the endpoint programatically using the web service proxy, unless you are using a CookieContainer class to cache the returning cookies.

Ad 2:

Hosting a Windows Workflow manually is another option, which gives you more flexibility towards the service detail tweeking.

An important thing in the specified sample is that the System.Workflow.Runtime.WorkflowRuntime instance is static to the service implementation class. This is a requirement, since the workflow runtime can only get loaded once per appdomain. If this is not the case you will get an exception during the second invocation of the workflow.

If you are using any additional workflow runtime services, like persistence, tracking or your own communication service to communicate with the workflow you will need to track that the services get loaded once only. Here's the example:

This adds the required services only during the first invocation of a web service. Since workflow runtime is a static class the services get persisted during all subsequent service calls. A boolean variable booServicesAdded is responsible for flag storage.

What it says is that the client certificate must validate according to the complete certificate chain. In broader terms it forces the caller to use the certificate that is 'validatable' on the service side. This means the following:

The certificate must be present at the time of request generation (client side)

The certificate must be valid according to expiration period and certificate generation (checking done on server side)

The certificate chain (issuing CAs path) must be valid (certificateValidationMode="ChainTrust")

The certificate must not be obsolete and/or revoked (revocationMode="Online")

Other authentication options of certificateValidationMode and revocationMode include:

certificateValidationMode can take a velue of ChainTrust, PeerTrust, ChainOrPeerTrust, None or Custom. None means that no certificate checking is done, Custom allows one to plug in a custom X509CertificateValidator (new, System.IdentityModel.Selectors namespace), PeerTrust forces a public key of the client certificate to be present in the 'Trusted People' certificate store on the service side and ChainTrust requests that the client cert can be validated against the root certificates on the server side. ChainOrPeerTrust just executes the OR operator on the last two.Remark:PeerTrust and ChainOrPeerTrust are also subjected to another attribute called trustedStoreLocation. If peer trust is demanded, one can specify where the public keys are present, meaning either in LocalMachine or CurrentUser store.

revocationMode takes the following value list: None, Online or Cached. None is saying that CRL (Certificate Revocation List) is not checked. Online demands that service checks (at every request) whether the certificate is still valid and thus not revoked. Offline says that the certificate should only be checked against the cached CRL.Remark:Online does not mean that CRL will be downloaded from the CA CRL endpoint at every request. It means it will check a local copy of it at every request. Every CRL has a validity period, when it expires, it is downloaded again.

The <metadataPublishing> element is there just to allow WSDL/MetadataExchange endpoints to exist. It also allows the familiar service HTML page to pop up if you hit the endpoint (courtesy of enableHelpPage="true").

Another remark:Current February 2006 WCF CTP bits do not reflect the naming used in this post. For example revocationMode="Cached" was renamed from revocationMode=Offline", but don't be afraid of using it, nevertheless.

I do expect that QueuedDeliveryRequirements property of [BindingRequirements] attribute will be standalone when Indigo ships. There's no point in having a separate attribute for expected transaction semantics and leave out the queued delivery. It's the same concept being pushed down to administrators (binding requirements are fixed requirements which are supposed to be met by the admin - they are the developers' law of expected processing model).

Maybe this attribute should be named [QueuedDelivery], with appropriate property for demanding it (like QueuedDeliveryOption) and a property called OrderedSessionOption, which would handle ordered session maintenance.

There is a common functionality request in modern distributed applications that clients and services (client also being other services) could communicate using different communication protocols and/or different transport semantics inside a single protocol.

For this sample we're going to limit ourselves to HTTP messaging, but this does not limit the scope of the article. Other transport protocols can be added without obstructing other transport mechanisms.

To allow this scenario Indigo (Windows Communication Foundation, WCF) allows multiple endpoints per service to be setup. Service side bindings can, for example, be the following:

The Secure binding uses WS-Security/WS-SecureConversation pair to secure all outgoing and incoming messages using encryption and digital signing. We’re not going to drill down into it in this post. I’m going to write another one where different certificate mechanisms will be discussed.

The SecureReliableTransacted endpoint also uses WS-AtomicTransaction to implement transaction semantics between the client and the service.There are another three bindings (*MTOM) with the same transport semantics as well as MTOM encoding turned on. Since services can support transfer of large binary files, we have also set the maxMessageSize attribute in every binding to 128 MB.

The first endpoint in this example is considered a default one and is mapped to the same binding as the *securereliableMTOM endpoint.

The problem with this is that current WCF’s WSDLExporter maps different endpoints into WSDL ports, but WSDL ports have a requirement to be uniquely named. The default port name construction is done by using the binding type name (i.e. wsProfileBinding, basicProfileBinding), which is concatenated with the contract name.

Therefore, when one has defined multiple bindings from the same binding type a name collision occurs (six WSDL ports with the same QName (namespace and local name)). This can be avoided using a bindingNamespace attribute as well as bindingName attribute. In this example we set the bindingNamespace to http://webservices.gama-system.com/bindings for all bindings and made the name unique by using the bindingName attribute.

There are currently two weird design decisions in multiple binding support of WCF. First bindingNamespace and bindingName attributes are bound to endpoints and not bindings. It would probably be more appropriate to put binding’s namespace and name into the <binding> element. Second, binding name is not propagated into WSDL properly when the same binding is used in two or more endpoints (in this example http://localhost:666/TransferService.svc/ and http://localhost:666/TransferService.svc/securereliableMTOM endpoints are bound to Default binding. If you look closely into the generated WSDL, you will see that the matching WSDL ports are not named after bindingName attribute.

These are non-breaking issues and will probably be addressed for beta 2 of WCF.

In the next Indigo series post, we’ll look closely into the security characteristics of certificate based authentication.

While I don't want to get into a discussion on naming schemes (and yes, I do understand that genuine Beta 1 is reserved for Longhorn Beta 1, but this is too much), these three will give you an option to review what's been hidden on the MSMQ story.

Things to consider:

Try and install MSMQ 3.5 after native MSMQ support in Add/Remove Programs. It will make your life easier.

Indigo RC Beta 1 will only work on official .NET Framework Beta 2. It will not work on any previous CTPs.

Having that installed, we can write some MSMQ Indigo code. A simple calculator service has a simple service contract:

All messages are processed asynchronously, therefore IsOneWay should be set to true on all operations. Any processing is not done at invocation time, but rather at service processing time, which decouples your client from your service. Service implementation, which implements ICanCalculate does the obvious:

There's a AutoCompleteTransaction property set to true in OperationBehaviour attribute, which automatically commits the transaction if no exceptions are thrown.

Up till now, nothing is different from any basic Indigo service. What's beautiful about Indigo architecture is that every single binding detail can be done via configuration. MSMQ endpoint is therefore configured using the following config file:

Setting netProfileMsmqBinding binding to this Indigo service will cause the infrastructure to listen on the specified queue (localhost/private$/CalcQueue). You must set authentication mode and protection level to none, if you're running in MSMQ workgroup mode, since by default it uses an internal certificate (from AD) - and therefore fails on other default security settings.

We can use transaction semantics on the client which will cause to submit all-or-no messages into the service queue:

Client and service are now totally independent. You can send arbitrary number of requests to the service side and they will land in the MSMQ queue. Your service does not need to be running at the same time your client is. When it gets back up, all existing messages will get processed automatically.

Singleton services process all requests using a single service instance. Try changing the ConcurrencyMode property of ServiceBehaviour attribute to obtain different instancing semantics. Having InstanceMode set to PerCall (current default) will disable ConcurrencyMode.Multiple behaviour, which is expected.