Tag Archive for WinFX January CTP

OperationContext is ThreadStatic

WCF Services tend to be big, heavy duty things. When I write a service I often want it to do a lot of work for a lot of clients, and it should do it efficiently. This usually means that I will use multithreaded code to get things done concurrently. Whether using the ThreadPool or instantiating a thread of my own, I expect this is a common scenario for WCF service writers.

That’s why I was suprised today to find out that the OperationContext of the current service call, our entry point for getting context information about the current call, its headers and so forth – is marked as [ThreadStatic]. This means that the moment I fork off to another thread, I lose all context information. If I want it available, I have to do it myself.

I don’t know how ASP.NET deals with this problem. If I spin a new thread under ASP.NET, I don’t lose my current HttpContext. A quick glance with Reflector shows that there’s no [ThreadStatic] anywhere. Whatever features of IIS they use there, it’s probably unavailable for WCF, so we have to do it manually.

The simplest way to pass the context to a thread is just to send it as a parameter:

void Method ()
{
    ThreadPool.QueueUserWorkItem(ThreadMethod, OperationContext.Current);
}

void ThreadMethod(object state)
{
    OperationContext.Current = state as OperationContext;
    // Do whatever.
}

Side note: Note the automatic delegate inference that .NET 2.0 does, rather than forcing me to manually create a WaitCallback delegate:
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod), OperationContext.Current);
I don’t think this was possible in v1.1.

If we want to spin a thread of our own, we can use the ParameterizedThreadStart delegate:

void Method ()
{
    Thread t = new Thread(new ParameterizedThreadStart(ThreadMethod), OperationContext.Current);
    t.Start();
}

If we have parameters to pass to our method, though, we need to be even hackier – maybe define a struct or class to hold our OperationContext as well as the custom parameters, and pass that on to the ThreadMethod and have it disassemble it.

There is a better way to build a Thread Launcher than can pass the ObjectContext. I’ll elaborate on that in my next post.

Deperplexing WCF errors pt. 3 – Interfaces and KnownTypes

Another error message that stumped me today (after I had removed the IsOneWay parameter and actually got to see it) was the following exception:

System.ServiceModel.CommunicationException
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error

This little gem was caused when calling a method on a service with an interface as a parameter, something like this:

[OperationContract]
void DoSomething (IMessage message)

When deserializing the IMessage, WCF had no way of knowing what type to deserialize it as, so it through the charming message above.
I don’t know how this situation came to be, since the proxy generated by svcutil seems to create the message as DoSomething(object message) and not IMessage, but the principle should be the same.

The immediate solution that fixed this was adding the [KnownType(typeof(myMessage))] attribute to the method. This allows the deserialization engine to understand the message and do something constructive with it rather than crashing.

Naturally, I am less than pleased with this solution. The whole purpose of using interfaces is that I won’t have to know, when coding, what objects will be passed to my service. I just want to expose the interface.

One way to keep this flexibility can be found in the very last paragraph of the long and detailed Data Contract Known Types article on MSDN – it seems that the list of Known Types can be defined globally in the system using the section in the config file. Details about that are also sparse, and I’m not at all sure if it’s possible in the January CTP – the section names seem to have changed from to between January and February, and there are no samples to explain the proper structure for the January version. I hope this gets clearer with the next beta.

Deperplexing WCF errors pt. 1 – CommunicationObjectAbortedException for security mismatch

As a follow-up to this post: another reason why we get CommunicationObjectAbortedExceptions is because our client channel definition does not send any credentials (using a binding that has the SecurityMode set to None) while the service is still set to the default settings, expecting Windows authentication. Rather than throwing some sort of SecurityException, the exception is raised.
Just a heads up.

Indigo Errors Perplexing

I was writing a very simple WCF service. Nothing fancy – just returning an array of structs via TCP, just like 3 others already implemented. Started testing, stepped through the server code, returned the value from the service interface, then WHAM – a big scary exception:

System.ServiceModel.CommunicationObjectAbortedException
The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue.

Inner Exception:
System.Net.SocketException
An existing connection was forcibly closed by the remote host

This rather scary error message is not very helpful. Was it because of a timeout? (Unlikely, as it happened immediately). Underlying network resource issue? Happens too predictably. Error processing your message? What does that mean, anyway? WHAT error processing my message? And anyway, the inner SocketException seems to imply that it’s a network error, not a message error.

But of course it is. WCF didn’t really point me towards it, but it seems I had forgotten to mark my struct as a [DataContract] and its members as [DataMember]s. No contract, nothing to serialize, no message.

Perfectly understandable, once you know what’s going on. Totally perplexing until you do.

Now let’s give this entry some Googlejuice so people who are experiencing this problem can find it:
WCF, Indigo, CommunicationObjectAbortedException,  SocketException, DataContract.
There. That should do it.

Adding custom headers to every WCF call – a solution

At last, a solution presented itself. While I must admit that at first I was very skeptical of the extensibilty model for WCF which seemed far too involved and complicated, but after implementing a simple extension I must say it’s simple and quite intuitive.

My goal was to have several custom headers added to each call made through a proxy, rather than manually adding them to each call’s OperationContext. With a little help from Ralph Squillace’s blog, I was able to get an extension up and running within minutes, and it Just Works.

The first item to build is the actual extension logic. In this case, I needed an IProxyMessageInspector object that inspects each outgoing message and adds the custom headers:

public class ContextPusher : IProxyMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            // Do nothing.
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            MessageHeader myHeader = new MessageHeader(“HeaderValue”).GetUntypedHeader(“MyHeader”, “ns”);
            request.Headers.Add(
myHeader);
            return null;
        }
    }
}

Now we want to attach that inspector to proxy. We do that wth Behavior objects. This can be done on an operation-by-operation basis or for all operations on a given channel. We can make the same class implement both behaviors, for flexibility:

public class CallContextAttribute : Attribute, IChannelBehavior, IOperationBehavior
    {
        #region IOperationBehavior Members

        public void ApplyBehavior(OperationDescription description, ProxyOperation proxy, BindingParameterCollection parameters)
        {      
            // Add my MessageInspector to each message sent by the proxy.
            proxy.Parent.MessageInspectors.Add(new ContextPusher());
  
        }

        public void ApplyBehavior(OperationDescription description, DispatchOperation dispatch, BindingParameterCollection parameters)
        {
            // No server-side behaviors for now.
        }

        #endregion
               
        #region IChannelBehavior Members

        public void ApplyBehavior(ChannelDescription description, ProxyBehavior behavior, BindingParameterCollection parameters)
        {
            // Add the MessageInspector to every message sent through the channel.
            behavior.MessageInspectors.Add(new ContextPusher());
        }

        #endregion
    }

And then simply put it on a Service or Operation.
I think in this case, putting the attribute on both will result in an error when trying to add duplicate headers. But this allows me flexibility in adding the headers only to certain calls.

[ServiceContract]
[CallContext]
public interface ILocalizationServices
{
   [OperationContract]
   [CallContext]
   string DoSomething(string param);
}

I think this is the first time I got really excited by the WCF framework and the ease of using and extending it. This is FUN.

How do I add a custom header to every WCF message?

One thing I still haven’t managed to do is create my proxy in such a way that a custom header is added to every call that is made through that proxy.
Currently, this is done by instantiating a new OperationContext around each call through the proxy. This can be optimized in several ways:
1) Create a shared OperationContext object and always instatiate the OperationContextScope with it:
using (OperationContextScope scope = new    
            OperationContextScope(standardContextObject))
{
   …
}

I don’t know if it’s a good idea, though. Should OperationContext objects be persisted between calls, or would it have unexpected side effects?

2) Create a wrapper around the OperationContextScope class that fills the OperationContext with the proper headers:

public class MyOperationContextScope : IDisposable
{
   OperationContextScope contextScope;

   public MyOperationContextScope ()
   {
      contextScope = new OperationContextScope();
      MessageHeader standardHeader = new   
      MessageHeader(“StringHeaderValue”).GetUntypedHeader(“StringHeader”, “ns”);
      OperationContext.Current.OutgoingMessageHeaders.Add(standardHeader );
    }

    public void Dispose()
    {
      if (contextScope != null)
      {
          contextScope.Dispose();
      }
    }     
 }

This is a bit cleaner, but still requires me to wrap every proxy call with a using() statement.

Is there a way to interecept all calls and have my headers added automatically?

Adding custom headers to a WCF message – Jan CTP

Guy Burstein, again, writes about adding custom headers to a call made by a WCF proxy.
This is all very nice and well, but his code only works with the Feb. CTP of WCF, while I’m still using January here.
The differences seemed subtle at first – his instantiation of the OperationContextScope passed the proxy to the constructor, but there is no such constructor in the January CTP.
Simply instantiating the OperationContextScope with no parameters and adding headers seemed to work, but those headers never made it to the server-side.

After much fussing and digging, it turns out that the headers were transferred, but the way to fetch them was obscure. I don’t know if this was a design change from Jan to Feb or maybe it was just a bug that was fixed, but instead of accessing the headers like this:

string myHeader = OperationContext.Current.IncomingMessageHeaders.GetHeader(“myHeader”, “myNS”);

we have to do it like this:

string myHeader = OperationContext.Current.RequestContext.RequestMessage.Headers.GetHeader(“myHeader”, “myNS”);

Hope it helps.

Creating metadata from WCF executables

So I’ve started messing around with WinFX and WCF.
It certainly feels like it needs more work, especially on the dev-tool end of things.

I was trying to run SvcUtil to generate metadata and proxy from a console application and ran into this error message:
 
Error: There was an error exporting the ContractDescription loaded from the type
: Strawjackal.WCFTest.IService, MyService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
    Duplicate contract QNames are not supported.
Another ContractDescription with the Name: IService and Namespace:
Strawjackal.WCFTest has already been exported.

This was very confusing until I found this page here explaining that SvcUtil is simply broken when running on EXE assemblies. The original poster’s solution was to recompile his assembly as a class, but I’ve discovered that an even simpler solution is to just rename my EXE to a DLL, run SvcUtil against it, and rename it back.

WSDL created.
Me happy.