What is the difference between RequestInterceptor and MessageInspector? - c#

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

Related

NServiceBus sending message to one endpoint and waiting for reply in another

I'm using NServiceBus with RabbitMQ in my project. I have two services that don't know about each other and don't share anything. service1 publishes request messages to endpoint1 (queue1) and service2 listens to endpoint1 and publishes responses to endpoint2 (queue2). There are two questions:
How can service1 handle responses from service2 if service1 doesn't know the response message type but only expects some particular fields in the response message?
I want to create an async API method that sends a request to endpoint1 and waits for the response in endpoint2. Is it somehow possible at all? Also how can I ensure that the reply corresponds with the request?
I expect something like:
public async Task<object> SendRequest(string str) {
var request = new MyRequest(str);
await endPoint1.Publish(request);
var reply = await endPoint2.WaitingReply();
return reply;
}
I will appreciate any help.
Whenever two things communicate, there is always a contract. When functions call each other the contract is the parameters that are required to call that function. With messaging the message is the contract. The coupling is towards the message, not the sender or receiver.
I'm not really sure what you're trying to achieve? You mention an API which is async and endpoint1 and endpoint2.
First of all, there's asynchronous execution and asynchronous communication. The async part in your example code is asynchronous execution of two methods that have the word await in front of them. When we talk about sending messages, that's asynchronous communication. A message is put on the queue and then the code moves on and never looks back at the message. Even when you use the request/reply pattern, no code is actually waiting for a message.
You can wait for a message by blocking the thread, but I highly recommend you avoid that and not use the NServiceBus callback feature. If you think you have to, think again. If you still think so, read the red remarks on that page. If they can't convince you, contact Particular Software to have them explain another time why not. ;-)
It could be that you need a reply message for whatever reason. If you build some website using SignalR (for example) and you want to inform the user on the website when a message returned and some work was completed, you can wait for a reply message. The result is that the website itself becomes an endpoint.
So if the website is EndpointA and it sends a message to EndpointB, it is possible to reply to that message. EndpointA would then also need a message handler for that message. If EndpointB first needs to send a message to EndpointC, which in turn responds to EndpointB and only then it replies back to EndpointA, NServiceBus can't easily help. Not because it's impossible, but because you probably need another solution. EndpointA should probably not be waiting for that many endpoints to reply, so many things could go "wrong" and take too much time.
If you're interested to see how replies work in combination with SignalR and what not, you can check a demo I built for a presentation that has that.

How to send updates from server to clients?

I am building a c#/wpf project.
It's architecture is this:
A console application which will be on a virtual machine (or my home computer) that will be the server side.
A wpf application that will be the client app.
Now my problem is this - I want the server to be able to send changes to the clients. If for example I have a change for client ABC, I want the server to know how to call a service on the clients computer.
The problem is, that I don't know how the server will call the clients.
A small example in case I didn't explain it well:
The server is on computer 1, and there are two clients, on computers 2 and 3.
Client 2 has a Toyota car and client 3 has a BMW car.
The server on computer 1 wants to tell client 2 that it has a new car, an Avenger.
How do I keep track and call services on the clients?
I thought of saving their ip address (from calling ipconfig from the cmd) in the DB - but isn't that based on the WI-FI/network they are connected to?
Thanks for any help!
You could try implementing SignalR. It is a great library that uses web sockets to push data to clients.
Edit:
SignalR can help you solve your problem by allowing you to set up Hubs on your console app (server) that WPF application (clients) can connect to. When the clients start up you will register them with a specified Hub. When something changes on the server, you can push from the server Hub to the client. The client will receive the information from the server and allow you to handle it as you see fit.
Rough mockup of some code:
namepsace Server{}
public class YourHub : Hub {
public void SomeHubMethod(string userName) {
//clientMethodToCall is a method in the WPF application that
//will be called. Client needs to be registered to hub first.
Clients.User(userName).clientMethodToCall("This is a test.");
//One issue you may face is mapping client connections.
//There are a couple different ways/methodologies to do this.
//Just figure what will work best for you.
}
}
}
namespace Client{
public class HubService{
public IHubProxy CreateHubProxy(){
var hubConnection = new HubConnection("http://serverAddress:serverPort/");
IHubProxy yourHubProxy = hubConnection.CreateHubProxy("YourHub");
return yourHubProxy;
}
}
}
Then in your WPF window:
var hubService = new HubService();
var yourHubProxy = hubService.CreateHubProxy();
yourHubProxy.Start().Wait();
yourHubProxy.On("clientMethodToCall", () => DoSometingWithServerData());
You need to create some kind of subscription model for the clients to the server to handle a Publish-Subscribe channel (see http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html). The basic architecture is this:
Client sends a request to the messaging channel to register itself as a subscriber to a certain kind of message/event/etc.
Server sends messages to the channel to be delivered to subscribers to that message.
There are many ways to handle this. You could use some of the Azure services (like Event hub, or Topic) if you don't want to reinvent the wheel here. You could also have your server application track all of these things (updates to IP addresses, updates to subscription interest, making sure that messages don't get sent more than once; taking care of message durability [making sure messages get delivered even if the client is offline when the message gets created]).
In general, whatever solution you choose is plagued with a common problem - clients hide behind firewalls and have dynamic IP addresses. This makes it difficult (I've heard of technologies claiming to overcome this but haven't seen any in action) for a server to push to a client.
In reality, the client talks and the server listens and response. However, you can use this approach to simulate a push by;
1. polling (the client periodically asks for information)
2. long polling (the client asks for information and the server holds onto the request until information arrives or a timeout occurs)
3. sockets (the client requests server connection that is used for bi-directional communication for a period of time).
Knowing those terms, your next choice is to write your own or use a third-party service (azure, amazon, other) to deliver messages for you. I personally like long polling because it is easy to implement. In my application, I have the following setup.
A web API server on Azure with and endpoint that listens for message requests
A simple loop inside the server code that checks the database for new messages every 100ms.
A client that calls the API, handling the response.
As mentioned, there are many ways to do this. In your particular case, one way would be as follows.
Client A calls server API to listen for message
Server holds onto call, waiting for new message entry in database
Client B calls server API to post new message
Server saves message to database
Server instance from step 2 sees new message
Server returns message to Client A.
Also, the message doesn't have to be stored in a database - it just depends on your needs.
Sounds like you want to track users à la https://www.simple-talk.com/dotnet/asp.net/tracking-online-users-with-signalr/ , but in a desktop app in the sense of http://www.codeproject.com/Articles/804770/Implementing-SignalR-in-Desktop-Applications or damienbod.wordpress.com/2013/11/20/signalr-a-complete-wpf-client-using-mvvm/ .

wcf oneway non blocking operation

I need such scenario: client sends message to server, not waiting for response, and don't care, if message was send properly.
using(host.RemoteService client = new host.RemoteService())
{
client.Open();
cliend.SendMessage("msg");
}
in scenario when firewall is on, or there is no connection to the internet, client dies at "SendMessage". I mean program stops to respond. I wish program don't care about the result. I mean if there is no connection, i wish program to go further, omitting "SendMessage" or sth like that.
What should I do, is there any solution for non blocking method?
Try something like this in your service contract:
[OperationContract(IsOneWay=true)]
void Send(string message);
See the following link:
One Way Operation in WCF
Edit: OP was already using my suggested solution.
Suggested approaches to solve the issue - taken from MSDN (One-Way Services):
Clients Blocking with One-Way Operations
It is important to realize that while some one-way applications return
as soon as the outbound data is written to the network connection, in
several scenarios the implementation of a binding or of a service can
cause a WCF client to block using one-way operations. In WCF client
applications, the WCF client object does not return until the outbound
data has been written to the network connection. This is true for
all message exchange patterns, including one-way operations; this
means that any problem writing the data to the transport prevents the
client from returning. Depending upon the problem, the result could
be an exception or a delay in sending messages to the service.
You can mitigate some of this problem by inserting a buffer between
the client object and the client transport's send operation. For
example, using asynchronous calls or using an in-memory message
queue can enable the client object to return quickly. Both
approaches may increase functionality, but the size of the thread pool
and the message queue still enforce limits.
It is recommended, instead, that you examine the various controls on
the service as well as on the client, and then test your application
scenarios to determine the best configuration on either side. For
example, if the use of sessions is blocking the processing of messages
on your service, you can set the
System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode
property to PerCall so that each message can be processed by a
different service instance, and set the ConcurrencyMode to
Multiple in order to allow more than one thread to dispatch messages
at a time. Another approach is to increase the read quotas of the
service and client bindings.
Modify your attribute
[OperationContract(IsOneWay=true)]

delegates across different machines

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)

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.

Categories

Resources