![]() | |
![]() |
| | Thread Tools | Search this Thread | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
Hi guys, I'm having a problem with remote events in .NET 2.0. I've written a really simple test application (taken from the Microsoft book "Microsoft .NET Distributed Applications: Integrating XML Web Services and .NET Remoting"). The aim is for the client to receive an event raised by an object on the server as a result of an asynchronous call from the client. The server (a console application) comprises a config file: ============================================= ?xml version="1.0" encoding="utf-8" ? configuration system.runtime.remoting application name="Server" service activated type="DLL.RemoteObject, DLL"/ /service channels channel ref="tcp server" port="8080" / /channels /application /system.runtime.remoting /configuration ============================================= ...and Program.cs with a Main method: ============================================= public static void Main(string[] args) { Console.WriteLine("Attempting to start server..."); try { //Start listening to the remoting channel: RemotingConfiguration.Configure("Server.exe.config ", false); Console.WriteLine("Server is now listening"); } catch(Exception e) { Console.WriteLine("Error: {0}", e.Message); } Console.WriteLine("Press Return to quit..."); Console.ReadLine(); } ============================================= A separate DLL contains a remote object (RemoteObject.cs): ============================================= public class RemoteObject : MarshalByRefObject { public event EventHandler<TaskCompleteEventArgs> TaskComplete; public void GetActiveDomainAsychronous() { new Thread ( delegate() { Console.WriteLine("Getting active domain..."); Thread.Sleep(3000); string activeDomain = AppDomain.CurrentDomain.FriendlyName; Console.WriteLine("Active domain obtained"); OnTaskComplete(new TaskCompleteEventArgs(activeDomain)); } ).Start(); } protected void OnTaskComplete(TaskCompleteEventArgs e) { if (TaskComplete != null) { foreach (Delegate d in TaskComplete.GetInvocationList()) { try { ((EventHandler<TaskCompleteEventArgs>)d)(this, e); } catch { //Ignore } } } } } ============================================= ...an event args class: ============================================= [Serializable] public class TaskCompleteEventArgs : EventArgs { private readonly string activeDomain; public TaskCompleteEventArgs(string activeDomain) { this.activeDomain = activeDomain; } public string ActiveDomain { get { return activeDomain; } } } ============================================= ...and a listener class: ============================================= [Serializable] public class EventListener : MarshalByRefObject { public void TaskComplete(object sender, TaskCompleteEventArgs e) { Console.WriteLine("Asynchronous response received. Domain: {0}", e.ActiveDomain); } public override object InitializeLifetimeService() { return null; } } ============================================= The client (another console application) also comprises a config file: ============================================= ?xml version="1.0" encoding="utf-8" ? configuration system.runtime.remoting application name="Client" client url="tcp://localhost:8080/Server" activated type="DLL.RemoteObject, DLL"/ /client channels channel ref="tcp client" / /channels /application /system.runtime.remoting /configuration ============================================= ...and a Program.cs: ============================================= public class Program { private static EventListener listener = new EventListener(); public static void Main(string[] args) { string currentDomain = AppDomain.CurrentDomain.FriendlyName; Console.WriteLine("Client application domain: {0}", currentDomain); Console.WriteLine("Attempting to start client..."); try { //Start listening to the remoting channel: RemotingConfiguration.Configure("Client.exe.config ", false); Console.WriteLine("Client is now running"); Console.WriteLine("Construct a remote object..."); RemoteObject remoteObject = new RemoteObject(); remoteObject.TaskComplete += listener.TaskComplete; Console.WriteLine("Perform asynchronous request..."); remoteObject.GetActiveDomainAsychronous(); } catch (Exception e) { Console.WriteLine("Error: {0}", e.Message); } Console.WriteLine("Press Return to quit..."); Console.ReadLine(); } } } ============================================= The server starts with no problems, but when the client starts, I get a problem when it hits the line 'remoteObject.TaskComplete += listener.TaskComplete;'. The error is: "Type System.DelegateSerializationHolder and the types derived from it (such as System.DelegateSerializationHolder) are not permitted to be deserialized at this security level." I'm having problems getting to the bottom of the problem. Any ideas? Thanks in advance guys, Steve. |
#3
| |||
| |||
|
#4
| |||
| |||
|
|
Hi Jacky! Thanks very much for your help. I've managed to make some progress. I've changed the config files as follows: Server config file: ============================= ?xml version="1.0" encoding="utf-8" ? configuration system.runtime.remoting application name="Server" service activated type="DLL.RemoteObject, DLL"/ /service channels channel ref="tcp server" port="8080" serverProviders provider ref="wsdl" / formatter ref="soap" typeFilterLevel="Full" / formatter ref="binary" typeFilterLevel="Full" / /serverProviders /channel /channels /application /system.runtime.remoting /configuration ============================= Client config file: ============================= ?xml version="1.0" encoding="utf-8" ? configuration system.runtime.remoting application name="Client" client url="tcp://localhost:8080/Server" activated type="DLL.RemoteObject, DLL"/ /client channels channel ref="tcp client" port="0" serverProviders formatter ref="soap" typeFilterLevel="Full" / formatter ref="binary" typeFilterLevel="Full" / /serverProviders /channel /channels /application /system.runtime.remoting /configuration ============================= This gets me a bit further. Now, when the server hits the line of code '((EventHandler<TaskCompleteEventArgs>)d)(this, e);' in the OnTaskComplete method of the RemoteObject class, I get the following error: "This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server." I guess I'm still missing something from the configuration files?! Many thanks, Steve. |
#5
| |||
| |||
|
#6
| |||
| |||
|
|
Hi Jacky, I tried changing the client port to 8000, but got the same error. 0 should be fine, since it just tells the client to communicate via any available port, which it will decide upon automatically. Does anyone know what the correct contents of each configuration file should be? Many thanks, Steve. |
| serverProviders |
#7
| |||
| |||
|
#8
| |||
| |||
|
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
| |