RemotingServices.IsObjectOutOfAppDomain when it will return false? - c#

As per Remote Object definition- Any object outside the application domain of the caller should be considered remote.
RemotingServices.IsObjectOutOfAppDomain- returns false if remote object resides in the same app domain.
In the MSDN article Microsoft .NET Remoting: A Technical Overview I
found the following statement (in the paragraph "Proxy Objects") about
method calls on remote objects:
...the [method] call is examined to determine if it is a valid method
of the remote object and if an instance of the remote object resides in
the same application domain as the proxy. If this is true, a simple
method call is routed to the actual object.
So I am surprised when the remote object and proxy will reside in the same app domain.
sample example:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace RemotingSamples
{
public class HelloServer : MarshalByRefObject
{
public HelloServer()
{
Console.WriteLine("HelloServer activated");
}
public String HelloMethod(String name)
{
return "Hi there " + name;
}
}
public class Server
{
public static int Main(string [] args)
{
// server code
ChannelServices.RegisterChannel(new TcpChannel(8085));
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(HelloServer), "SayHelloSingleton",
WellKnownObjectMode.Singleton);
// client code
HelloServer obj = HelloServer)Activator.GetObject(
typeof(HelloServer), "tcp://localhost:8085/SayHelloSingleton");
System.Console.WriteLine(
"IsTransparentProxy={0}, IsOutOfAppDomain={1}",
RemotingServices.IsTransparentProxy(obj),
RemotingServices.IsObjectOutOfAppDomain(obj));
Console.WriteLine(obj.HelloMethod("server"));
return 0;
}
}
}

Well, one obvious case when it will return false is when the object isn't a proxy, but is a regular .NET object in the local domain (no remoting involved).
I don't understand the MSDN note fully, either ;-p

Related

Two questions about Remoting

【Question1】
When in the Client-Activation mode for Remoting:
RemotingConfiguration.RegisterActivatedClientType(
typeof(ServerRemoteObject.ServerObject),
"tcp://localhost:8080/ServiceMessage");
ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();
Suppose "ServiceRemoteObject" is a class inherited from MarshalByRefObject and it has a default public constructor, and it's referred by the client side application.
So if I say:
ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();
How does the client application know whether I'm creating the serverObj instance through the Remoting, not directly creating that instance by "new" locally?
【Question 2】
I don't want to refer the ServerRemoteObject from the server side, so I just tricked the server side by creating the same class at the client side:
public class ServerObject:MarshalByRefObject
{
public ServerObj()
{
throw new System.NotImplementedException();
}
public Person GetPersonInfo(string name,string sex,int age)
{
throw new System.NotImplementedException();
}
}
This also works fine, why? Because in my mind, the server-side class's namespaces... aren't the same as the client one, which means I've cheated the server-side. But How it can be converted?

Suggest a design pattern for implementing fail over mechanism

I have an application(say App1) which is connected to another application (App2) via .net remoting. App2 acts as a server.. If App2 goes down App1 will not be able to pull data from App2. We are planning to run an instance of App2(say App2a) in another machine so that if App2 goes down App1 automatically takes the data from App2a. When App2 runs again.. App1 will need to take the data from App2. The fail over mechanism is not implemented yet... Please suggest a design pattern so that in future any number of server instances can be added for App1 to pull data.
Thanks
The closest design pattern that I can think of is the Chain of Responsibility pattern.
The idea is that:
You build a chain of objects (servers)
Let the object (server) handle the request
If it is unable to do so, pass the request down the chain
Code:
// Server interface
public interface IServer
{
object FetchData(object param);
}
public class ServerProxyBase: IServer
{
// Successor.
// Alternate server to contact if the current instance fails.
public ServerBase AlternateServerProxy { get; set; }
// Interface
public virtual object FetchData(object param)
{
if (AlternateServerProxy != null)
{
return AlternateServerProxy.FetchData(param);
}
throw new NotImplementedException("Unable to recover");
}
}
// Server implementation
public class ServerProxy : ServerProxyBase
{
// Interface implementation
public override object FetchData(object param)
{
try
{
// Contact actual server and return data
// Remoting/WCF code in here...
}
catch
{
// If fail to contact server,
// run base method (attempt to recover)
return base.FetchData(param);
}
}
}
public class Client
{
private IServer _serverProxy;
public Client()
{
// Wire up main server, and its failover/retry servers
_serverProxy = new ServerProxy("mainserver:2712")
{
AlternateServerProxy = new ServerProxy("failover1:2712")
{
AlternateServerProxy = new ServerProxy("failover2:2712")
}
};
}
}
This example wires up a chain of 3 servers (mainserver, failover1, failover2).
The call the FetchData() will always attempt to go to mainserver.
When it fails, it'll then attempt failover1, followed by failover2, before finally throwing an exception.
If it were up to me, I wouldn't mind using something quick and dirty such as:
public class FailoverServerProxy: IServer
{
private readonly List<ServerProxy> _servers;
public FailoverServerProxy RegisterServer(Server server)
{
_servers.Add(server);
return this;
}
// Implement interface
public object FetchData(object param)
{
foreach(var server in _servers)
{
try
{
return server.FetchData(param);
}
catch
{
// Failed. Continue to next server in list
continue;
}
}
// No more servers to try. No longer able to recover
throw new Exception("Unable to fetch data");
}
}
public class Client
{
private IServer _serverProxy;
public Client()
{
// Wire up main server, and its failover/retry servers
_serverProxy = new FailoverServerProxy()
.RegisterServer("mainserver:2712")
.RegisterServer("failover1:2712")
.RegisterServer("failover2:2712");
}
}
I think it borrows ideas from other patterns such as Facade, Strategy and Proxy.
But my motivations are simply to:
Make the least impact on existing classes (ie, No extra property in the Server class)
Separation of concerns:
Central class for the server's failover/recovery logic.
Keep the failover/recovery's implementation hidden from the Client/Server.

How share data in WCF webservice

In order to call webservices dynamicly, I use WCF Dynamic Proxy from Microsoft
If I understood properly how it works, the code load the wsdl and compile on system class in order to consume distant webservice. I put this code in a "generic webservice". Its goal is to call any webservice with a request in parameter, and respond the answer of the webservice called.
But a problem appears : each request to this "generic webservice" pulls a new compilation of the proxy, and use time and ressources of the server.
My objective is to save instance of each proxies during a laps of time, and renew the instance when this laps is reached.
After few hours of googling, I found two ways :
Use my WCF webservice "by session", but I don't find any tutorial which explains how create easily the session layer
Use a singleton in order to save my datas and mutualize them with all instances of webservice
I exclude the first solution because I don't know how to do this. So I decided to use the second way.
There is my implementation :
FactoryTest is the singleton, contening the hashtable with instances
ProxyTest is the class which contains information about each instances of distant webservices
There is the code of FactoryTest :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WcfSamples.DynamicProxy;
using System.Threading;
using System.Collections;
namespace WS_Generic
{
public sealed class FactoryTest
{
private static object syncRoot = new Object();
private static Hashtable hashFactory = new Hashtable();
public static DynamicProxy getProxy(String sServiceWsdl, String sContract)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
lock (syncRoot)
{
if (hashFactory[sServiceWsdl] == null || ((ProxyTest)hashFactory[sServiceWsdl]).getTimeFromCreation().TotalSeconds > 60 * 60 * 6)
{
hashFactory.Add(sServiceWsdl, new ProxyTest(sServiceWsdl, sContract));
}
}
}
return ((ProxyTest)hashFactory[sServiceWsdl]).getProxy();
}
public static bool isProxyExists(String sServiceWsdl, String sContract)
{
lock (syncRoot)
{
return hashFactory[sServiceWsdl] == null ? false : true;
}
}
}
}
There is the code of ProxyTest :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WcfSamples.DynamicProxy;
namespace WS_Generic
{
public class ProxyTest
{
private DateTime instanceCreation;
private String sServiceWsdl;
private String sContract;
private DynamicProxyFactory factory;
private volatile DynamicProxy proxy;
public ProxyTest(String sServiceWsdl, String sContract)
{
instanceCreation = DateTime.Now;
this.sServiceWsdl = sServiceWsdl;
this.sContract = sContract;
this.factory = new DynamicProxyFactory(this.sServiceWsdl);
this.proxy = factory.CreateProxy(this.sContract);
}
public DynamicProxy getProxy()
{
return proxy;
}
public TimeSpan getTimeFromCreation()
{
return DateTime.Now.Subtract(instanceCreation);
}
}
}
The problem is the webservice seems to reset the static status of FactoryTest after each call. So each time I called the webservice, my hashtable is empty and the factory create a new instance.
If anybody had already the problem of share datas between differents threads in WCF webservice (and found the solution), thanks in advance to give me some tips :)
PS : Sorry for my english, that's not my native language
If you store data in static variable WCF itself will not affect their purging. The problem must be somewhere else (application restart, app domain recreation, etc.).
Btw. this solution has only very limited usage because long living shared proxies should not be used and in many cases it can result in unexpected behavior. It can perhaps work only for services using basicHttpBinding.

Specific network interface IPv4 availability - No connectivity, Local, Internet

How to identify connectivity status of a specific NetworkInterface ?
NetworkInterface[] nets = NetworkInterface.GetAllNetworkInterfaces();
foreach (var n in nets)
{
// TODO: determine connectivity status of each network interface
// ( mainly interested in IPv4 connectivity )
}
This question is not about general internet connectivity and as such using say GetIsNetworkAvailable() is not a solution
OperationalStatus.Up can be used to filter out some inactive network interfaces, but not all - OperationalStatus.Up leaves in some interfaces that show "No network access" for both IPv4 and IPv6
I'm also aware how to get the IPv4 UnicastAddresses, but then what / is that useful?
I could not find anything relevant in these sections of WMI
i.e. extracting per interface status as Internet, Local, Limited or None
As mentioned in a comment above you need to use Network List Manager as explained there
To do so first add a reference to it as shown in the the screenshot below.
Right click on your project in your Visual Studio solution. Select Add > Reference... Go to COM and find the "Network List Manager 1.0 Type Library" entry using the search box.
That will generate an Interop DLL to this COM interface in your binary output folder. That DLL is named Interop.NETWORKLIST.dll.
In your Solution Explorer you can right click on the NETWORKLIST reference you just added and select "View in Object Browser" to inspect the interfaces you get access to.
From here you can implement a Network Manager class as shown below to subscribe to connectivity change events.
using System;
using System.Runtime.InteropServices.ComTypes;
using System.Diagnostics;
using NETWORKLIST;
namespace SharpDisplayManager
{
public class NetworkManager: INetworkListManagerEvents, IDisposable
{
public delegate void OnConnectivityChangedDelegate(NetworkManager aNetworkManager, NLM_CONNECTIVITY aConnectivity);
public event OnConnectivityChangedDelegate OnConnectivityChanged;
private int iCookie = 0;
private IConnectionPoint iConnectionPoint;
private INetworkListManager iNetworkListManager;
public NetworkManager()
{
iNetworkListManager = new NetworkListManager();
ConnectToNetworkListManagerEvents();
}
public void Dispose()
{
//Not sure why this is not working form here
//Possibly because something is doing automatically before we get there
//DisconnectFromNetworkListManagerEvents();
}
public INetworkListManager NetworkListManager
{
get { return iNetworkListManager; }
}
public void ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
{
//Fire our event
OnConnectivityChanged(this, newConnectivity);
}
public void ConnectToNetworkListManagerEvents()
{
Debug.WriteLine("Subscribing to INetworkListManagerEvents");
IConnectionPointContainer icpc = (IConnectionPointContainer)iNetworkListManager;
//similar event subscription can be used for INetworkEvents and INetworkConnectionEvents
Guid tempGuid = typeof(INetworkListManagerEvents).GUID;
icpc.FindConnectionPoint(ref tempGuid, out iConnectionPoint);
iConnectionPoint.Advise(this, out iCookie);
}
public void DisconnectFromNetworkListManagerEvents()
{
Debug.WriteLine("Un-subscribing to INetworkListManagerEvents");
iConnectionPoint.Unadvise(iCookie);
}
}
}
You can instantiate your Network Manager like this:
iNetworkManager = new NetworkManager();
iNetworkManager.OnConnectivityChanged += OnConnectivityChanged;
Upon receiving connectivity change events you could test IsConnectedToInternet and IsConnected attribute as shown below:
public void OnConnectivityChanged(NetworkManager aNetwork, NLM_CONNECTIVITY newConnectivity)
{
//Update network status
UpdateNetworkStatus();
}
/// <summary>
/// Update our Network Status
/// </summary>
private void UpdateNetworkStatus()
{
//TODO: Test the following functions to get network and Internet status
//iNetworkManager.NetworkListManager.IsConnectedToInternet
//iNetworkManager.NetworkListManager.IsConnected
}
Here is a related question:
INetworkConnectionEvents Supports what?
I think the Microsoft dialog you show above is using information gained by coding against the Network Location Awareness API.
http://msdn.microsoft.com/en-us/library/ee264321%28v=VS.85%29.aspx

.Net Remoting to WCF Challenge!

I am trying to migrate my .net remoting code to wcf but I'm finding it difficult. Can someone help me migrate this simple Remoting based program below to use WCF? The program implements a simple publisher/subscriber pattern where we have a single TemperatureProviderProgram that publishers to many TemperatureSubcriberPrograms that subcribe to the TemperatureProvider.
To run the programs:
Copy the TemperatureProviderProgram and TemperatureSubcriberProgram into seperate console application projects.
Copying to remaining classes and interfaces into a common Class Library project then add a reference to System.Runtime.Remoting library
Add a reference to the Class Library project from the console app projects.
Complie and run 1 TemperatureProviderProgram and multiple TemperatureSubcriberProgram.
Please note no IIS or xml should be used. Thanks in advance.
public interface ITemperatureProvider
{
void Subcribe(ObjRef temperatureSubcriber);
}
[Serializable]
public sealed class TemperatureProvider : MarshalByRefObject, ITemperatureProvider
{
private readonly List<ITemperatureSubcriber> _temperatureSubcribers = new List<ITemperatureSubcriber>();
private readonly Random randomTemperature = new Random();
public void Subcribe(ObjRef temperatureSubcriber)
{
ITemperatureSubcriber tempSubcriber = (ITemperatureSubcriber)RemotingServices.Unmarshal(temperatureSubcriber);
lock (_temperatureSubcribers)
{
_temperatureSubcribers.Add(tempSubcriber);
}
}
public void Start()
{
Console.WriteLine("TemperatureProvider started...");
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
TcpServerChannel tcpChannel = new TcpServerChannel("TemperatureProviderChannel", 5001, provider);
ChannelServices.RegisterChannel(tcpChannel, false);
RemotingServices.Marshal(this, "TemperatureProvider", typeof(ITemperatureProvider));
while (true)
{
double nextTemp = randomTemperature.NextDouble();
lock (_temperatureSubcribers)
{
foreach (var item in _temperatureSubcribers)
{
try
{
item.OnTemperature(nextTemp);
}
catch (SocketException)
{}
catch(RemotingException)
{}
}
}
Thread.Sleep(200);
}
}
}
public interface ITemperatureSubcriber
{
void OnTemperature(double temperature);
}
[Serializable]
public sealed class TemperatureSubcriber : MarshalByRefObject, ITemperatureSubcriber
{
private ObjRef _clientRef;
private readonly Random portGen = new Random();
public void OnTemperature(double temperature)
{
Console.WriteLine(temperature);
}
public override object InitializeLifetimeService()
{
return null;
}
public void Start()
{
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
int port = portGen.Next(1, 65535);
TcpServerChannel tcpChannel = new TcpServerChannel(string.Format("TemperatureSubcriber_{0}", Guid.NewGuid()), port, provider);
ChannelServices.RegisterChannel(tcpChannel, false);
ITemperatureProvider p1 = (ITemperatureProvider)RemotingServices.Connect(typeof(ITemperatureProvider), "tcp://localhost:5001/TemperatureProvider");
_clientRef = RemotingServices.Marshal(this, string.Format("TemperatureSubcriber_{0}_{1}.rem", Environment.MachineName, Guid.NewGuid()));
p1.Subcribe(_clientRef);
}
}
public class TemperatureProviderProgram
{
static void Main(string[] args)
{
TemperatureProvider tp = new TemperatureProvider();
tp.Start();
}
}
public class TemperatureSubcriberProgram
{
static void Main(string[] args)
{
Console.WriteLine("Press any key to start TemperatureSubcriber.");
Console.ReadLine();
TemperatureSubcriber ts = new TemperatureSubcriber();
ts.Start();
Console.ReadLine();
}
}
In WCF, with a "push" from the server you're really talking about duplex comms; the MarshalByRefObject is largely redundant here (AFAIK). The page here discusses various scenarios, including duplex/callbacks.
If the issue is xml (for some philosophical reason), then simply using NetDataContractSerializer rather than DataContractSerializer might help.
The other approach is to have the clients "pull" data periodically; this works well if you need to support basic http, etc.
What it sounds like you want to do is use WCF NetTcpBinding with Callbacks.
Take a look at this: http://www.codeproject.com/KB/WCF/publisher_subscriber.aspx
"Learning WCF" by Michele Bustamante is also very good. You can get Chpt1 for VS2008 at her website along with the code for the book. Chpt1 will explain/demo setting up connections and such. She also has downloadable sample code. One of the Samples is a DuplexPublishSubscribe.
You will need to modify your logic a bit. If you want to migrate this app to WCF. You will need to have clients pull data from the service at regular intervals.
You will also need a Windows service or application to host the WCF like the console you are using in the previous code.
Well I build real time systems so polling is not an option - I need to push data.
Also I am finding there is no WCF equivalent of System.Runtime.Remoting.ObjRef! This is an extremely useful type that encapsulates a service endpoint and can be serialise and passed around the network to other remoting service.
Think I’ll be sticking with good old remoting until the ObjRef equivalent is introduced.
Yes it is true, just one correction..
ObjRefs are created automatically when any MarshalByRefObject derived object is going outside the appdomain.
So in this case your ITemperatureProvider interface Subscribe method shoud take ITemperatureSubscriber instead of objref.
And then on client side just call p1.Subscribe(this) and the remoting layer will generate ObjRef from the object that will be serialized and sent. (sending b reference)

Categories