.NET Remoting: how to access server application objects from remotable object? - c#

I'm writing a windows service application, which will be accessed through .NET Remoting.
The problem is I can't figure out how to access service objects from remotable class.
For example, I've a handler class:
class Service_console_handler
{
public int something_more = 20;
//some code...
TcpChannel serverChannel = new TcpChannel(9090);
ChannelServices.RegisterChannel(serverChannel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(RemoteObject), "RemoteObject.rem",
WellKnownObjectMode.Singleton);
//from here on RemoteObject is accessible by clients.
//some more code doing something and preparing the data...
}
And I've a remotable class:
public class RemoteObject : MarshalByRefObject
{
private int something = 10;
public int Get_something()
{
return something;
}
}
Clients can access data in RemoteObect with no problem. But how can I access Service_console_handler object (i.e. to retrieve useful info from something_more)?
Sorry for dumb questions and thanks in advance.

What you want is somehow to access the instance of ServiceConsoleHandler via a RemoteObject instance, which is visible for the client.
For this you need to consider two things: (1) Get control over the object construction of the RemoteObject instance and make it accessible and (2) modify ServiceConsoleHandler so it can be accessed remotely.
(1)
How would you construct a RemoteObject instance in ServiceConsoleHandler, if you don’t need to consider remoting?
I guess you would do something like this:
class ServiceConsoleHandler
{
…
RemoteObject remoteObject = new RemoteObject();
// now assume that you also already have
// modified the RemoteObject class so it can hold
// a reference to your server:
remoteObject.Server = this;
…
}
It would be nice if you could make this object accessible for the client. You can do this by using RemotingServices.Marshal instead of RemotingConfiguration.RegisterWellKnownServiceType:
class ServiceConsoleHandler
{
…
TcpServerChannel channel = new TcpServerChannel(9090);
ChannelServices.RegisterChannel(channel, true);
RemoteObject remoteObject = new RemoteObject();
remoteObject.Server = this;
RemotingServices.Marshal(remoteObject, "RemoteObject.rem");
…
}
(2)
If you execute the code right now and access the remoteObject.Server in the client code you would get some remoting exception, because the class ServiceConsoleHandler cannot be accessed remotely. Therefore you need the add the [Serializable] attribute:
[Serializable]
class ServiceConsoleHandler
{ … }
Reason: Types which should be accessed remotely, need to be marshaled to some special transferrable representation. This way they can be squeezed through the TCP port and transferred via the TCP protocol. Basic data types can by marshaled by the framework, so you don't need to think about them. For custom types you will need to state, how to do this. One way to do this is by subclassing from MarshalByRefObject. That’s exactly what you have already done with RemoteObject. Another way is to mark your custom classes as [Serializable] as shown above.
That’s it. Now you should be able to access the server’s field in the client code. Note that you don’t need your existing code for object activation:
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, true);
RemoteObject remoteObject = (RemoteObject)Activator.GetObject(
typeof(RemoteObject), "tcp://localhost:9090/RemoteObject.rem");
Console.WriteLine(remoteObject.Server.SomethingMore);
For me .NET remoting is full of funny surprises and sleepless nights. To counter this, make yourself familiar with the remoting concepts (which are from my point of view poorly documented). Dig into the serialization concept (MarshalByRefObject vs. [Serializable]). If you want to make a production code out of it, think a very good ways to handle remoting exceptions. Also consider multithreading. There could be more than one client using this remote object at once.
Have fun!

Thank you! I very much appreciate thoroughness and clarity of you answer.
Most bizzare thing is that I didn't even know that you can publish object instance. About a dozen simple tutorials I studied proposed RemotingConfiguration.RegisterWellKnownServiceType as only method to do remoting. Stupid me.
Now remoting looks much more useful to me. I just wrote a quick test application and it worked. Thanks again.

Related

Reference object in two classes C#

Let's go straight to my probably fairly simple problem.
I have a LoginService class in my Services folder which makes a connection with the server. I have another UserModel where I want to receive information from the server. In order not to login again (which would be stupid), I need to maintain the client reference in both files having the same value. In other words, I need to be able to access the same object from a different class (make another reference).
I have tried and tried and searched but I am missing something.
A fairly similar post that I found that still didn't solve mine is this.
The code in my LoginService:
namespace App_Name.Services
{
class LoginService
{
public static Class_Name client;
public async Task MakeConnectionAsync(string userToken)
{
client = new Class_Name();
PasswordVault vault = new PasswordVault();
await client.LoginAsync(TokenType.User, userToken);
await client.StartAsync();
}
So now I want to get the user avatar on my UserModel.cs:
namespace App_Name.Models
{
class UserModel
{
public string GetAvatar()
{
return LoginService.client.CurrentUser.GetAvatarUrl();
}
But it always gives an exception because it tries but there is no connection.
I am sure that it was Connected because in order to load the UserModel it has to be a successful connection.
Any ideas ?
When you call directly the client.CurrentUser.GetAvatarUrl() method, its not determined by the LoginService class. You should be create the Login class before the usage. Also you are using async tasks on your LoginService class, you must confirm that already create user by your UserModel class.
For best practice you can create instance with your constructor like this.
static class LoginService
{
public static Class_Name client;
static LoginService()
{
client = new Class_Name();
}
If you want to go with static (which I not prefer for service level) not use static for like this purpose of usage.
Firstly you should be check dependency injection concepts; i suggest unity and structuremap containers. You can create your consume services by your classes without any object null ref. exception. Dependency injection decrease on coupling and null reference exception.
Ehmmm, for anyone that can use this as a reference, my code above is just fine.
The problem was with the connection API not returning the status immediately. A delay of 2 seconds solved my problem. Thanks everyone for their help.

How to make an existing C# dll available as a web service

In principal this looks like a simple job, but I wonder if anyone can take me through the basic steps?
I have an application API, implemented as a C# class library project in the application solution. People can thus write their own conventional .Net applications using this API by referencing the dll directly.
I now need to make exactly the same functionality available as a web service so applications can be written to remotely access the same API over http. Ideally I would just like to tag the API classes and methods with appropriate web service attributes, but I suspect there is more to it than that. I also must have the API dll continue to work as an API for desktop applications as it does at present.
Is this do-able? If so, what are the steps I need to take?
The web service can be composed mostly of wrapper methods. Take the simple case...
If your API method in the assembly is
public void DoFoo(string bar)
Then your web API method (your choice of implementation, such as WebAPI, ASMX web service, etc) will look like
public void DoFoo(string bar) {
// ... initialization or validation
try {
refToDll.DoFoo(bar);
} catch (Exception e) {
// implementation specific return of error.
}
}
If you have mostly static methods or those taking primitive types, that becomes more easy. If your API has types defined, this becomes harder. You will need to change the type signature and reimplement methods. Without your API it would be difficult to make specific suggestions. However, there are several options. If you had
public class BazClass {
public string GetScore() {
return scores.Sum();
}
}
You basically need to ensure that the remote side (the web API) can reconstruct the context from your client side. You have to pass in a serializable instance or other representation of BazClass and let the remote API work on it. It just doesn't exist otherwise. You could also create a bunch of methods that store state on the server and you work with a "handle" on the client side, or object reference, but that will have to be a design decision (just look at interop with native libraries, and handles, and translate to cross network). Example:
public string BazGetScore(Transport.BazClass baz) {
// Depending on the framework and class (all public getters/setters)?
// your framework may allow for transparent serialization
BazClass bazReal = bazFactory(baz);
string score = bazReal.GetScore();
return score;
}
How much of your source API is based on interfaces? This may make the creation of a Proxy class much more transparent to your end user. If you have
public class Baz : IBaz { ... }
Then you can create a Proxy class that acts just like an IBaz but calls the remote API instead of acting locally. Depending on your framework and tooling, this may be able to be facilitated by the tools.
namespace RemoteAPIProxy {
public class Baz : IBaz {
public string GetScore() {
// initialization of network, API, etc
Transport.Baz baz = new Transport.Baz.From(this);
string score = CallRemoteAPI("BazGetScore", baz);
return score;
}
}
}
In summary, you may have to make some intermediate classes depending on if you need to support state, non-public methods, or full scope. The "how" can mostly be considered just another wrapper, but you need to be conscious of how you get your local state over the wire and into the context of the remote API. Use interfaces, serialization helpers, and lightweight transport objects for state to help with the "glue". Remember, the only "I" in "API" is for "Interface", so you might want to make sure you have some. Good luck!

Is it possible to track all outgoing WCF call?

Our application calls external services like
//in client factory
FooServiceClient client = new FooServiceClient(binding, endpointAddress);
//in application code
client.BarMethod(); //or other methods
Is it possible to track all of these calls (e.g by events or something like that) so that the application can collect the statistics like number of call, response time, etc? Note that my application itself needs to access the values, not only to write to a log file.
What I can think is to create a subclass of VisualStudio-generated FooServiceClient and then add codes like this
override void BarMethod()
{
RaiseStart("BarMethod");
base.BarMethod();
RaiseEnd("BarMethod);
}
and the RaiseStart and RaiseEnd method will raise events that will be listened by my code.
But this seems tedious (because there are a lot of methods to override) and there is a lot of repeated codes, my code needs to change everytime the service contract changes, etc. Is there a simpler way to achieve this, for example by using reflection to create the subclass or by tapping into a built-in method in WCF, if any?
The first thing I would look at is to see if the counters available in your server's Performance Monitor can provide you with the kind of feedback you need. There's built in counters for a variety of metrics for ServiceModel Endpoints, Operations and Services. Here is some more info http://msdn.microsoft.com/en-us/library/ms735098.aspx
You could try building an implementation of IClientMessageInspector, which has a method to be called before the request is sent and when the reply is received. You can inspect the message, make logs etc in these methods.
You provide an implementation of IEndpointBehavior which applies your message inspector, and then add the endpoint behavior to your proxy client instance.
client.Endpoint.Behaviors.Add(new MyEndpointBehavior())
Check out the docs for MessageInspectors and EndpointBehaviors, there are many different ways of applying them (attributes, code, endpoint xml config), I can't remember of the top of my head which apply to which, as there also IServiceBehavior and IContractBehavior. I do know for sure that the endpoint behaviors can be added to the client proxy collection though.
I found a simple way to do it by using dynamic proxy, for example Castle's Dynamic Proxy.
Firstly, use a factory method to generate your client object
IFooClient GetClient()
{
FooClient client = new FooClient(); //or new FooClient(binding, endpointAddress); if you want
ProxyGenerator pg = new ProxyGenerator();
return pg.CreateInterfaceProxyWithTarget<IFoo>(client, new WcfCallInterceptor());
}
And define the interceptor
internal class WcfCallInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
RaiseStart(invocation.Method.Name);
invocation.Proceed();
}
finally
{
RaiseEnd(invocation.Method.Name);
}
}
//you can define your implementation for RaiseStart and RaiseEnd
}
I can also change the intercept method as I wish, for example I can add a catch block to call a different handler in case the method throw exception, etc.

Handling client/server messages?

From my client/server I receive serialized data, once the data is deserialized, it goes into a command handler where receivedData.Action is the ClientMessage:
Command._handlers[receivedData.Action].Handle(receivedData.Profile);
The command handler will work out the client message and return the response that should be given to the client.
I have an enum for the client messages as follow:
public enum ClientMessage
{
INIT = 1,
NEW_PROFILE,
UPDATE_PROFILE_EMAIL,
UPDATE_PROFILE_PASSWORD,
UPDATE_PROFILE_PHONE,
UPDATE_PROFILE_DATE,
UPDATE_PROFILE_SECRET_ANSWER,
UPDATE_PROFILE_POSTAL_CODE,
UPDATE_SUCCESS,
PING,
PONG,
QUIT
}
What I am having a difficult is how to have all the actions written, for example:
Should I have a separated enum for what the client sends and another for what the server should reply with ?
Or should I have a single enum with all messages and follow it as requested ?
Or how should I go about defining the messages and handling it ?
This is what my server/client currently does just to give you a better view:
Server starts
Client connects
Client send auth to server
Server verify client and send connected approval message
Client will from there start sending and updating profiles to the server
This is roughly an example only.
IPacketHandler
public interface IPacketHandler
{
MyCommunicationData Handle(ProfileData profile);
}
Command
public class Command
{
public static Dictionary<ClientMessage, IPacketHandler> _handlers = new Dictionary<ClientMessage, IPacketHandler>()
{
{ClientMessage.INIT, new Init()},
{ClientMessage.NEW_PROFILE, new NewProfile()},
{ClientMessage.UPDATE_PROFILE_EMAIL, new UpdateEmail()},
{ClientMessage.UPDATE_PROFILE_PASSWORD, new UpdatePassword()},
{ClientMessage.UPDATE_PROFILE_PHONE, new UpdatePhone()},
{ClientMessage.UPDATE_PROFILE_DATE, new UpdateDate()},
{ClientMessage.UPDATE_PROFILE_SECRET_ANSWER, new UpdateSecretAnswer()},
{ClientMessage.UPDATE_PROFILE_POSTAL_CODE, new UpdatePostalCode()},
{ClientMessage.UPDATE_SUCCESS, new Success()},
{ClientMessage.PING, new Ping()},
{ClientMessage.PONG, new Pong()},
{ClientMessage.QUIT, new Quit()},
};
}
Example of the INIT
public class Init : IPacketHandler
{
public MyCommunicationData Handle(ProfileData profile)
{
// Some verification to auth the client here
// bla bla
// return response
return new MyCommunicationData() { Action = ClientMessage.CONNECTED };
}
}
PS: If my title is off and you have a better suggestion let me know or if you can go ahead and update it, I was not sure of how to describe this in English.
If your question is about how to design the class and interactions as I understood it, then I would - and it's totally dependant on the specifics of your application - separate this big Enumerations type into separate, smaller ones that are more descriptive of what they do, and of your intentions, for example, ProfileAction, ActionResult, PingStatus etc.. Then when you're using these enums, you make sure that you get compiler-time checks that you're doing it correctly, otherwise, what you're doing is almost like just passing strings.
It also has to do with sticking to Single Responsibility principle in OO design: an object should have single responsibility. Your enum as it stands now has more than one responsibility.
With issues like these, I find it helpful to look at what .NET framework does: for example look at Ping class and how it uses PingStatus enumerations and other enumerations as well.
Not sure I'd use an enum at all. They are great inside a peice of code, exposed as communicated value, they are considerably less than great.
For me I'd have a different class per message, not one message with a god property.

Use WCF to broadcast/notify different object?

Just... doing some practices.
Structure:
A Client WPF App and a Server WPF App, both of them Self Host a WCF service.
Client WPF contains a View, which contains the ListBox
What I want to do:
Server WPF will create channels to the Client's WCF and constantly Send Message.
Client's WCF will receive the message and boardcast to any classes that subscribe it. (Or maybe I will say the classes that observe it).
In this case, the Client's View should receive message and put into the listbox.
Problems:
So the problem is how do I let the View observe the WCF? Or get notify by the WCF?
The Client's WCF is created by using ServiceHost myHost = new ServiceHost(typeof(MyClient));
How can I let the WCF have reference to my Client's View and do the notification?
Throught:
Somehow hardcoding the Client's WCF to have the View reference internally (this...doesn't make sense)
Observer Pattern? Make a static Subject class tht's implement Client's WCF Interface.
In the Client's will routers all the methods calls to Subject class. The View will also implement Client's WCF Interface and attaches to Subject class. Finally Subject class will routers calls to all the Views....
Something like this:
public class ClientServiceObserver : IClient
{
static List<IClient> _observers = new List<IClient>();
public static void Attach(IClient client)
{
_observers.Add(client);
}
public static void Detach(IClient client)
{
_observers.Remove(client);
}
public void SendCallbackMessage(string message)
{
foreach (IClient client in _observers)
{
client.SendCallbackMessage(message);
}
}
}
3.Everything similar to option 2, but instead of router all calls everywhere, might as well let WCF just notify Subject class there is update, then View will just get notify and create channel to Server to get it own data.....
All above options doens't really sounds good... and option 2 I don't even know if that's Observer Patterns anymore....
I wonder what will be the best practice to do it?
Please look EventAggregator pattern to achieve what you are trying. EvenAggregator implementation are available in
MVVM Light
Microsoft PRISM
Caliburn.Micro
See example for using EventAggregator here
You do not need to use the complete framework mentioned here, you can pull out the EventAggregator class and use it.

Categories

Resources