views:

323

answers:

2

If I use code like this [just below] to add Message Headers to my OperationContext, will all future out-going messages contain that data on any new ClientProxy defined from the same "run" of my application?

The objective, is to pass a parameter or two to each OpeartionContract w/out messing with the signature of the OperationContract, since the parameters being passed will be consistant for all requests for a given run of my client application.

public void DoSomeStuff()
{
    var proxy = new MyServiceClient();
    Guid myToken = Guid.NewGuid();
    MessageHeader<Guid> mhg = new MessageHeader<Guid>(myToken);
    MessageHeader untyped = mhg.GetUntypedHeader("token", "ns");
    OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
    proxy.DoOperation(...);
}

public void DoSomeOTHERStuff()
{
    var proxy = new MyServiceClient();
    Guid myToken = Guid.NewGuid();
    MessageHeader<Guid> mhg = new MessageHeader<Guid>(myToken);
    MessageHeader untyped = mhg.GetUntypedHeader("token", "ns");
    OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
    proxy.DoOtherOperation(...);
}

In other words, is it safe to refactor the above code like this?

bool isSetup = false;
public void SetupMessageHeader()
{
    if(isSetup) { return; }
    Guid myToken = Guid.NewGuid();
    MessageHeader<Guid> mhg = new MessageHeader<Guid>(myToken);
    MessageHeader untyped = mhg.GetUntypedHeader("token", "ns");
    OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
    isSetup = true;
}

public void DoSomeStuff()
{
    var proxy = new MyServiceClient();
    SetupMessageHeader();
    proxy.DoOperation(...);
}

public void DoSomeOTHERStuff()
{
    var proxy = new MyServiceClient();
    SetupMessageHeader();
    proxy.DoOtherOperation(...);
}

Since I don't really understand what's happening there, I don't want to cargo cult it and just change it and let it fly if it works, I'd like to hear your thoughts on if it is OK or not.

+1  A: 

I think your refactored code doesn't put any added-value. Have you taken in account that the OperationContext can be null?

I think this will be a safer approach:

 using(OperationContextScope contextScope =
        new OperationContextScope(proxy.InnerChannel))
  {

      .....
      OperationContext.Current.OutgoingMessageHeaders.Add(untyped); 
      proxy.DoOperation(...); 
  }

OperationContextScope's constructor will always cause replacement of the Operation context of the current thread; The OperationContextScope's Dispose method is called which restores the old context preventing problems with other objects on the same thread.

Sander Pham
+1  A: 

I believe your OperationContext is going to get wiped each time you new the proxy.

You should plan on adding the custom message headers prior to each call. This is good practice in any case as you should prefer per call services and close the channel after each call.

There are a couple patterns for managing custom headers.

  1. You can create the header as part of the constructor to the proxy.

  2. Alternatively, you can extend the binding with a behavior that automatically adds the custom header prior to making each call. This is a good example: http://weblogs.asp.net/avnerk...

Scott P
So, aside from my original question, you are saying that I should create a new proxy, call methods, close proxy every time? Instead of keeping one proxy open for the entire length of the program? Isn't there some overhead in opening a new proxy?
Nate Bross
Of course, there are always exceptions to the rule, but this is recommended for most cases. If you know you will make a quick succession of calls or you are using a session, you would leave the channel open. Otherwise, it makes sense to close it. This is really true when you think of error handling and potentially cleaning up a faulted channel after each call. You should assume the proxy is not there each time you access it. The overhead is usually insignificant compared to that of the actual call.
Scott P