CommunicationState listener? - c#

Does anyone know of a way to create a listener for a proxy so that when the CommunicationState has changed I can invoke an action or a method?
An example, I want to update my WCF service for a code change. Since the application is in its early development code changes are very frequent. However, instead of annoying my employees with an email tell them that hey they need to restart their application. I would rather avoid them having to restart the app and having to send them an email. I would rather write a listener that looks at the communication state of a service and if it has changed to a faulted stated then attempt to reconnect.
Edit
Maybe some more context here.
InstanceContext context = new InstanceContext(this);
Subscriber = new SubscriptionService.MySubscriptionServiceClient(context);
Subscriber.Subscribe("");
So basically I want to know when the subscription service has stopped so that I can attempt to reconnect every 60 seconds or so. I tried looking for an event in the Subscriber service but I didn't see anything. Would I need to implement something on the service end?
Thanks

You can use the Faulted event available on the InnerChannel property of your generated client class. The State property of the client class is just a wrapper for InnerChannel.State, so this should work as you desire.
(For reference, you can also use the similarly named event on ChannelFactory<TChannel> if you are creating communication channels in code rather than using generated proxies.)

Related

ActiveMQ access to previously published data on subscription

We're using ActiveMQ locally to transfer data between 5 processes that turn simultaneously.
I have some data I need to send to a process, both at runtime (which works perfectly fine), but also a default value on start. Thing is it is published when the process starts, it just doesn't read because it wasn't subscribed to the topic at the time the data was sent.
I have multiple solutions : I could delay the first publishing for a moment so that the process has time to launch (which doesn't seem very appealing) ; or is there a way to send all stored previously non-treated messages to some process that just subscribed ?
I'm coding in C#.
I don't have any experience with ActiveMQ, but other message system usually have an option which marks the subscription as persistent, which means that; after the first subscription; the message queue itself checks if a certain message is delivered to that system and retries with a timeout. In this scenario you need to start the receiver at least 1 time.
If this is not an option and you want to plug in receiver afterwards, you might want to consider a setup of your messages which allows you to retrieve the full state, i.e. if you send total-messages instead of differential- messages.
After a little google, I came upon this definition durable subscribers, I hope this helps:
See:
http://activemq.apache.org/how-do-durable-queues-and-topics-work.html
and
http://activemq.apache.org/manage-durable-subscribers.html
since you are using C# client i don't konw if this is supported
topic = new ActiveMQTopic("TEST.Topic?consumer.retroactive=true");
http://activemq.apache.org/retroactive-consumer.html
So, another solution is to configure this behavior on the broker side by adding that to the activemq.xml and restart :
The subscription recovery policy allows you to go back in time when
you subscribe to a topic.
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" >
<subscriptionRecoveryPolicy>
<timedSubscriptionRecoveryPolicy recoverDuration="10000" />
<fixedCountSubscriptionRecoveryPolicy maximumSize="10000" />
</subscriptionRecoveryPolicy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
http://activemq.apache.org/subscription-recovery-policy.html
I went around the issue by sending a message from each process when they're launched back to the main one, and then only sending the info I needed to send.

WCF - Determining when session ends on the server side

In the project I'm working on, we have several services implemented using WCF. The situation I'm facing is that some of the services need to know when a session ends, so that it can appropriately update the status of that client. Notifying the service when a client gracefully terminates (e.g. the user closes the application) is easy, however, there are cases where the application might crash, or the client machine might restart, in which case the client won't be able to notify the service about its status.
Initially, I was thinking about having a timer on the server side, which is triggered once a client connects, and changes the status of that client to "terminated" after, let's say, 1 minute. Now the client sends its status every 30 seconds to the service, and the service basically restarts its timer on every request from the client, which means it (hopefully) never changes the status of the client as long as the client is alive.
Even though this method is pretty reliable (not fully reliable; what if it takes the client more than 1 minute to send its status?) it's still not the best approach to solving this problem. Note that due to the original design of the system, I cannot implement a duplex service, which would probably make things a lot simpler. So my question is: Is there a way for the sevice to know when the session ends (i.e. the connection times out or the client closes the proxy)? I came accross this question: WCF: How to find out when a session is ending but the link on the answer seems to be broken.
Another thing that I'm worried about is; they way I'm currently creating my channel proxies is implemented like this:
internal static TResult ExecuteAndReturn<TProxy, TResult>(Func<TProxy, TResult> delegateToExecute)
{
string endpointUri = ServiceEndpoints.GetServiceEndpoint(typeof(TProxy));
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
TResult valueToReturn;
using (ChannelFactory<TProxy> factory = new ChannelFactory<TProxy>(binding,
new EndpointAddress(new Uri(endpointUri),
EndpointIdentity.CreateDnsIdentity(ServiceEndpoints.CertificateName))))
{
TProxy proxy = factory.CreateChannel();
valueToReturn = delegateToExecute(proxy);
}
return valueToReturn;
}
So the channel is closed immediately after the service call is made (since it's in a using block), is that, from a service standpoint, an indication that the session is terminated? If so, should I keep only one instance of each service during application runtime, by using a singleton maybe? I apologize if the questions seem a little vague, I figured there would be plenty of questions like these but wasn't able to find something similar.
Yes, closing the channel terminates the session, but if there is an error of some kind then you are subject to the timeout settings of the service, like this:
<binding name="tcpBinding" receiveTimeout="00:00:10" />
This introduces a ten second timeout if an error occurs.
Check out Managing WCF Session Lifetime with IsInitiating and IsTerminating

Trigger event from ChannelFactory

We are using the ChannelFactory to connect to our WCF Service. When ever I do a call to the service, I want the Channel factory to trigger another event. Something like 'OnFunctionCall'. How can I add such a event handler to the ChannelFactory. I'm kinda rushed for time, so I hope someone could help.
Working with C#, .net 3.5 SP1
Kind Regards
One possible solution is to create an endpoint behavior and attach it to the factory endpoint (see below). That behavior would add an inspector to the channels the factory creates (which can be either an IClientMessageInspector or an IParameterInspector), and your inspector would trigger the OnFunctionCall event whenever a message is sent to the server.
var factory = new ChannelFactory<IService>(...);
factory.Endpoint.Behaviors.Add(new MyInspector());
For more information on message inspectors you can look at http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/19/wcf-extensibility-message-inspectors.aspx, and for parameter inspectors you can look at http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/26/wcf-extensibility-iparameterinspector.aspx.

ServiceHost message receive event?

Surely there must be an event to attach onto before a ServiceHost or Channel or Dispatcher handles a message? I'm assuming it can be accessed through OperationContext.Current, but the closest events I can find are Opening and Closing. Is there something like a MessageReceived or BeforeMessageProcessed event?
If not using events, is there some other way using WCF classes/configuration to determine if a ServiceHost SingletonInstance is currently processing a DataContract?
EDIT: IDispatchMessageInspector (AfterReceiveRequest and BeforeSendReply) is perfect. I have about 8 services and need to know what messages (DataContracts) they are currently processing. While it would be possible to use something like a helper method that takes a delegate and does BeforeReceive(); InvokeDelegate(); AfterReceive(); it's far easier to use IDispatchMessageInspector and behaviors.
As far as I know, there isn't such an event at the service host level directly. Could you explain what you're trying to accomplish?
Normally, if you've got any processing that must be done whenever a message arrives, then the right way is to use one of the several extensibility points that WCF offers for this, like IDispatchMessageInspector. In this case, you'd inject your message inspector into the WCF pipeline through a service or an endpoint behavior.

.Net 2.0: How to subscribe to a event publisher on a remote computer using transient subscriptions?

My problem is that I want to have a server application (on a remote computer) to publish certain events to several client computers. The server and client communicate using .Net-Remoting so currently I am using remoted .Net-Events to get the functionality. But there is one drawback: when the server (the event publisher) comes offline and is restarted, the clients lose the connection since the remote object references become invalid.
I am looking into Loosely Coupled Events and Transient COM Subscriptions to solve this issue. I put together a small demo application with one publisher and two subscribers. It works beautifully on one computer.
I am using the COMAdmin-Libraries to create a transient subscription for the event subscribers. The code looks like this:
MyEventHandler handler = new MyEventHandler();
ICOMAdminCatalog catalog;
ICatalogCollection transientCollection;
ICatalogObject subscription;
catalog = (ICOMAdminCatalog)new COMAdminCatalog();
transientCollection = (ICatalogCollection)catalog.GetCollection("TransientSubscriptions");
subscription = (ICatalogObject)transientCollection.Add();
subscription.set_Value("Name", "SubTrans");
subscription.set_Value("SubscriberInterface", handler);
string eventClassString = "{B57E128F-DB28-451b-99D3-0F81DA487EDE}";
subscription.set_Value("EventCLSID", eventClassString);
string sinkString = "{9A616A06-4F8D-4fbc-B47F-482C24A04F35}";
subscription.set_Value("InterfaceID", sinkString);
subscription.set_Value("FilterCriteria", "");
subscription.set_Value("PublisherID", "");
transientCollection.SaveChanges();
handler.Event1 += OnEvent1;
handler.Event2 += OnEvent2;
My question now is: what do I have to change in the subscription to make this work over a network? Is it even possible?
What about MSMQ? It seems perfect for what you are trying to achieve? You can use a traditional publish/subscribe model or multicast the messages.
This might be a step too far, but have you considered using WCF and the callback element of WCF?
Callback effectively turns the what was client into a server. To be honest, I don't know a great deal about callback and have only experimented. Perhaps worth a 10 minute google though.
If your server comes offline every once and a while I cannot see how you can avoid to poll it to check that it is alive.
As you are talking about COM and remote computers, I suspect you'll have to do some DCOM security configuration.

Categories

Resources