delegates across different machines - c#

it seems like it should be dead easy, but i couldn't find anything in google on it:
I have a video store server, and it has multiple client applications, installed on users' machines, communicating via (let's say) web services.
When a DVD is returned, I'd like to be able to notify useres that have been waiting for that DVD.
When dealing with a single application, then that's no problem using delegates.
my question is- can this approach work with remote clients as well?

You can use a duplex WCF service for that.
But if it really is a DVD handling service where the user doesn't need to be notified immediately, I would recommend a solution where the users' clients poll the server every say 10 minutes. It is far more simple to implement.

Yes - you can use .NET remoting. See this article for a simple example:
http://www.codeproject.com/KB/IP/remotingandevents.aspx

If you want to have a client application that will provide a delegate that people can wire up to, then yes. You would use .net remoting for that.
I used this example: http://www.codeproject.com/KB/dotnet/DotNetRemotingEventsExpl.aspx
Basically what you are going to do, is to expose a remoting server that publishes a known object. The trick with events, is that the server has to know about the type that the client is wiring the event handlers to. So what you do in that case is that you also provide an abstract class as an event sink.
Basically that class will look something like this:
public abstract class MyEventSinkClass : MarshalByRefObject
{
public abstract void MyAbstractEventHandler(string arg1, string arg2);
public void MyEventHandler(string arg1, string arg2)
{
MyAbstractEventHandler(arg1,arg2);
}
}
Then on the client side they would create a class, and inherit from MyEventSinkClass. They put their logic for handling the event in the override for MyAbstractEventHandler. When they wire up the instance that they are using remoting for, instead of wiring like you normally would, they need to wire to their instance of the class that inherits MyEventSinkClass to the MyEventHandler Method. Then when the event fires, it will eventually call into the overriden method and execute their code.
You can find the details of how to setup a remoting server and client in the link I gave, it isn't difficult.

If you don't want to invent the wheel, Use a Message Queuing tool.
Then, when a dvd is return you post a message on some queue. The users are registering to the queues of the DVDs they are interesting in.
Then the communication is persistent and async. the users are getting notifications even if they are offline (they'll get it once they connect and poll the queue)

Related

What is the difference between RequestInterceptor and MessageInspector?

I have two queries here :-
1) What is the basic difference between Microsoft.ServiceModel.Web.RequestInterceptor and System.ServiceModel.Dispatcher.DispatchRuntime.MessageInspectors (IdispatchMessageInterceptor)
Both appears to be Request/Message interceptors which can be used to implement custom validation/interceptors in the request pipeline.
When to use one on another?
2) Also how to plugin RequestInterceptor in RouteTable.Routes.Add(new ServiceRoute())
I have class like this -
public class AuthenticationInterceptor : RequestInterceptor
{
//Authentication logic goes here......
}
and a route definition like this : -
RouteTable.Routes.Add(new ServiceRoute(routePrefix, new MyServiceHostFactory(container, (sh) => {
foreach (System.ServiceModel.Dispatcher.ChannelDispatcher cd in sh.ChannelDispatchers)
{
foreach (System.ServiceModel.Dispatcher.EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.MessageInspectors.Add(new AuthenticationInterceptor());
}
}
return sh; })));
Here is the definition of MyServiceHostFactory: -
public MyServiceHostFactory(IocContainer container, Func<ServiceHost, ServiceHost> createservicehost = null);
Now it is throwing following error : -
The best overloaded method match for 'System.Collections.Generic.SynchronizedCollection<System.ServiceModel.Dispatcher.IDispatchMessageInspector>.Add(System.ServiceModel.Dispatcher.IDispatchMessageInspector)' has some invalid arguments
at this line : -
ed.DispatchRuntime.MessageInspectors.Add(new AuthenticationInterceptor());
I know why, it is just because I am trying to hookup RequestInterceptor in MessageInspector. Both comes in different interface hierarchy.
So what should I do here?
Edit:
Also note, I cannot change AuthenticationInterceptor logic as the code in not under my control.
Here are the answers to your questions(you need to read through point number 2 to understand Interceptors and Inspectors a little):
1. Solution to the Error (you need to add your code logic to it )
Implement IDispatchMessageInspector in the following code. Please note that the name of the following class should change to inspector, but as you have mentioned you cannot change it so you should implement the interface here. Otherwise, it is recommended to create another class with Matching Inspector suffix and implementation.
public class AuthenticationInterceptor : RequestInterceptor, IDispatchMessageInspector
{
//Authentication logic goes here......
object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
//Your code here.
}
void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
//Your code here.
}
}
2. Difference between RequestInterceptor and MessageInspectors
In any client server communication there can be two important phases of communication. First, when a client establishes connection with the server and second when they both communicate.
When establishing the connection it is not necessary that the client which is trying to establish the connection is a valid client. It could be an unauthorized request as well or it could be possible that the request is valid but not intended to the destined server and requires authorization or connection rerouting.
A good example of rerouting is when :
you want regional client/servers to avoid cross region communications but one of the client(which is valid) but tries to connect to a different region server.
You want the servers selectively decide if you wish to allow cross region client-server communications for a few exceptional users.
There could be even more complex rerouting scenarios which is out of scope of this answer.
So in WCF, the Rest starter kit provides you additional ability to intercept the request during connection establishment phase. The interceptor (in your case the AuthenticationInterceptor) should authenticate such requests and if the request is invalid, it can log the necessary entries and just reject to process any communication further from this rejected client/session.
We have many benefits of having a RequestInterceptor:
It helps us to validate the incoming request at a very early phase.
It can help us to build custom authenticators or rerouting components.
It blocks any further message processing during request phase itself which is very important to keep the unnecessary load away from the WCF Service/Server.
Message Inspectors:
The MessageInspectors can be treated as part of second phase of client-server communication when a Request is validated and connection is well established and thus it's the time when client-server has to started communicating by passing messages to each other. Now, in your application environment it could be possible that the messages pass using a binary, xml or json serialized format. There could be applicable encryptions.
An example is, it is possible that a message arrives from client A and given to Server B now server Queues it up to another Server C which can wait for some more information from Another Server D. Once Server D provides the information, the Server C which has the message in queue further joins the raw message received from Server B and Server D, gives it to another service to deserialize and convert it to something meaningful which can be returned to server B and B returns it back to Client A.
Quite complex, right? But a multi server authentication like payments by credit card using mobile PIN somewhat works in similar manner, though could be not exactly the same, but even more complex.
In WCF, Interceptors and Inspectors can work together and their duties are different. An interceptor validates the end user/connection/rerouting and an Inspector validates/processes the message.
A few points:
You can build your own message inspectors by implementing IClientMessageInspector for the client side and IDispatchMessageInspector on the server side.
You can implement both of the interfaces in a single class if you are owner of both client and server components.
Here, in your case it seems you need to implement IDispatchMessageInspector.
A class implementing IDispatchMessageInspector does not intercepts as I mentioned before but is meant to 'Inspect' an incoming message and any outgoing message and this Inspector can be hooked using configurations when a message arrives from the client.
Please note that by this time at Inspector levels, any message which arrives is already processed at various channel stack levels and assigned to which WCF Service will process this request. If you are using any encryption in between, then the message has already been decrypted. But, the message is not deserialized yet.
A use of having your custom Inspector is it could be possible that your system implements custom serialization format like (SWIFT/FIX protocol in banking) or another level of zip/unzip encoding etc.
This custom inspector can deserialized the data and give it to your component COMP which is actually meant to work on the deserialized data.
An IDispatchMessageInspector interface has got two methods which you need to implement:
a) AfterReceiveRequest and
b) BeforeSendReply(ref Message, Object).
AfterReceiveRequest is the method which can dezerialize the data and gives it to COMP, and BeforeSendReply is the method which again serializes the data and perform any operation on the message.
You can use behaviors to attach the MessageInspectors for every message your web service receives.
Both, custom Interceptors and Inspectors are largely meant to be used in Enterprise Platform or a Highly customizable platforms.
Hope this answer helps you. You can read more on the following links (possible you have gone through the first one):
http://msdn.microsoft.com/en-us/library/ee391967.aspx
http://msdn.microsoft.com/en-us/library/aa717047(v=vs.110).aspx
Regards
Kajal

Ordered delivery with NetNamedPipeBinding using oneWay calls

Is it possible to guarantee ordered delivery with oneWay calls using namedPipe binding?
I have a WCF service/client communicating using namedPipe binding. The client is exposing a callback contract in which all the methods in the callback are marked as OneWay. Something like this
[ServiceContract(CallbackContract = typeof(IMyServiceCallback))]
public interface IMyService
{
[OperationContract]
void MyOperation();
}
public interface IMyServiceCallback
{
[OperationContract(IsOneWay=true)]
void MyCallback1();
[OperationContract(IsOneWay=true)]
void MyCallback2();
}
At the server side, the implementation of MyOperation method always calls MyCallback1 first and then MyCallback2 but I am observing that sometimes the client receives the calls in the incorrect order (MyCallback2 first and then MyCallback1).
On searching the internet I found that the order is not guaranteed with oneway operation as mentioned here and also there is something called reliableSession which ensure message ordering.
All the examples on the internet for reliable session are with TCP binding (and not a single one with NamedPipeBinding) and the tcpBinding also has a property called ReliableSession which is not present on the NetNamedPipeBinding. So I am not sure whether reliable session is expected to work with NetNamedPipeBinding or not.
Question:
Does reliable session work with namedPipeBinding? If yes, how? If no, Is there any other approach with which I can guarantee ordered delivery?
http://msdn.microsoft.com/en-us/library/aa480191.aspx
Introduction to Reliable Messaging with the Windows Communication Foundation
...
The NetNamedPipeBinding sits on top of the Windows operating system's support for reliable message delivery and reliable streams through named pipes. Because named pipes are connection-oriented, readily support sessions, are reliable by design, and are typically not bridged, there is no need for WS-RM support in this binding.
Chances are, your messages are being delivered in the order the server sends them, and the latter is what you need to work with. The server may be running concurrently and offer no guarantee for ordered dispatch.
Then again, I could be wrong. From my link above, there are some attributes you can specify on your contract and implementation that control ordered delivery.
This question has some more information as well.

WCF: Is there a way to return an object that is able to execute on the server?

Coming from a Java background, this is the way I'm thinking:
The server provides an object to the client. This object should be able to execute on the server.
Server:
private string _S = "A";
public interface IFoo { void Bar(); }
private class Foo : IFoo {
void Bar() { _S = "B";}
}
public IFoo GetFoo() { return new Foo(); }
Client:
IFoo foo = serverChannel.GetFoo();
foo.Bar();
Is this possible? Or is my understanding wrong and this is not how it works in WCF? What would be a better design?
No, I don't think that'll work. You see: WCF is not some kind of a remoting, remote-object, or remote-procedure call mechamism.
WCF at its core is a messaging infrastructure. Your client make a call to a method on a client-side proxy; the WCF runtime on the client captures the input parameters and the method name and a few more bits and pieces, serializes them into a message (either text or binary), and send that message across the wire (using whatever transport you like). The server does the same thing in reverse, deserializes the message, instantiantes a service class, executes a method on that class, and packages the return values back into a serialized message.
But there's really no connection or remoting link between client. Anything that goes between the two has to be serializable - into XML text at its core. You can pass around concrete classes and so on - but you cannot pass around interface, object references etc.
No - you cannot send objects around. As marc_s pointed out, WCF is a message-oriented communications framework.
But, you do have different instancing options.
By default, Windows Communication Foundation instantiates services on a per-call basis: a service instance, a common language runtime (CLR) object, exists only while a client call is in progress. Every client request gets a new dedicated service instance. This is something like Stateless Session Beans in J2EE.
Another option is session-based activation, which is something like Stateful Session Beans in J2EE. Using this approach, when the client creates a new proxy to a service configured as session-aware, WCF activates a new service instance and attaches it to the session. Every message sent by the client over that proxy will go to the same instance on the server side.
This activation behavior is selectable with the ServiceContract attribute.
Juval Lowy has written a good article on instantiation options in WCF.
Within these instancing options, you may find something that works for you.

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