Nicholas Allen's Indigo Blog

Windows Communication Foundation From the Inside

October, 2007

  • Nicholas Allen's Indigo Blog

    Checking for ServiceSecurityContext

    • 1 Comments

    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

  • Nicholas Allen's Indigo Blog

    Better Proxy Clients

    • 0 Comments

    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.

  • Nicholas Allen's Indigo Blog

    Videos from MIX UK

    • 0 Comments

    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.

  • Nicholas Allen's Indigo Blog

    Substituting for TryAccept

    • 1 Comments

    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.

    ChannelPump
    BEGIN LOOP
    AcceptChannel
    IF AcquireThrottle THEN
    DoWork (runs in the background)
    ELSE
    STOP (GotThrottle will run when a throttle is free)
    END LOOP
    GotThrottle
    DoWork (runs in the background)
    ChannelPump
    DoWork
    MessagePump
    CloseChannel
    ReleaseThrottle

    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.

    • AcceptChannel completes normally and returned a channel: success
    • AcceptChannel completes normally and returned null: success (read this article if you're unclear why)
    • AcceptChannel fails due to being aborted or faulted: success (read the same article above if you're unclear why)
    • AcceptChannel fails due to a timeout: retry
    • AcceptChannel fails due to some other reason: either retry or abort depending on whether the exception is recoverable

    We can finish up by rewriting ChannelPump to take advantage of our new TryAcceptChannel method.

    ChannelPump
    BEGIN 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 IF
    END LOOP
    GotThrottle
    DoWork (runs in the background)
    ChannelPump
    DoWork
    MessagePump
    CloseChannel
    ReleaseThrottle

    Next time: Checking for ServiceSecurityContext

  • Nicholas Allen's Indigo Blog

    No Session Before Sending

    • 1 Comments

    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.

    • TCP session: A unique identifier is generated on the fly, this identifier will continue to be used after the channel is opened.
    • Reliable session: The session identifier is empty, an identifier will be created when the channel is opened.
    • Security session: Trying to access the identifier produces a runtime exception, an identifier will be created when 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

  • Nicholas Allen's Indigo Blog

    When Certificates are Required

    • 1 Comments

    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

  • Nicholas Allen's Indigo Blog

    Extensibility

    • 1 Comments

    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

  • Nicholas Allen's Indigo Blog

    SOA & Business Process Conference Next Week

    • 3 Comments

    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.

  • Nicholas Allen's Indigo Blog

    Best Practice for Channel Shapes

    • 1 Comments

    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.

    1. Your channel factory or listener can't substitute an extended variation of a channel shape even though the type system lets you cast to the parent type. For example, IDuplexChannel and IInputSessionChannel both derive from IInputChannel. It would be wrong to return a duplex or sessionful channel if asked for an IInputChannel though. The build process is asking for the semantics of a one-way, non-sessionful input channel rather than just a type that has a callable interface compatible with IInputChannel. Use separate shape-changing channels if you need to adapt a channel implementation or supply a channel implementation that natively supports the correct shape.
    2. Each concrete channel implementation should only implement a single channel shape. While it's possible to write a single implementation that simultaneously supports multiple channel interfaces, you should instead have multiple channel implementations each supporting a single channel interface. The fact that you have different channel implementations for different shapes is hidden by the channel factory or listener so there's no additional complexity that the user of your implementation needs to worry about.

    Next time: Extensibility

  • Nicholas Allen's Indigo Blog

    Controlling HTTP Caching

    • 3 Comments

    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

  • Nicholas Allen's Indigo Blog

    Body is a Stream

    • 5 Comments

    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

  • Nicholas Allen's Indigo Blog

    Shutting Down a Channel

    • 4 Comments

    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.

    1. If the operation is supposed to return some object, then that object is null. We didn't actually get an object instance during the operation.
    2. If the operation is conditional and reports whether it succeeded or failed, then the outcome is that it succeeded. A failure indicates that something went wrong, but there's nothing wrong with being done.

    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

  • Nicholas Allen's Indigo Blog

    Configuring SSL Certificates for Windows Vista

    • 5 Comments

    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

  • Nicholas Allen's Indigo Blog

    Two Videos on Orcas

    • 0 Comments

    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.

  • Nicholas Allen's Indigo Blog

    AtomPub RFC Released

    • 0 Comments

    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.

  • Nicholas Allen's Indigo Blog

    ContractNamespaceAttribute

    • 1 Comments

    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

  • Nicholas Allen's Indigo Blog

    Unblocking Flow Throttles

    • 3 Comments

    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.

    ChannelPump
    BEGIN LOOP
    AcceptChannel
    AcquireThrottle
    DoWork
    END LOOP
    DoWork
    MessagePump
    CloseChannel
    ReleaseThrottle

    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.

    ChannelPump
    BEGIN LOOP
    AcceptChannel
    IF AcquireThrottle THEN
    DoWork
    ELSE
    STOP
    END LOOP
    GotThrottle
    DoWork
    ChannelPump
    DoWork
    MessagePump
    CloseChannel
    ReleaseThrottle

    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

  • Nicholas Allen's Indigo Blog

    Flow Throttles

    • 2 Comments

    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.

    ChannelPump
    BEGIN LOOP
    AcceptChannel
    DoWork
    END 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.

    ChannelPump
    BEGIN LOOP
    AcceptChannel
    AcquireThrottle
    DoWork
    END LOOP
    DoWork
    MessagePump
    CloseChannel
    ReleaseThrottle

    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

  • Nicholas Allen's Indigo Blog

    Server.MapPath

    • 8 Comments

    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%:

    • Session state
    • System.Web authorization, impersonation, and globalization
    • IHttpModule
    • AppSettings
    • HttpContext
    • MapPath

    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

  • Nicholas Allen's Indigo Blog

    Stripping Out Extra Endpoints

    • 1 Comments

    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

  • Nicholas Allen's Indigo Blog

    SOAP Extensions

    • 1 Comments

    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):

    1. BeforeDeserialize, the request before going through the XML serializer
    2. AfterDeserialize, the request after going through the XML serializer
    3. BeforeSerialize, the response before going through the XML serializer
    4. AfterSerialize, the response after going through the XML serializer

    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

  • Nicholas Allen's Indigo Blog

    Always Begin with Accept

    • 1 Comments

    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

  • Nicholas Allen's Indigo Blog

    Help for Policy Authors

    • 0 Comments

    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.

Page 1 of 1 (23 items)