Instantiate WCF service object on server, not client? - c#

I am writing two applications in C# that need to be able to communicate (in one direction only). The two apps will always run on the same machine, so using WCF with named pipes, and self-hosting the WCF service, seemed like the logical choice.
I understand that I can use InstanceContextMode to configure if a service instance is instantiated per session, per call, or if there should just be a single instance. In my case I want a single instance, because I will have just the two apps running, so there will be a single client and a single server.
But here's where I'm stuck. When my client makes a call on the service, which I'm doing this way:
var myServiceFactory = new ChannelFactory<IMyService>(
new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyService"));
IMyService myService = myServiceFactory.CreateChannel();
myService.DoStuff();
I don't want a new server object instance to be created on the server. Instead I'd like myService to point at the (one and only) IMyService instance that has already been constructed on the server. At the moment, a second IMyService instance gets constructed.
In other words, I want my server object to be constructed by the server (when the server starts up), not when a client first makes a call.
Can anyone explain how to do this? From what I understand, .NET Remoting makes this quite easy, and WCF has supposedly replaced Remoting, so there must be an easy way... right?

WCF's ServiceHost has a constructor which takes a singleton instance of the service class rather than the service type, for exactly this purpose. You must set InstanceContextMode to Singleton if using this constructor in your service host.
Note that in the client side code you quote, IMyService myService is not what you call "the server object" ... it is the client-side proxy through which WCF routes messages from the client to the actual service.

Related

WCF duplex: calling callback outside class of WCF-service

I develop WCF-service with duplex mode and use nettcpbinding. I use .NET 4.5. I have only one client and only one server and there is a lot of logic between its. The client always the first begins communication with the server. I want that server can call client functions outside WCF-service class. I try to use duplex mode for this purpose.
This is my WCF-service:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
...
public IServiceCallback Callback
{
get
{
return OperationContext.Current.GetCallbackChannel<IServiceCallback>();
}
}
}
I have no problem when I call my callback within OperationContract functions of my service:
Callback.foo();
But when I try to call it outside class Service for example:
service = new Service();
service.Callback.foo();
I got NullReferenceException of OperationContext.Current. I found a lot of information about the similar problems on the SO and other resources but it can't help to decide my problem.
Are there any solutions of my issue or may be workarounds for calling of callback? At the moment I plan to create one more WCF-service for my purpose but I feel that this is bad solution. Thanks for attention.
OperationContext.Current has a meaning only when it runs from the same thread that handles the current client request. You did not specify where exactly you calls this from.

How to notify the host of a WCF service when a client connects?

I have a WCF service that is hosted by a windows service. I can't figure out how to inform the windows service when a client connects to the WCF service. Basically all I have in the windows service to start the WCF service is this:
private ServiceHost sHost;
WCF.WCFService wcfService = new WCF.WCFService();
sHost = new ServiceHost(wcfService);
sHost.Open();
I am able to call methods in the WCF service with the windows service using the wcfService object. Is there some way to have some kind of event that would fire when a client connects to WCF service?
The service runs as an object which is instantiated according to the ServiceBehaviourAttribute property InstanceContextMode
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService
{
// ...
The values for InstanceContextMode are
Single - a single instance of the service runs for all sessions and calls
PerSession - an instance of the service runs for each session (i.e. each client)
PerCall - an instance of the service is instantiated for each call, even from a single client
The default value is PerSession, and this makes sense for most scenarios. Assuming you're using PerSession, you can put whatever 'connect logic' you like inside the constructor for the service.
// you don't need to specify PerSession as it is default, but I have for clarity
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService : IMyService
{
public MyService()
{
// constructor will be called for each new client session
// eg fire an Event, log a new client has connected, etc
}
// ...
}
You need to be careful running code in the constructor, because the service will not be available until the constructor has completed. If you want to do anything that may take time, fire an event or send a thread to perform that work.
I found the best answer here: Subscribe to events within a WCF service
As suspected you can create an event handler in the WCF service that can be picked up by the host.

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.

Confusion in .net Remoting

I am studying .net Remoting
I've read from MSDN, but in one step I am facing some confusion..
Three steps are required for remoting purpose.
1 - RemoteObject
2 - Host
3 - Client
creating RemoteObject and Host is fine. I understand all the things, it uses Configuration File for both Host and Client Configuration. In Client it uses the following code
public static void Main(){
RemotingConfiguration.Configure("Client.exe.config");
RemotableType remoteObject = new RemotableType();
Console.WriteLine(remoteObject.SayHello());
}
Here it is creating Object of RemotableType with new operator. Where as this Client application has reference of RemotableType.dll.
When this dll is available locally then what is the purpose of calling SayHello() remotely?
I ran this client without running server and it still displays me Hello World message.
Is this creation of remoteObject with new operator is valid here?
Where as the other method of getting remoteobject is:
RObject remoteObject = (RObject)Activator.GetObject(typeof(RObject), "tcp://localhost:9999/RObject");
Usually you will create two DLLs: One that contains an interface definitions for your remotable object and another one that contains the implementation of the interface definitions.
You will then add the interface definition DLL to the client, while the server needs both DLLs. The client will then create instances of the class using the Activator.GetObject(...) call.
If you reference the implementation DLL from your client - as you pointed out - you do not have any advantages from the client/server implementation.
Calling new RemotableType() is simply creating a local instance of RemotableType on the client. Calling any methods on it will get called on this instance.
Using Activator.GetObject() is creating a TransparentProxy in the client to the instance of RemotableType that was published in the host application. Calling any methods on this will make a remote call to the host application and will execute there. If your implementaion of SayHello was to return the name of the entry assembly (using Assembly.GetEntryAssembly()), it would return Host.exe even though you are running in the client.

Can an WCF Service create his own host?

I have a client / server type of application and I'd like the server object to create his own host. It looks something like this:
public class Server : IServer {
private ServiceHost m_Host;
public Server() {
m_Host = new ServiceHost(this);
m_Host.Open();
}
}
It seems to work fine when there are few message transfers occurring. But when it starts to speed up (my application requires that data is transfered every 50 ms), the server hangs and and the transfers stop after a few seconds without throwing an exception.
So, is it possible for an object to create his own host? Or do I really have to create it in the main() or do something else?
EDIT: I think the problem in this case is that I want the object that implements the service itself to create his own ServiceHost.
There's nothing really stopping any object to create an instance of ServiceHost.
The big question then is - can you guarantee that your object containing the service host is "alive"? Or was it garbage collected by any chance?
We use Windows (NT) Services to host our own custom service host classes to provide around-the-clock availability for WCF services - works just fine.
Marc
To be a WCF service it simply needs to implement the service contract. There's nothing to stop you adding more methods to open and close an instance of itself as a service.
Check out the ServiceBehaviorAttribute which allows you to specify how your service ... behaves. ;) The ConcurrencyMode property defined the support for multithreading and defaults to single threaded mode, and the InstanceContextMode defines if the service object is per session, per call or singleton.
Quote from ConcurrencyMode:
Setting ConcurrencyMode to Single instructs the system to restrict instances of the service to one thread of execution at a time, which frees you from dealing with threading issues. A value of Multiple means that service objects can be executed by multiple threads at any one time. In this case, you must ensure thread safety.
Quote from InstanceContextMode:
If the InstanceContextMode value is set to Single the result is that your service can only process one message at a time unless you also set the ConcurrencyMode value to Multiple.
We could really use some code examples of your service to further debug the behavior you're describing. For example, is your service object expensive to construct (assuming non singleton implementation), or do the operation slow down? Do you know where the time is spent, is it code, or could it as well be some firewall that limits connection? What protocol do you use?

Categories

Resources