views:

94

answers:

3

I have a WCF service with a client application. I have complete control over both the client and server implementation. I have hundreds of methods in the WCF contract which need a piece of information supplied by the client. Instead of modifying hundreds of methods, is there a way I can send specific data from the client with every call to the service, possibly somewhere in the channel?

Maybe when the client is setting up the proxy before making the call, it can store this data somewhere in an internal property of the proxy... the data would then get sent to the server and from within the service method I could inspect the OperationContext or some other piece of memory to get this data back and use it?

Any ideas?

+1  A: 

It sounds like you are wanting something like headers like with SOAP webservices. I'm not a WCF expert, but this looks like the WCF equivalent.

Darren Kopp
A: 

You can't do this trivially. It will take some work.

It's true that SOAP Headers are the perfect way to pass out-of-band data to and/or from a service. But you already have your contract defined, and adding headers will change the contract.

I believe you'll have to start using message contracts.

Original:

[DataContract]
public class ComplexObject
{
    [DataMember(Name = "Id")] 
    public int Id;

    [DataMember] 
    public string Name;
}

[ServiceContract()]
public interface IMyContract
{
    void MyOperation(ComplexObject co);
}

public class MyService : IMyContract
{
    #region Implementation of IMyContract

    public void MyOperation(ComplexObject co)
    {
        // use co.*
    }

    #endregion
}

Using Message Contracts:

[DataContract]
public class ComplexObject
{
    [DataMember(Name = "Id")] 
    public int Id;

    [DataMember] 
    public string Name;
}

[DataContract]
public class MyHeader
{
    [DataMember]
    public string UserName;

    [DataMember]
    public string Password;
}

[DataContract]
public class OutputHeader
{
    [DataMember]
    public string Token;
}

[MessageContract]
public class MyOperationRequest
{
    [MessageHeader]
    public MyHeader Authentication;

    [MessageBodyMember]
    public ComplexObject TheObject;
}

[MessageContract]
public class MyOperationResponse
{
    [MessageHeader] 
    public OutputHeader OutputHeader;
}

[ServiceContract()]
public interface IMyContract
{
    MyOperationResponse MyOperation(MyOperationRequest request);
}

public class MyService : IMyContract
{
    public MyOperationResponse MyOperation(MyOperationRequest request)
    {
        // use request.TheObject.*
        // Can also read request.Authentication.*

        return new MyOperationResponse 
               { OutputHeader = new OutputHeader { Token = "someToken" } };
    }
}
John Saunders
+1  A: 

It shouldn't actually be that hard. The best way I can think of is to write an IClientMessageInspector that adds a SOAP header into the Message.Headers in its BeforeSendRequest method.

See e.g. http://weblogs.asp.net/paolopia/archive/2007/08/23/writing-a-wcf-message-inspector.aspx

Eugene Osovetsky