When authorizing a client, how do I tell the difference between a connection with anonymous security and a connection with no security?
Anonymous security turns out to offer a surprising amount of protection even though you have no idea who the caller is. With anonymous message security, it's still possible to authenticate the server using the server's credentials and it's possible to protect messages using signing and encrypting. For that reason, some people will want to behave differently if clients are anonymously authenticated than if no security was applied.
Much of the information about client security is stored in the thread local ServiceSecurityContext. ServiceSecurityContext is actually about the remote endpoint, which is the client when running on the service and the service when running on the client. The simplest test is to look at whether a ServiceSecurityContext exists or not by checking ServiceSecurityContext.Current for null. If there's no ServiceSecurityContext, then you know that no security was applied. ServiceSecurityContext also has an IsAnonymous property that tells you whether information exists about the current client connection.
However, there are some cases where a ServiceSecurityContext is created even if there was no security for the client connection. If you have customized authorization through an extensibility point, such as installing a ServiceAuthorizationManager, then WCF may have created a ServiceSecurityContext despite there not actually being any security because it usually makes the authorization logic simpler. In that case, you could look at the tokens associated with the request and determine that some form of security was applied if any kind of token exists.
Next time: Ignoring Bad Requests
I was in a meeting last week with a few WCF users at Microsoft when they asked about performance issues creating client proxies. The first service pack for WCF, which ships at the same time as Orcas, includes some performance fixes for the most frequently seen issues, including the one they described. Wenlong Dong from the WCF performance team was at that meeting and has written up an in-depth description of the changes to client proxy creation, along with some best practices for using client objects.
I'll be at the Ask the Experts reception tonight for the SOA and Business Process conference that Microsoft is hosting. I expect regular articles to resume tomorrow since I've done announcements for the first two days this week already.
Session videos from the UK version of the 2007 MIX conference are now available for download. Go to the session schedule page for the conference and choose to either watch or download videos for the sessions that are available. It looks like about two-thirds of the sessions on both day 1 and day 2 have videos.
Videos from the original MIX conferences are also available for download from the main MIX site.
We're back to the channel pump for another round. In the previous channel pump article we had introduced an asynchronous coroutine between the main channel pump loop and a callback on acquiring a channel throttle. This use of coroutines let us suspend the channel pump until a throttle was available without having to tie up a thread during that wait. That left us with the following channel pump code.
ChannelPumpBEGIN LOOP AcceptChannel IF AcquireThrottle THEN DoWork (runs in the background) ELSE STOP (GotThrottle will run when a throttle is free)END LOOP
GotThrottleDoWork (runs in the background)ChannelPump
DoWorkMessagePumpCloseChannelReleaseThrottle
Now, let's look at the problem of accepting a channel. In many cases, we could fail to actually get a channel when we call AcceptChannel. For example, the channel listener may have been closed, the timeout for listening may have expired, or the network may have gone down. Some of these conditions are transient and some indicate that no more channels will ever be created. What we really want to know after failing to get a channel is whether the channel pump should keep trying.
In a message pump, we can build the desired behavior by calling TryReceive on the channel. Unfortunately, there's no equivalent TryAcceptChannel. We'll have to build our own TryAcceptChannel to replace the call to AcceptChannel in ChannelPump. Under the covers, we'll call AcceptChannel inside of a try-catch block. The trick is to handle the exceptions properly and then return whether TryAcceptChannel succeeded in accepting a channel. Here's how TryAcceptChannel should handle each case.
We can finish up by rewriting ChannelPump to take advantage of our new TryAcceptChannel method.
ChannelPumpBEGIN LOOP IF TryAcceptChannel THEN IF channel IS NULL THEN STOP END IF IF AcquireThrottle THEN DoWork (runs in the background) ELSE STOP (GotThrottle will run when a throttle is free) END IF END IFEND LOOP
Next time: Checking for ServiceSecurityContext
When you create a sessionful channel, that implies the existence of some correlation factor for all of the messages that are associated with the session. For example, the correlation factor for a TCP session is that all of the messages travel over the same TCP connection and the correlation factor for a WS-RM session is that all of the messages belong to the same reliable sequence. There is no way to identify what the correlation factor is at runtime but the channel provides an ISession object so that one correlation factor is distinguishable from another. This is done just by having a unique identifier associated with the session.
Since the session and session identifier are part of the channel interface for a sessionful channel, it's possible to try to access the session as soon as the channel is created. However, there's no guarantee that the session information is valid if the channel is not open at the time. Here is how some of the standard client-side sessions behave if accessed after the channel is created but before the channel is opened.
In short, you can't rely on any meaningful behavior for the session until you're ready to start sending data.
Next time: Substituting for TryAccept
I'm trying to use a username and password with message security but I'm being told that I need to have a certificate on the client or the server depending on the configuration. Is it possible to send username credentials without issuing a certificate?
The reason a certificate is being specified here is because without an additional security mechanism, the password for securing the message would be transmitted without protection. Anybody could intercept the password on its way to the server. There are several configurations that solve that problem by encrypting the password, for which nearly all of the practical methods make use of a certificate. The most common configuration is to use transport security to protect the exchange combined with the message level credentials. You don’t have to use a certificate here but it would rarely make sense to have username credentials if the other transport security mechanisms are available to you.
In rare cases, you may have some external way to protect the messages such that WCF can't detect the presence of the protection. For example, you could transmit the messages over a secured network, such as a VPN. There is probably still a certificate in that case, but it is buried under other software. Although the messages are secure, WCF rejects the configuration. To work around that problem, you can add a layered channel above the transport that lies about the ISecurityCapabilities of the transport channel so that the level of protection for the message is properly reported.
Next time: No Session Before Sending
One of the frequently repeated phrases around SOA development is that SOA allows you to build composite applications that span heterogeneous environments. It's tough to put a perspective on how heterogeneous an environment can be until you look at surveys of protocol usage in the enterprise. There must be several thousand different protocols used on a daily basis, some of which are used only at a single site and some of which are used at millions of sites around the world. Of those thousands of protocols, a single, large application may be using several dozen protocols in conjunction to solve a business problem. Many of the protocols are small and insidious, creeping into an application to take care of an important but not necessarily central problem. A small handful make up the core set of protocols used to move data from system to system in bulk.
Although Microsoft is a large company, we can supply only a limited set of protocols with our products compared to the thousands of protocols that exist in the wild. Primarily, we focus in WCF on the core set of transport protocols and on the infrastructure protocols that have broad and generally applicable uses. I value very highly that all of the features needed to build an application have a consistent design and integrate with each other well. We try to cover the collection of standard protocols such that many customers will be able to get all of the features they need from a single source. Nevertheless, we're never going to be able to cover every protocol in the world and there are going to be many customers that will need to get their features from multiple sources.
That's why I consider extensibility to be a more valuable feature in WCF than any single protocol that comes in the box and that's why I spend so much time writing about how to use WCF extensibility. BizTalk is an example of a product that developed a relatively large market for third-party components so that application builders could source many of the features they needed without having to write the code themselves. My goal is to create a similarly robust developer ecosystem for WCF.
There are already partners starting to deliver into that ecosystem. IBM has published a WCF channel that lets more people talk to existing WebSphere MQ systems. Noemax has created WCF components because they see a market supplying protocols that are optimized for particular communication and consumption patterns. Developer Express wants to make developers building these applications more productive. Seeing an early market emerge based on the extensibility and consistency of the platform makes me feel good that we made the right choices about balancing the features of the product with the openness of the product.
If you're doing interesting things with WCF extensibility, then I want to know about it. I'm not going to promise to publicize every effort, but developers that make themselves heard have a lot of power to influence what gets shipped in future releases.
Next time: When Certificates are Required
Microsoft is hosting a conference on SOA and Business Processes here in Redmond next week running from October 29th to November 2nd. It looks like the final agenda is now available at the conference website for those of you that are attending and want to plan your days. I've already talked to a few people who are registered. Let me know if you are planning to be there and whether you'll be at either the Ask the Experts session on Tuesday or the general reception on Wednesday.
The hierarchy of channels derives from the single interface IChannel. By itself, IChannel is not particularly interesting because it doesn't introduce any new methods for communication. Each channel shape, such as IInputChannel or IDuplexSessionChannel, has its own interface derived from IChannel that describes the capabilities and semantics of the channel.
When you write a channel, you may support variations of your channel for many different channel shapes. For example, you may support both an IInputChannel and an IOutputChannel variation for sending and receiving. Or, you may support both an IDuplexChannel and IDuplexSessionChannel variation depending on whether sessionful communication is needed. During the channel build process, your channel factory or listener will be asked to supply a single particular variation of IChannel. Since the variation is part of the generic contract, the concrete channel implementation that gets returned by the channel factory or listener must support the specified interface.
Here are two best practices that specify more explicitly how that concrete channel implementation should work.
Next time: Extensibility
Is HttpResponse.Cache the preferred way to control caching? HttpResponse is only available in ASP.NET compatibility mode.
No, you don't need ASP.NET compatibility mode to set cache headers. In fact, almost everything from HttpResponse can be done by attaching an HttpResponseMessageProperty to the outbound message. The largest difference is that HttpResponseMessageProperty makes you use a collection of headers rather than having an individual property for each header.
Next time: Best Practice for Channel Shapes
I've answered this question before but it continues to keep being asked so I'll answer it again. This comes up most often when someone is trying to log messages, either through the official message logging feature or on their own by calling ToString.
Why do I get this text rather than the body of the message?
<s:Body>... stream ...</s:Body>
Logging can only display the data that is actually present for a message. Message headers and properties are always buffered but the body content of a message can be either buffered or streamed. If the body content is buffered, then it can easily be played multiple times and so it is displayed while logging. If the body content is streamed, then the data may not be present and it may not be possible to replay the data again in the future. Streamed messages do not attempt to display the body contents to avoid these problems.
If you want to guarantee that you are reading the complete contents of a message, then you have to suck all of the message contents out using a reader or writer yourself. I've seen people recommend calling CreateBufferedCopy as a workaround but this just happens to work with the common implementations of Message today. There's no guarantee that the messages you create from a MessageBuffer are going to be buffered rather than streamed.
Next time: Controlling HTTP Caching
A common corner-case in programming is what happens when multiple operations are attempted at the same time. One way to avoid the troubles of this corner-case is to simply prohibit having multiple operations occur simultaneously. However, it typically isn't possible to make this exclusion work in a universal fashion. Consider an object that prevents having multiple operations but permits having long-running (perhaps indefinitely long-running) operations. When faced with a long-running operation, it's desirable to have some way to prematurely stop that operation. The trick is that stopping an operation is often an operation in itself, violating the guarantee that only one operation runs at a time for at least a tiny period during shutdown of the object. This makes shutdown particularly prone to being a corner-case.
Channels don't make any guarantees about the simultaneous execution of methods, but it can still be confusing to describe their behavior during shutdown. The basic operations of accept and receive are often long-running, meaning that there frequently is going to be some overlap between these operations and the end of the channel's lifetime. The accept or receive operation needs to have some outcome when it completes. How can that outcome be determined? Here's a rule of thumb to guess the behavior of any related method for a channel. This rule of thumb can be applied for example when shutting down the system or when a session finishes all of its input.
For example, the TryReceive method returns both an object and a conditional report of success or failure. According to the rule of thumb, when the channel has no more data, it should return null for the received message. Also, it should report a conditional result of success (true, in this case) for the attempt to receive a message.
Next time: Body is a Stream
The documentation for configuring a port with an SSL certificate shows example commands using the httpcfg.exe program. Starting with Windows Vista, httpcfg.exe was replaced in function by the netsh program that comes with the operating system. This is more convenient than having to download a separate tool, but it means that the syntax that you need to use changes slightly.
Let's assume that you've created a certificate and have already installed it using either the command line or the MMC certificate snap-in. Now, through the MMC snap-in, get the thumbprint of the certificate you want to install to a port if you don't already know what the thumbprint is. This process hasn't changed much so your existing directions should continue to work. The thumbprint for the test certificate I generated was 45d08a92798460d84e4ce157f31662b36c4edbff. When you copy the thumbprint from the snap-in, don't forget to remove all of the spaces.
You'll need to run netsh from an elevated command prompt. This first command installs my generated test certificate to port 8000 for the wildcard IP address.
netsh http add sslcert ipport=0.0.0.0:8000 certhash=45d08a92798460d84e4ce157f31662b36c4edbff appid={00112233-4455-6677-8899-AABBCCDDEEFF}
The only new thing here is the appid, which is a guid that can be used to associate the certificate with a particular application. You can check the installed certificates with the following command.
netsh http show sslcert
That gives me the following certificate description.
SSL Certificate bindings:------------------------- IP:port : 0.0.0.0:8000 Certificate Hash : 45d08a92798460d84e4ce157f31662b36c4edbff Application ID : {00112233-4455-6677-8899-aabbccddeeff} Certificate Store Name : (null) Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : (null) DS Mapper Usage : Disabled Negotiate Client Certificate : Disabled
Finally, you can remove the certificate associated with a particular address to undo the earlier changes.
netsh http delete sslcert ipport=0.0.0.0:8000
Next time: Shutting Down a Channel
With all the things that were happening during the summer, I evidently missed out on two Channel 9 videos that were done on the Orcas version of WCF. These cover some of the features that are new in the upcoming .Net Framework 3.5 release.
In the first video Eugene Osovetsky talks about using JSON in the programming model and serialization, which is one of several new features for writing non-SOAP web services.
In the second video Pravin Indurkar talks about integrating web services with workflows using the Workflow Services technology codenamed Silver.
There's a newly minted RFC 5023 out this week covering the Atom Publishing Protocol. AtomPub is an application protocol for drafting and publishing a collection of documents over HTTP. It comes almost two years after the related Atom XML syndication format was published as RFC 4287. AtomPub uses the standard GET, POST, PUT, and DELETE verbs to interact with documents and document collections on a server. Each document is essentially just an XML metadata blob that contains a content block and can be extended to create microformats for specific document types.
Back when I did an overview of custom namespaces, I omitted any namespace declarations that wouldn't appear in the final metadata. One of those declarations is the default namespace for data contracts. I had two example data contracts, one for faults and one for normal messages, although they actually work exactly the same in practice.
[DataContract(Namespace = "http://example.com/faultcontract/datacontract")]public class MyFault{ [DataMember] public string detail;}[DataContract(Namespace = "http://example.com/datacontract")]public class MyData{ [DataMember] public string data;}
These data contracts include an explicitly declared XML namespace. However, you can modify the test program in the earlier article to see what happens when those namespace declarations are removed. What you end up with is an ugly looking namespace based on a fixed prefix http://schemas.datacontract.org/2004/07/ and a suffix that is the CLR namespace.
If you want to get rid of that default namespace for every data contract you define, then you can add a ContractNamespaceAttribute to the assembly. This attribute defines the default XML namespace for data contracts that are located in a particular CLR namespace. You can retrieve a ContractNamespaceAttribute in the standard way for assembly attributes by calling GetCustomAttributes on the assembly with the ContractNamespaceAttribute type.
Next time: Configuring SSL Certificates for Windows Vista
Last time, we were looking at how to control flow through a channel pump by introducing the concept of a throttle. The implementation of the throttle was a semaphore, allowing us to limit the number of channels active in the system at any point in time. This lead to a straightforward approach; the channel pump stopped to acquire the semaphore each time before starting new work.
ChannelPumpBEGIN LOOP AcceptChannel AcquireThrottle DoWorkEND LOOP
The straightforward approach to throttling has the drawback that a thread of execution is blocked sitting in the ChannelPump loop. We can have several instances of DoWork running simultaneously by executing DoWork asynchronously. We can similarly use asynchronous execution to straighten out the ChannelPump loop. This produces an approach where execution ping-pongs between two asynchronous methods.
The key to the ping-pong approach is that the asynchronous execution can wait to start until a condition is satisfied. Let's change AcquireThrottle to return immediately from the call rather than blocking. If AcquireThrottle returns true, then it means that we acquired the semaphore. If AcquireThrottle returns false, then it means that we weren't successful but in the future a method will be executed once the semaphore is available. Let's call that method GotThrottle.
We can now bounce execution from ChannelPump to GotThrottle and then back to ChannelPump in the future.
ChannelPumpBEGIN LOOP AcceptChannel IF AcquireThrottle THEN DoWork ELSE STOPEND LOOP
GotThrottleDoWorkChannelPump
There's no longer any need to wait for the semaphore to become available. There is some code waiting to start running pending availability of the semaphore but it doesn't have to be assigned any resources. We have to be careful now though about being very precise with asynchronous execution. Since ChannelPump is calling itself through an intermediary, synchronous execution of those calls would lead to building up an unlimited number of stack frames. We have also created some new complexity for ourselves in the form of state management between the calls.
That's all for the channel pump this week. I'll have some more articles in this series in the future.
Next time: ContractNamespaceAttribute
When programming using channels, the common usage pattern for the server is to sit in a loop accepting channels. This loop, sometimes called a pump, cycles through each time accepting a channel and initiating some work. Let's look at the most basic channel pump possible. I'm going to write things with pseudocode to make it even simpler.
ChannelPumpBEGIN LOOP AcceptChannel DoWorkEND LOOP
We'll assume that DoWork goes off in the background to perform some asynchronous processing and will take care of cleaning up resources. There's nothing we could cut out of this pump. There are many things that we'd have to add though to make the pump survive more than a few iterations without blowing up.
One problem with the pump is that we spin through it as fast as possible. The pump will continue kicking off additional work even if the system can't withstand the load. We need some way to throttle the flow of data.
A simple throttling mechanism is to limit the number of channels that we can have working at once. Let's add a semaphore to count the number of active channels and prevent DoWork from being called if we're already using all of the available work throttles. We'll need to change ChannelPump and also put some details into DoWork.
There are some new constructs here but the only one that needs explanation is MessagePump. MessagePump is what actually receives messages from the channel and processes them. All of DoWork runs asynchronously though so ChannelPump will continue running while DoWork is taking place.
Unfortunately, ChannelPump will block when AcquireThrottle isn't able to acquire the semaphore immediately. This does what we want because DoWork won't get called but it's less than ideal that we sit there waiting. Next time, we'll look at how to change ChannelPump to solve the blocking problem.
Next time: Unblocking Flow Throttles
How do I use % Feature X% from ASP.NET in a WCF service?
ASP.NET has an HTTP-centric application model with many great features specialized for web development in IIS. WCF is transport and host agnostic. Out of the box, WCF supports most of the features of ASP.NET in a way that makes sense independent of HTTP and IIS. Some of the features excluded from that set are supported as part of the specific implementation for the HTTP transport.
If you're porting an application from ASP.NET to WCF, you may find that one of the ASP.NET features not in the regularly supported subset has been made integral to the design of your application. WCF has an ASP.NET compatibility mode that gives you both the features and limitations of that environment. Using compatibility mode gets you your favorite ASP.NET %Feature X%:
but the preference should be to use host and transport agnostic equivalents except when trying to get code working that already use these ASP.NET features.
This article was originally just about Server.MapPath, but I changed it because advice for the other features would read exactly the same.
Next time: Flow Throttles
I want my service to have a set of endpoints that are conditionally enabled. Is it possible to put all of the endpoint definitions in a single configuration file rather than changing configuration depending on the conditions?
Due to the design of configuration, it's difficult for a service to pull from alternative configuration files or sources. Therefore, the approaches that rely on a single configuration file tend to work out better. The problem at hand then is to have a single, big configuration file that gets loaded by the service and a subset of that configuration file that actually gets enabled. Configuration doesn't have the concept of conditionals so we're going to need some place outside of the configuration system to perform the evaluation.
This sounds like a job for subclassing ServiceHost to override ApplyConfiguration. The base implementation will load all of the endpoints from the configuration file. Code in ApplyConfiguration can then evaluate the conditions and strip out all of the endpoints from the service description that shouldn't be enabled. This may not be as efficient as only loading the appropriate endpoints to begin with, but the process takes place only once and before any network traffic occurs. It seems more valuable to keep the implementation simple.
Next time: Server.MapPath
What replacement in WCF should I be using for an ASP.NET SoapExtension?
A SOAP extension is an extensibility point in ASMX that allows processing of SOAP messages during sending and receiving. WCF has many extensibility points for processing messages so the question is really about which extensibility point is the closest match to the functionality provided by the SoapExtension class. SoapExtension has a single ProcessMessage method that is called for four different message states (the descriptions are from the server's perspective):
All of these calls could be replaced by an IDispatchMessageFormatter, which allows control over the serialization process. You could add hooks to the DeserializeRequest and SerializeReply methods of an IDispatchMessageFormatter to process the messages immediately before or after the serializer invocation. However, this requires knowledge about the serialization process. It lacks the convenience of having a pipeline of processors that don't require knowledge of the steps of the serialization pipeline. Although the functionality is centralized as it is in SoapExtension, this is the wrong extensibility point to use.
Message inspectors are a more convenient mechanism for processing messages while they are in an XML form. The AfterReceiveRequest and BeforeSendReply methods of an IDispatchMessageInspector correspond to the BeforeDeserialize and AfterSerialize states.
Parameter inspectors are a more convenient mechanism for processing service method invocations while they are in a parameterized form. The AfterCall and BeforeCall methods of an IParameterInspector correspond to the AfterDeserialize and BeforeSerialize states.
WCF has an equivalent client interface for a message inspector and uses the same interface for a parameter inspector.
Next time: Stripping Out Extra Endpoints
Inside a service, there's a fundamental loop running whose job it is to create channels for the incoming connections to the service. There's another loop that runs later, which you may argue is equally fundamental, that reads messages from each channel to determine the actual service invocation. Every one of these service requests though was preceded at some point by a channel being accepted (one channel may produce multiple requests of course).
Depending on how things are configured, the service may be running a transactional loop or a non-transactional loop. The transactional loop runs when the service needs to create its own transaction for reading messages. As a custom channel author, the two loops have different implications for how your channel gets used.
In the non-transactional case, the service sits in a loop calling BeginAcceptChannel on the topmost channel listener. This loop continues until the listener fails to give back a channel or the listener faults. The loop pauses if a quota is reached that prevents more channels from being accepted, but the loop can later be restarted when the quota is no longer an issue.
In the transactional case, the service first sits in a loop calling WaitForChannel. When WaitForChannel completes, the loop creates a new transaction and calls AcceptChannel. The use of WaitForChannel is an optimization to reduce the number of unnecessary transactions that get created. The loop will later complete or abort the transaction as appropriate but otherwise functions very similarly from this point.
Next time: SOAP Extensions
The W3C Web Services Policy Working Group is putting together a pair of documents to help policy users and authors with the new version of WS-Policy. This includes an explanation of how policy works and best practices for policy authors. There's currently a three week period for collecting comments, which runs through October 19th.
You can get both of these documents from the W3C web site:
Copies of the standard itself are linked from the earlier announcement I made.