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.
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.
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
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
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
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
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
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
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
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
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,
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
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.
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
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
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
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
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 Talks
The Location
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
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.
Next time: Live from TechEd Day 5
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:
Next time: Live from TechEd Day 4
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.
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
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
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 bytesSystem.ServiceModel.Channels.HttpInput.DecodeBufferedMessage + 0x56 bytesSystem.ServiceModel.Channels.HttpInput.ReadBufferedMessage + 0x7e bytesSystem.ServiceModel.Channels.HttpInput.ParseIncomingMessage + 0x9e bytesSystem.ServiceModel.Channels.HttpRequestContext.CreateMessage + 0x2e bytesSystem.ServiceModel.Channels.HttpChannelListener.HttpContextReceived + 0x99 bytesSystem.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore + 0x231 bytesSystem.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext + 0x1e bytesSystem.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame + 0x28 bytesSystem.Net.LazyAsyncResult.Complete + 0x7f bytesSystem.Net.LazyAsyncResult.ProtectedInvokeCallback + 0x8b bytesSystem.Net.ListenerAsyncResult.WaitCallback + 0x22a bytesSystem.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 bytesSystem.ServiceModel.Channels.FramingDuplexSessionChannel.FramingDuplexSessionChannel + 0x4f bytesSystem.ServiceModel.Channels.FramingDuplexSessionChannel.FramingDuplexSessionChannel + 0x38 bytesSystem.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ServerFramingDuplexSessionChannel.ServerFramingDuplexSessionChannel + 0x29 bytesSystem.ServiceModel.Channels.TcpDuplexChannelListener.System.ServiceModel.Channels.ISessionPreambleHandler.HandleServerSessionPreamble + 0x99 bytesSystem.ServiceModel.Channels.ConnectionOrientedTransportManager.OnHandleServerSessionPreamble + 0x53 bytesSystem.ServiceModel.Channels.ConnectionDemuxer.OnSessionPreambleKnown + 0xac bytesSystem.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ContinueReading + 0x11d bytesSystem.ServiceModel.Channels.ServerSessionPreambleConnectionReader.StartReading + 0x4b bytesSystem.ServiceModel.Channels.ConnectionDemuxer.OnDuplexConnection + 0xf6 bytesSystem.ServiceModel.Channels.ConnectionDemuxer.OnConnectionModeKnownCore + 0x214 bytesSystem.ServiceModel.Channels.ConnectionDemuxer.OnConnectionModeKnown + 0x7 bytesSystem.ServiceModel.Channels.ConnectionModeReader.Complete + 0xf bytesSystem.ServiceModel.Channels.ConnectionModeReader.ReadCallback + 0x74 bytesSystem.ServiceModel.Channels.SocketConnection.FinishRead + 0x19 bytesSystem.ServiceModel.Channels.SocketConnection.AsyncReadCallback + 0x13b bytesSystem.ServiceModel.Channels.OverlappedContext.CompleteCallback + 0x88 bytesSystem.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame + 0x2f bytesSystem.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