Thursday, April 19, 2012

WCF Discovery Underpinning

Incase you don't know what WCF Discovery is, please read this first

<endpoint kind="udpDiscoveryEndpoint" />

what is kind ?
A string that specifies the type of standard endpoint applied. The type must be registered in the <extensions> section or in machine.config.

Extensions?
<system.serviceModel>
    <extensions>    
        <behaviorExtensions>
            <add name="MyInspectorA" type="MyTypeA" />
            <add name="MyInspectorB" type="MyTypeB" />
        </behaviorExtensions>
    </extensions>
</system.serviceModel>


This extensible object pattern is used for extending the runtime behavior of the existing classes or to add custom state information.

[to be completed soon..]

Wednesday, April 18, 2012

WCF Call Back

Client subscribes to service and service calls clients back and that is what this is about.

1) A normal WCF contract for server(impementation) and client(for proxy)
[ServiceContract]
interface IMessage    
{
        [OperationContract]
        void AddMessage(string message);
 }
2) A special interface(not a contract) for server(proxy) and client(implementation)
 interface IMessageCallback    
{
        [OperationContract(IsOneWay = true)]
        void OnMessageAdded(string message, DateTime timestamp);
 }
3) Add subscribe mechanism to normal WCF contract (given in step 1)
   [ServiceContract(CallbackContract = typeof(IMessageCallback))]
    public interface IMessage {
        [OperationContract]
        void AddMessage(string message);

        [OperationContract]
        bool Subscribe();

        [OperationContract]
        bool Unsubscribe();
    }

4) Implentation of normal contract given in step 3
a) a list to store subscribers
private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>();
b) get subscriber(callback channel to client)
IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
c) add subscriber to list
subscribers.Add(callback);
complete code:

public bool Subscribe()
{
    try {
        IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
        if (!subscribers.Contains(callback))
            subscribers.Add(callback);
        return true;
    }
    catch {
        return false;
    }
}

public bool Unsubscribe()
{
    try {
        IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
        if (subscribers.Contains(callback))
            subscribers.Remove(callback);
        return true;
    }
    catch {
        return false;
    }
}
public void AddMessage(string message)
{
    subscribers.ForEach(delegate(IMessageCallback callback)
    {
        if (((ICommunicationObject)callback).State == CommunicationState.Opened)
        {
            callback.OnMessageAdded(message, DateTime.Now);        }
        else {
            subscribers.Remove(callback);
        }
    });
}
5) add a suitable binding in config
<endpoint address ="" binding="wsDualHttpBinding" contract="WCFCallbacks.IMessage">

6) Client implementation
a) implement call back contract(given in step 2)
b) dispose mechanism needed
c) a context is required
 [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class Sender : IMessageCallback, IDisposable
{
    private MessageClient messageClient; public void Go()
    {
        InstanceContext context = new InstanceContext(this);
        messageClient = new MessageClient(context, "WSDualHttpBinding_IMessage");

        for (int i = 0; i < 5; i++)
        {
            string message = string.Format("message #{0}", i);
            Console.WriteLine(">>> Sending "+message);
            messageClient.AddMessage(message);
        }

    }
public void OnMessageAdded(string message, DateTime timestamp)
    {
        Console.WriteLine("<<< Recieved {0} with a timestamp of {1}", message, timestamp);
    }

    public void Dispose()
    {
        messageClient.Unsubscribe();
        messageClient.Close();
    }
}

Courtesy

WCF Sessions vs ASP.Net Sessions

WCF sessions are different from ASP.Net sessions

  • ASP.NET sessions are always server-initiated.(WCF session is caller initated)
  • ASP.NET sessions are implicitly unordered(WCF session is processed in the order of reception)
  • ASP.NET sessions provide a general data storage mechanism across requests(not in WCF session except 'durable services')
In ASP.Net you can access session very easily

1) In config: <configuration>
<sessionstate
mode="inproc" />
1) and then in code : Session("Stocks") = "MSFT; VRSN; GE"

But in WCF, to manage sessions, we should learn about a few WCF concepts:
1) There is an attribute to enable session(SessionMode)
2) We should manage instancing ourselves (which is there for an entirely different purpose)
3) Instancing is related to binding, so we should learn about supporting bindings
4) We might even need to control the execution threads(concurreny)
For simple and indepth overview on WCF Sessions check this blog