Nicholas Allen's Indigo Blog

Windows Communication Foundation From the Inside

June, 2007

  • Nicholas Allen's Indigo Blog

    Michele's Webcasts Start Monday

    • 1 Comments

    Michele Bustamante will be giving 15 hours of webcasts over the next 10 weeks starting on Monday. She may even mention her new book. It looks like each of the talks has an independent set of topics so you can join in even if you're only able to make some of the dates.

    1. Overview- Monday, July 02, 2007 9:00 AM Pacific Time
    2. Contracts- Monday, July 09, 2007 9:00 AM Pacific Time
    3. Contract Versioning- Wednesday, July 11, 2007 10:00 AM Pacific Time
    4. Exceptions and Faults- Friday, July 13, 2007 9:00 AM Pacific Time
    5. Bindings- Monday, July 23, 2007 9:00 AM Pacific Time
    6. Hosting- Wednesday, July 25, 2007 10:00 AM Pacific Time
    7. Messaging Patterns- Friday, August 10, 2007 9:00 AM Pacific Time
    8. Instancing Modes- Monday, August 13, 2007 9:00 AM Pacific Time
    9. Concurrency, Throughput, and Throttling- Wednesday, August 15, 2007 10:00 AM Pacific Time
    10. Security Fundamentals- Friday, August 24, 2007 9:00 AM Pacific Time
    11. Federated Security- Monday, August 27, 2007 9:00 AM Pacific Time
    12. Reliable Messaging- Wednesday, August 29, 2007 9:00 AM Pacific Time
    13. Transactions- Monday, September 03, 2007 9:00 AM Pacific Time
    14. Message Queuing- Wednesday, September 05, 2007 9:00 AM Pacific Time
    15. Extensibility- Friday, September 07, 2007 9:00 AM Pacific Time
  • Nicholas Allen's Indigo Blog

    WSDL 2.0 Completed

    • 1 Comments

    Yesterday morning it was announced to the W3C membership that the Web Services Description Language 2.0 (WSDL 2.0) was officially a standard. WSDL is an XML language for describing web services using an abstract model for service operations. I mentioned a few weeks ago that WSDL had become a Proposed Recommendation, and the final version has come out a few days after the end of the comment period with a small number of minor revisions. You can get all of the parts of the specification at the W3C site.

  • Nicholas Allen's Indigo Blog

    Glossary Updates

    • 1 Comments

    This year I've added a dozen additional categories to cover the topics that I was writing about most frequently but didn't have any specific label for. You can read about the older categories in the original glossary. Some of these categories go with article series that haven't been published yet. I don't intend to go back through the entire history to update articles with the new categories. I will update articles as I see them though.

    Addressing- Articles about WS-Addressing and other ways of referring to endpoints.

    Behaviors- Articles about the behavior model of WCF services.

    Channel Dev Tour- Series of articles on building and using channels.

    Contracts- Articles about service and operation contracts.

    Faults- Articles about the SOAP model for faults and error handling.

    Message Security- Articles about SOAP-level security protocols.

    Proxies- Articles about the proxy objects generated for talking with services.

    Queues- Articles about MSMQ and other queuing systems.

    Quotas- Articles about the throttles and limits that bound service operations.

    Reliable Messaging- Articles about WS-ReliableMessaging and other reliable delivery guarantees.

    Serialization- Articles about the conversion between strongly-typed objects and messages.

    Service Model- Articles about one of the WCF service-level topics.

    Next time: ChannelFactory Contract and Generated Types

  • Nicholas Allen's Indigo Blog

    Session Lifetime on the Server

    • 4 Comments

    Why doesn't increasing the InactivityTimeout of a reliable session keep client connections alive for longer?

    When using a reliable session, there are two different inactivity timers that must be satisfied to keep the connection alive. If either inactivity timer goes off, then the connection is killed.

    The first inactivity timer is on the reliable session and is called InactivityTimeout. This inactivity timer fires if no messages, either application or infrastructure, are received within the timeout period. An infrastructure message is a message that is generated for the purpose of one of the protocols in the channel stack, such as a keep alive or an acknowledgment, rather than containing application data.

    The second inactivity timer is on the service and uses the ReceiveTimeout setting of the binding. This inactivity timer fires if no application messages are received within the timeout period.

    Since the connection is killed if either inactivity timer fires, increasing InactivityTimeout once it is greater than ReceiveTimeout has no effect. The default for both of these timeouts is 10 minutes, so you always have to increase ReceiveTimeout first to make a difference.

    Next time: Glossary Updates

  • Nicholas Allen's Indigo Blog

    Changing the ChannelFactory Contract

    • 3 Comments

    A ChannelFactory is a local client endpoint that can stamp out proxy instances for a remote service endpoint. Knowing this detail about the local endpoint is essential when the client endpoint that gets automatically generated for the ChannelFactory doesn’t do what you want. Let's take a generic untyped echo service as the remote service endpoint for an example.

    [ServiceContract]
    public interface IService
    {
    [OperationContract(Action="*", ReplyAction="*")]
    Message Echo(Message message);
    }

    public class Service : IService
    {
    public Message Echo(Message message)
    {
    return Message.CreateMessage(message.Version, "", message.GetReaderAtBodyContents());
    }
    }

    The fact that the interface is called IService is pretty unimportant. The only operation on the interface has the basic form of request-reply with no fixed action required for either the request or reply message. Rather than having to know about IService, it makes sense for clients to simply refer to this service using the built-in IRequestChannel. Sometimes this works without doing anything special, but we can find circumstances where the automatically generated local client endpoint doesn't correctly guess what you're trying to do. Here's some code that starts an instance of IService and tries to connect to it as an IRequestChannel over TCP.

    string uri = "net.tcp://localhost:800/";
    Binding binding = new NetTcpBinding();

    ServiceHost service = new ServiceHost(typeof(Service));
    service.AddServiceEndpoint(typeof(IService), binding, uri);
    service.Open();

    ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(binding, new EndpointAddress(uri));
    IRequestChannel channel = factory.CreateChannel();

    XmlReader reader = XmlReader.Create(new StringReader("<MyData>text</MyData>"));
    Message message = Message.CreateMessage(binding.MessageVersion, "", reader);
    Console.WriteLine(channel.Request(message));
    message.Close();

    factory.Close();
    service.Close();

    If we try to run this code, it fails with an InvalidOperationException: "Contract does not allow Session, but Binding 'NetTcpBinding' does not support Datagram or is not configured properly to support it."

    Where is the contract definition? Well, we don't have access to it because IRequestChannel is a built-in type. However, we can modify the contract that has been associated with the ChannelFactory because it is just a local client endpoint.

    factory.Endpoint.Contract.SessionMode = SessionMode.Allowed;

    Now, we have a contract that makes both the local and remote endpoints happy so we can get our echoed message.

    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
    <a:Action s:mustUnderstand="1" />
    <a:RelatesTo>urn:uuid:c41a2b38-e8de-4215-ab70-69ce823af7dc</a:RelatesTo>
    <a:To s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/anonymous</a:To>
    </s:Header>
    <s:Body>
    <MyData>text</MyData>
    </s:Body>
    </s:Envelope>

    Next time: Session Lifetime on the Server

  • Nicholas Allen's Indigo Blog

    Spot the Intern

    • 1 Comments

    Microsoft runs intern programs all the time, but there's a particularly large wave that comes for summer college internships. This is the wave that has tons of weekly events, product fairs, and a summer-end party at Bill's house. After watching this year's candidates trickle through for their interviews in the spring, the last few weeks have had a noticeable rush of those that accepted offers. I don't know how many interns there are in total, although I've read that it's somewhere around a thousand in the area. Nevertheless, the number is quite small compared to the size of the regular employee workforce. For some reason though, it is possible to spot the intern if you have a careful eye. This is because

    1. They are frequently in the vicinity of the intern staples beer and pizza, a fact which attracts many non-intern visitors to their events
    2. Although Microsoft employees receive enough free shirts to rarely need laundry services, only the interns are brave enough to wear them
    3. The urge to go to the grocery store and get an entire cart of nothing but microwaveable dinners and koolaid packets fades quickly after graduation
  • Nicholas Allen's Indigo Blog

    Where to Find Training

    • 1 Comments

    A few people have asked me to post advertisements for their WCF training classes. I have a general policy of not making recommendations for commercial offerings unless I've actually tried the class or seen the class material. Since it's very unlikely that I'll be spending time checking out the various classes, that means it's also unlikely that I'll be posting announcements for third-party offerings.

    However, you shouldn't let that stop you from getting the word out about your training sessions. The wcf.netfx3.com site does have a list of training offerings that was put together by Clemens Vasters. If you are buying or selling training, then you can use that site to get the word out or find out about what's being offered. Since I'm not involved in putting the list together, you'll have to contact Clemens for any details.

    Next time: Changing the ChannelFactory Contract

  • Nicholas Allen's Indigo Blog

    Abort Instances on Errors

    • 3 Comments

    How do I kill off an instance of my service when an error occurs?

    Call Abort. More specifically, call Abort on the InstanceContext that corresponds to the service instance that you wish to be rid of.

    This may be dangerous if your service is implemented by a singleton instance because then you will have no way to get more instances of your service.

    Next time: Where to Find Training

  • Nicholas Allen's Indigo Blog

    Subqueues

    • 1 Comments

    How do I create a subqueue for dead lettering messages with MSMQ?

    Subqueues are a relatively new feature of MSMQ that do not actually involve creating a new physical queue. Instead, the subqueue represents a logical group of messages that are stored inside the parent physical queue. Messages can cheaply move between the parent queue and the subqueue.

    Since there is no physical queue being created, the distinguishing feature of subqueues must therefore be the address used to put messages into the queue. The subqueue syntax adds to the URI scheme for referring to a queue. Here is the URI scheme for net.msmq.

    net.msmq://hostname/[private/]queuename[;subqueuename]

    The bracketed sections in the above scheme represent the optional parts.

    Next time: Abort Instances on Errors

  • Nicholas Allen's Indigo Blog

    Irrevocable Certificates

    • 1 Comments

    A certificate revocation list is a way to revoke and expire an individual certificate at any time. Revocation lists are a complement to expiration times because a certificate may be bad even when it's not particularly old, such as when someone has compromised the private key of the certificate. Control of the certificate revocation list is therefore very sensitive. You wouldn't want an attacker to be able to add or remove entries from the revocation list as this would allow them to manipulate the list of valid certificates and prevent a compromised certificate from being detected. Certificates can chain back to a revocation list just as they chain back to an issuer certificate. The whole combination is generally signed so that the directions to the revocation list can't be modified and the revocation list itself can't be forged.

    When you create your own certificates though, you often aren't going to go to the trouble of setting up a revocation list for your issued certificates. The default of WCF is to be secure, which means checking the revocation list of the client and server certificate. This can cause problems if you intend to use certificates that have no revocation list. You can disable the check of the revocation list by setting the RevocationMode to NoCheck.

    service.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
    factory.Credentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;

    Since you're validating the certificate of the opposite party, the ServiceHost is the one that has the setting for client certificates and the ChannelFactory is the one that has the setting for service certificates.

    Next time: Subqueues

  • Nicholas Allen's Indigo Blog

    Slow Proxy Discovery

    • 3 Comments

    The initial connection to a web service is always going to take some time to complete. If you've been reading for a while, then you know that calling Open on the proxy client before the first call is one way to get the initial connection expense out of the way. Otherwise, the initial connection happens when the first call is made. Successive calls tend to be faster as you've completed the initial work and warmed up all of the relevant network resources.

    However, the initial call sometimes takes far longer than you'd expect even though you know there is some additional work going on. In these cases, there is a noticeable delay, sometimes on the order of five, ten, or even twenty seconds. This much longer delay is typically caused by a network resource being unavailable. For example,

    • You may be trying to resolve a host name and your DNS server isn't working.
    • You may be trying to contact a domain controller that isn't present.
    • You may be retrying authorization requests with bad credentials.
    • You may have misconfigured proxy settings on your system.

    The last one is my favorite because it is such an unexpected way to be tripped up. Automatic proxy detection is a scriptable way to find proxy servers with little or no configuration on the user's part. It uses a variety of search mechanisms, such as DHCP, DNS, and the registry, in a predefined order to locate a proxy configuration script. Since automatic proxy detection has little interaction with the user and little visible effect, it is easy to forget that it exists until it fails entirely.

    There is no foolproof way to diagnose issues with excessively long first call times. Often, you need to do some data gathering first to figure out what network resource is failing to respond and why someone is attempting to access that resource. A good way to get started with this investigation is to simply run the client under a debugger and collect a stack trace during the first call. Since the vast majority of the time is spent sitting around waiting for the offending method to complete, you can frequently find out who is causing the problem rather quickly although you still have to figure out how to fix it.

    Next time: Irrevocable Certificates

  • Nicholas Allen's Indigo Blog

    Between 50 and 100

    • 2 Comments

    Services have a built-in defense mechanism, called throttles, to prevent them from taking over too much of the system's resources. There are three of these throttles that are controllable through a ServiceThrottlingBehavior that you can supply to the service.

    • MaxConcurrentCalls limits the number of service calls (messages) that the service will have processing at one time. You may get less than this maximum number if the concurrency or instancing behavior of your service does not allow processing multiple messages.
    • MaxConcurrentSessions limits the number of persistent connections (sessionful channels) that the service will accept messages from at one time. Again, you need a minimum level of concurrency in your service for this to become an issue.
    • MaxConcurrentInstances limits the number of copies of the service (instance contexts) that can exist. This is only interesting if your service is permitted to have multiple instances.

    Knowledge of these throttle values can help you track down problems when you are achieving concurrency for a while with client connections but suddenly hit a wall when the number of clients is pushed farther. These throttles are going to stack with the number of clients that are buffered at the transport level, for example by having the connections sit in kernel TCP buffers. You can tell the two apart because the throttles are what drive the steady-state simultaneous client processing load while the transport quotas stack with the throttles for the initial maximum client backlog.

    The number of instances is unlimited by default, but there are very conservative default throttles of 10 simultaneous sessions and 16 simultaneous service calls. During the beta, the number of sessions was unlimited and the MaxConcurrentCalls throttle was set to 64, which made it easy to guess when someone had a throttling problem. They would report that the throughput mysteriously fell off somewhere between 50 and 100 clients.

    Next time: Slow Proxy Discovery

  • Nicholas Allen's Indigo Blog

    Logging Binary Messages

    • 1 Comments

    I've added a binary message encoder but the logged messages are still in plain text. How do I configure the service to produce binary messages?

    Message logging always outputs the decoded message. If you have set everything up right, then that means that the message will be in plain text. The point of message logging is to record messages so that you can view them later. You probably don't know how to read a binary message. The output of message logging has no relationship to the transfer format of the message.

    The binary message in this question can be replaced with encrypted message or any similar on the wire transformation. You can put a proxy between the client and server if you want to see exactly what gets sent on the wire. It wouldn't be possible to create an equivalent capture from within WCF because the native networking stack may be changing the protocol stream.

    Next time: Between 50 and 100

  • Nicholas Allen's Indigo Blog

    BeginInvoke Bugs

    • 3 Comments

    A delegate is a special type that can be bound at execution time to a method invocation. Normally you'd think of method invocations as being synchronous, but delegates can be executed either synchronously in the obvious way or asynchronously by introducing an extra thread of execution. An asynchronous delegate invocation uses the standard BeginInvoke and EndInvoke pattern, with the option to provide a callback for when the work is complete. You would expect that the asynchronous delegate pattern would be an easy way to make asynchronous calls to a web service. You would be wrong.

    [ServiceContract]
    public interface IService
    {
    [OperationContract]
    string Echo(string text);
    }

    public class Service : IService
    {
    public string Echo(string text)
    {
    Thread.Sleep(5000);
    return text;
    }
    }

    public delegate string EchoDelegate(string text);

    public class BeginInvokeDelegate
    {
    static void Callback(IAsyncResult result)
    {
    Console.WriteLine("In callback.");
    }

    static void Main(string[] args)
    {
    string uri = "http://localhost:8000/";
    ServiceHost service = new ServiceHost(typeof(Service));
    service.AddServiceEndpoint(typeof(IService), new BasicHttpBinding(), uri);
    service.Open();

    ChannelFactory<IService> factory = new ChannelFactory<IService>(new BasicHttpBinding(), new EndpointAddress(uri));
    IService proxy = factory.CreateChannel();

    EchoDelegate d = new EchoDelegate(proxy.Echo);
    IAsyncResult result = d.BeginInvoke("foo", new AsyncCallback(Callback), null);
    Console.WriteLine("Returned.");
    Console.WriteLine(d.EndInvoke(result));

    factory.Close();
    service.Close();
    Console.ReadLine();
    }
    }

    The code above is using a ChannelFactory against a synchronous version of the Echo interface. The client and service are decoupled so it would have been legal to generate a client proxy that expressed the Echo interface using an asynchronous representation regardless of how Echo is implemented on the server. Instead, the code attempts to make the service call asynchronous by wrapping it in a delegate and using BeginInvoke. If you run this code, then you'll see that the call to BeginInvoke does not complete until after the Echo service call has returned. This defeats the purpose of using the asynchronous pattern. The problem is that BeginInvoke knows about and only works with specific types of proxy objects, which do not include the proxy objects generated by ChannelFactory. The right way to make an asynchronous service call is to generate a proxy that has an asynchronous representation of the service method.

    Next time: Logging Binary Messages

  • Nicholas Allen's Indigo Blog

    Single Shot Security Requires Request Reply

    • 1 Comments

    Why does message security stop working when the transport isn't HTTP?

    There are two ways that messages can be secured using message security: single shot security (per message security) and conversations (multiple messages). The difference between these two modes is that a secure conversation has established an ongoing security context to use for exchanging messages. Single shot security doesn't have any security context because each message is secured individually.

    The use of different security patterns impacts which messaging patterns you can choose to use with a web service. Providing message security for a service operation requires correlating the incoming and outgoing messages together. There is only one messaging pattern that is naturally correlated, and that is the request-reply messaging pattern. The request-reply messaging pattern is naturally correlated because each request message is associated with one and only one response message. One-way and duplex messaging patterns do not offer automatic correlation between request and response messages. When a security context exists, that security session can be used to correlate messages together even if the underlying messaging pattern doesn't support correlation.

    You should be able to see now that the problem probably isn't that message security has stopped working. The problem is likely that the messaging pattern is no longer correlated and the service has no security context for the exchange. You need to establish a secure conversation to create the security context. The secure conversation can be bootstrapped with a single shot security mechanism. Afterwards, the application messages are transmitted using the secure conversation.

    Next time: BeginInvoke Bugs

  • Nicholas Allen's Indigo Blog

    Live from TechEd Day 5

    • 3 Comments

    It's midway through the final day of the conference so it's about time to give a summary of the week.

    The Event

    • The overall level of announcements was light during the week. There was a lot more focus on the products that have been released than the products that are upcoming. Acropolis was announced at the beginning of the week (links, my review). Windows Server Core got some additional elaboration but had already been announced previously.
    • The attendance was larger than last year but the venue was massively larger. There is still room for growth next year when TechEd returns to Orlando.
    • Lunch was distinctly improved from last year in Boston and was at the level of moderate cheap cafeteria food this year. Snacks were plentiful and varied.

    The Talks

    • There were a lot of great talks this year- too many to attend everything I wanted to see. The distribution across the week is uneven depending on your interests so I'll have to watch a few sessions once the recordings are published. It's unfortunate that the chalk talks aren't recorded because I missed almost all of them due to conflicts.
    • The rooms for breakout sessions were large and I had almost no problem getting a spot. Even the smaller rooms held 300 people, which was great for the sessions that turned out to be unexpectedly popular.
    • The setup for chalk talks was much better than last year. Each theater was equipped with AV equipment, monitors, and this time the white boards were usable. However, a lot of the chalk talks had capacity problems as they only held 32 people. The chalk talks last year only tended to get 20-30 people but this year a lot of chalk talks had 40-50 people. The microphones were not powerful enough and the monitors weren’t large enough to support an overflow crowd.

    The Location

    • The weather in Orlando is absolutely brutal coming in from Seattle. Every day was in the 90s with the humidity maxed out.
    • It's actually tough finding nice restaurants. The towns in the area are spread out a bit and a lot of places serve resort fare. You have to search around and ask people in order to distinguish the good spots from the best-advertised spots. This is going to be a whole lot easier next year at least.

    Update: Lunch on Friday sucked so that has pulled the average down a bit.  It was still better than the lunches last year.

    Next time: Single Shot Security Requires Request Reply 

  • Nicholas Allen's Indigo Blog

    Live from TechEd Day 4 (More Acropolis)

    • 1 Comments

    This post is coming in the afternoon because I spent most of the morning playing around with the Acropolis release. It is a very early release: a lot of the templates and options that you would want to use are missing, so it is mostly an attempt to find out about the vision for the product. I also watched the introduction video that they have on the website. I recommend watching the video because it points out the places where more content will come in the future rather than trying to guess while using the program.

    There are also two walkthroughs in the help file. I hadn't seen that mentioned so I didn't find the walkthroughs until after I had been playing around for a while. One of the walkthroughs goes through the same scenario as the introduction video. The other walkthrough is more interesting and it covers building a simple RSS reader. You will notice that while there is almost no code written for the notepad walkthrough, the RSS walkthrough has a substantial amount of code and XAML to write relative to the time you spend using the tools. I think that the RSS walkthrough is closer to a realistic example and it's better to use that sample if you want to get a feel for the developer experience. Writing notepad only gives you a feel for the installation process because all of the functionality is built into the product already.

    I don't think that it takes that long to get a feel for the product because a lot of the features and polish are still to be added. The core tools are very simple, but you'll need to learn each of the application types, component parts, layouts, and themes once they are available. After about four hours, here are my initial impressions.

    • I like the wizard approach for getting started but it has to be easy and robust to change my mind later and not lose the code I've already worked on.
    • There is a lot of terminology and stuffy terms that get thrown in your face right when you start. It threw off my initial impression on usability to large extent.
    • I like the model for command routing and handling. It matches the way I'd want to code but the infrastructure gets automatically generated.
    • The separate designer application helps get the infrastructure crud out of my face when I don't want to see it.
    • I hope the extensive use of XAML leads to a substantial wealth of tool support in the future. I'm weary of having to play with huge piles of angle brackets, whether it's XML config, XAML, or any other angle bracket dialect that is in style at the time. I just want tools to keep it out of my face. Acropolis uses XAML for the UI (and hopefully gets any WPF focused tools for free) and XAML for wiring together components. That is screaming for a solid and polished visual model designer rather than giving me notepad with nice text highlighting.
    • So, how do I deeply integrate all of this with workflows for actually building my business applications?

    Next time: Live from TechEd Day 5

  • Nicholas Allen's Indigo Blog

    Live from TechEd Day 3

    • 2 Comments

    Although TechEd doesn't normally have major product announcements (the conference is more about what has already happened rather than what is coming up), this year has been particularly light. Last year, we were caught up in the large rebranding of .NET Framework 3.0, which happened the week before the conference. We were not a newly-announced product, but we essentially had to act that way because it reset people's awareness about the components that Microsoft was shipping. Our role this year has evolved from explaining who we are to more explaining how to use the product.

    One product that did get announced this year is Acropolis. Acropolis continues the line of Greek-themed web application frameworks by helping you build client applications that tie together components from multiple different providers. There actually isn't a requirement that you build mashup-style web applications but I suspect that will be a favorite of the early-adopter crowd. Once it gets a bit more mature, I can see the potential here for writing business portal and integration applications faster (and hopefully they'll look a lot better than older generation applications as a bonus).

    The keynote address by Bob Muglia on Monday was similarly bigger on vision than substance. The second half of the talk did touch on quite a few products although we didn't get much that was deep or surprising. Here's the list of references that I put together:

    • Windows Server 2008 ("ships late 2007") - and more details about Windows Server Core
    • Visual Studio 2008 ("ships late 2007")
    • SQL Server 2008 ("actually ships in 2008")
    • Windows Virtualization
    • Silverlight
    • BizTalk Services

    Next time: Live from TechEd Day 4

  • Nicholas Allen's Indigo Blog

    Live from TechEd Day 2

    • 1 Comments

    I gave a chalk talk on channel development in the afternoon yesterday. I did a huge experiment for the second-half of the talk, which was to write a custom channel from scratch for the audience. That's the kind of theater that you can pull off in a chalk talk but not a regular breakout session. I started with a completely empty Visual Studio environment, wrote a web service, explained why the web service call crashed due to a protocol issue, and then fixed the crash by writing a custom channel.

    We had 46 people in the audience at the start. The capacity of the chalk talk theaters is only 32 people, but we secured about a dozen extra chairs from the lounges and people stood along the back. Capacity was an issue for several of the chalk talks yesterday. I saw one chalk talk for BizTalk that had crammed almost 60 people into the room. If you're in the audience, it starts getting quite warm after a while. The breakout session rooms are quite spacious on the other hand so I haven't seen any problems there. The Orlando venue has a tremendous capacity and a generally good layout.

    The only other difficulty was that the standard equipment was a non-adjustable over-ear headset microphone. In addition to making you look like a cross between a call-center worker and a pop star, that type of mic is pretty uncomfortable to wear for an hour and picks up a lot of extra noise if you move around while talking. I tried a half-dozen ways of putting the headset on to fix the issues before the AV guy offered a standard lapel microphone. They had one sitting in the AV case in the room. I don't know why they didn't make the proper equipment available from the start.

    I promised at the end of the talk that I'd post some resources.

    Ed Pinto and Kenny Wolf are giving a talk "Architecture of Microsoft Windows Communication Foundation and Common Extensibility Points" on Thursday at 4:30 PM.

    Steve Maine is giving the buzzword titled talk "Microsoft Windows Communication Foundation Syndication, AJAX and REST Services in Web 2.0 with .NET Framework 3.5" on Friday at 1 PM.

    There are six samples that I particularly recommend for channel developers.

    1. Chunking channel
    2. HttpCookieSession channel
    3. UDP transport
    4. WSE transport
    5. UDP activation
    6. Config code generator

    Finally, here is the code that was written during the talk. The scenario was based on an HTTP problem I described back in August.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    
    public class TechEdChannel : ChannelBase, IRequestChannel
    {
       IRequestChannel innerChannel;
    
       public TechEdChannel(ChannelManagerBase parent, IRequestChannel innerChannel) : base(parent)
       {
          this.innerChannel = innerChannel;
    
       }
       protected override void OnAbort()
       {
          innerChannel.Abort();
       }
    
       protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
       {
          return innerChannel.BeginClose(timeout, callback, state);
       }
    
       protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
       {
          return innerChannel.BeginOpen(timeout, callback, state);
       }
    
       protected override void OnClose(TimeSpan timeout)
       {
          innerChannel.Close(timeout);
       }
    
       protected override void OnEndClose(IAsyncResult result)
       {
          innerChannel.EndClose(result);
       }
    
       protected override void OnEndOpen(IAsyncResult result)
       {
          innerChannel.EndOpen(result);
       }
    
       protected override void OnOpen(TimeSpan timeout)
       {
          innerChannel.Open(timeout);
       }
    
       #region IRequestChannel Members
    
       public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
       {
          return innerChannel.BeginRequest(message, timeout, callback, state);
       }
    
       public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state)
       {
          return innerChannel.BeginRequest(message, callback, state);
       }
    
       Message FixMessage(Message message)
       {
          if (message == null)
             return null;
          HttpResponseMessageProperty property = (HttpResponseMessageProperty)message.Properties[HttpResponseMessageProperty.Name];
          if (property != null && property.StatusCode == System.Net.HttpStatusCode.Accepted)
          {
             return null;
          }
          return message;
       }
    
       public Message EndRequest(IAsyncResult result)
       {
          return FixMessage(innerChannel.EndRequest(result));
       }
    
       public EndpointAddress RemoteAddress
       {
          get { return innerChannel.RemoteAddress; }
       }
    
       public Message Request(Message message, TimeSpan timeout)
       {
          return FixMessage(innerChannel.Request(message, timeout));
       }
    
       public Message Request(Message message)
       {
          return FixMessage(innerChannel.Request(message));
       }
    
       public Uri Via
       {
          get { return innerChannel.Via; }
       }
    
       #endregion
    }
    
    public class TechEdChannelFactory : ChannelFactoryBase, IChannelFactory<IRequestChannel>
    {
       IChannelFactory<IRequestChannel> innerFactory;
    
       public TechEdChannelFactory(IChannelFactory<IRequestChannel> innerFactory) : base()
       {
          this.innerFactory = innerFactory;
       }
       protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
       {
          return innerFactory.BeginOpen(timeout, callback, state);
       }
    
       protected override void OnEndOpen(IAsyncResult result)
       {
          innerFactory.EndOpen(result);
       }
    
       protected override void OnOpen(TimeSpan timeout)
       {
          innerFactory.Open(timeout);
       }
    
       #region IChannelFactory<IRequestChannel> Members
    
       public IRequestChannel CreateChannel(EndpointAddress to, Uri via)
       {
          return new TechEdChannel(this, innerFactory.CreateChannel(to, via));
       }
    
       public IRequestChannel CreateChannel(EndpointAddress to)
       {
          return new TechEdChannel(this, innerFactory.CreateChannel(to));
       }
    
       #endregion
    }
    
    public class TechEdBindingElement : BindingElement
    {
       public TechEdBindingElement()
          : base()
       {
       }
    
       protected TechEdBindingElement(TechEdBindingElement element)
          : base(element)
       {
       }
    
       public override BindingElement Clone()
       {
          return new TechEdBindingElement(this);
       }
    
       public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
       {
          IChannelFactory<TChannel> innerFactory = base.BuildChannelFactory<TChannel>(context);
          return (IChannelFactory<TChannel>)new TechEdChannelFactory((IChannelFactory<IRequestChannel>)innerFactory);
       }
    
       public override bool CanBuildChannelFactory<TChannel>(BindingContext context)
       {
          if (typeof(TChannel) != typeof(IRequestChannel))
             return false;
          return base.CanBuildChannelFactory<TChannel>(context);
       }
    
       public override T GetProperty<T>(BindingContext context)
       {
          return context.GetInnerProperty<T>();
       }
    }
    
    [ServiceContract]
    public interface IService
    {
       [OperationContract(Action="*", IsOneWay=true)]
       void DoNothing();
    }
    
    public class Service : IService
    {
       public void DoNothing()
       {
          Console.WriteLine("Did nothing.");
       }
    }
    
    class Program
    {
       static void Main(string[] args)
       {
          string uri = "http://localhost:8000/";
    
          TextMessageEncodingBindingElement be = new TextMessageEncodingBindingElement();
          be.MessageVersion = MessageVersion.None;
    
          Binding binding = new CustomBinding(
             new OneWayBindingElement(),
             new TechEdBindingElement(),
             be,
             new HttpTransportBindingElement()
             );
    
          ServiceHost host = new ServiceHost(typeof(Service));
          host.AddServiceEndpoint(typeof(IService), binding, uri);
          host.Open();
          ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
          factory.Open();
          IService proxy = factory.CreateChannel();
          proxy.DoNothing();
          factory.Close();
          host.Close();
          Console.ReadLine();
       }
    }
    

    Next time: Live from TechEd Day 3

  • Nicholas Allen's Indigo Blog

    Live from TechEd

    • 1 Comments

    For those of you that weren't reading last year, here's how the week is going to work. Rather than posting on the regular 5 AM schedule, I'll be doing a post a day between 10 AM and 12 AM Eastern time summarizing what happened the previous day. If there are any events during the day, I may also give a second post in the afternoon. The response to having a picture story was a bit lukewarm so I'm not going to repeat that this year. Orlando also lacks the nice overhead walkways that Boston had so it wouldn't have turned out as well.

    I actually have nothing to report from yesterday so this post is a bit short. I had a five hour flight delay at Atlanta and missed all of the preconference activities on Sunday. I'm currently working on getting ready for a chalk talk on channel development this afternoon. It roughly follows the Channel Dev Tour series but in a 75 minute format.

    Next time: Live from TechEd Day 2

  • Nicholas Allen's Indigo Blog

    Binary Encodings and Addressing

    • 2 Comments

    There are three types of message encodings that come with WCF: text, binary, and MTOM. Text is the traditional way of encoding an XML document; MTOM is an interoperable way to create messages with attachments; and binary is an optimized format. The binary message encoder requires you to use SOAP 1.2 and any version of message addressing. Validation for the message encoder checks that you are using SOAP 1.2. A transport can supply its own native version of addressing, but the HTTP, TCP, and named pipe transports don't work with this for the binary encoding. The validation doesn't check to make sure that you have some kind of message addressing, so if you are using AddressingVersion.None, then that won't show up as an error until you try to send a message.

    It may be difficult to figure out the cause of the error because the resulting message looks invalid and the connection just gets refused. If you are capturing all of the exceptions that occur though, you should see something that looks like one of these stack traces when you have an invalid configuration.

    The stack trace when using HTTP is going to look like:

    System.ServiceModel.Channels.BinaryMessageEncoderFactory.BinaryMessageEncoder.ReadMessage + 0x299 bytes
    System.ServiceModel.Channels.HttpInput.DecodeBufferedMessage + 0x56 bytes
    System.ServiceModel.Channels.HttpInput.ReadBufferedMessage + 0x7e bytes
    System.ServiceModel.Channels.HttpInput.ParseIncomingMessage + 0x9e bytes
    System.ServiceModel.Channels.HttpRequestContext.CreateMessage + 0x2e bytes
    System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived + 0x99 bytes
    System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore + 0x231 bytes
    System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext + 0x1e bytes
    System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame + 0x28 bytes
    System.Net.LazyAsyncResult.Complete + 0x7f bytes
    System.Net.LazyAsyncResult.ProtectedInvokeCallback + 0x8b bytes
    System.Net.ListenerAsyncResult.WaitCallback + 0x22a bytes
    System.Threading._IOCompletionCallback.PerformIOCompletionCallback + 0x68 bytes

    The stack trace when using TCP or named pipes is going to look like:

    System.ServiceModel.Channels.TransportOutputChannel.TransportOutputChannel + 0x8b bytes
    System.ServiceModel.Channels.FramingDuplexSessionChannel.FramingDuplexSessionChannel + 0x4f bytes
    System.ServiceModel.Channels.FramingDuplexSessionChannel.FramingDuplexSessionChannel + 0x38 bytes
    System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ServerFramingDuplexSessionChannel.ServerFramingDuplexSessionChannel + 0x29 bytes
    System.ServiceModel.Channels.TcpDuplexChannelListener.System.ServiceModel.Channels.ISessionPreambleHandler.HandleServerSessionPreamble + 0x99 bytes
    System.ServiceModel.Channels.ConnectionOrientedTransportManager.OnHandleServerSessionPreamble + 0x53 bytes
    System.ServiceModel.Channels.ConnectionDemuxer.OnSessionPreambleKnown + 0xac bytes
    System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ContinueReading + 0x11d bytes
    System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.StartReading + 0x4b bytes
    System.ServiceModel.Channels.ConnectionDemuxer.OnDuplexConnection + 0xf6 bytes
    System.ServiceModel.Channels.ConnectionDemuxer.OnConnectionModeKnownCore + 0x214 bytes
    System.ServiceModel.Channels.ConnectionDemuxer.OnConnectionModeKnown + 0x7 bytes
    System.ServiceModel.Channels.ConnectionModeReader.Complete + 0xf bytes
    System.ServiceModel.Channels.ConnectionModeReader.ReadCallback + 0x74 bytes
    System.ServiceModel.Channels.SocketConnection.FinishRead + 0x19 bytes
    System.ServiceModel.Channels.SocketConnection.AsyncReadCallback + 0x13b bytes
    System.ServiceModel.Channels.OverlappedContext.CompleteCallback + 0x88 bytes
    System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame + 0x2f bytes
    System.Threading._IOCompletionCallback.PerformIOCompletionCallback + 0x68 bytes

    Update: Made it clearer why the message encoder needs a real addressing version in this case.

    Next time: Live from TechEd

Page 1 of 1 (21 items)