I hope this isn't a basic question. (Something very similar came up last
year on the list, but didn't get answered. I've also found a couple of
references on the newsgroup microsoft.public.dotnet.framework.remoting, but
again there was no answer beyond "I guess it just doesn't work".)
Using a client compiled against a SoapSuds generated proxy, I'm unable to
invoke any server-side method that returns an instance of another
server-side class. So, if I write on the client:
FactoryClass factory = (FactoryClass) Activator.GetObject (...)
String s = factory.getName();
UtilityClass utility = factory.getUtility();
then factory.getName() returns successfully, but factory.getUtility() gives
an InvalidCastException. (Details below.)
The only way I can get this to work is to compile the client against the
server's library. If I compile against the proxy generated by SoapSuds, it
doesn't work.
Does anyone know why this is happening? Is it a bug in SoapSuds, or
something trivial that I've overlooked? Apologies if it's the latter, but I
really can't find any refrences that would explain how to solve this
issue. I'm working through Rammer's "Advanced .NET Remoting" and it doesn't
seem to have anything to say on the subject.
Thanks,
Alasdair
=================================================================
Source Code
=================================================================
-----------------------------------------------------------------
Client.cs
-----------------------------------------------------------------
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using Server;
public class TheClient
{
public static void Main (string[] args)
{
ChannelServices.RegisterChannel (new HttpChannel());
FactoryClass factory = (FactoryClass) Activator.GetObject
(typeof (FactoryClass),"http://localhost:1095/FactoryClass");
String s = factory.getName();
Console.WriteLine("Got name " + s);
UtilityClass utility = factory.getUtility();
}
}
-----------------------------------------------------------------
Server.cs
-----------------------------------------------------------------
using System;
using System.IO;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
namespace Server
{
public class UtilityClass : MarshalByRefObject {
}
public class FactoryClass : MarshalByRefObject {
public UtilityClass getUtility() {
return new UtilityClass();
}
public String getName() {
return "I'm a useful factory";
}
}
public class ServerClass
{
public static void Main ()
{
ChannelServices.RegisterChannel (new HttpChannel(1095));
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(FactoryClass),"FactoryClass",WellKnownObjectMode.Singleton);
Console.WriteLine ("Press enter to stop the server...");
Console.ReadLine ();
}
}
}
-----------------------------------------------------------------
command line options
-----------------------------------------------------------------
This works:
csc AJMClient.cs /r:AJMServer.exe
This doesn't
soapsuds -nowp -ia:AJMServer -oa:soapsuds.dll
csc AJMClient.cs /r:soapsuds.dll
Nor does this:
soapsuds -nowp -ia:AJMServer -gc
csc AJMClient.cs soapsuds.cs
(Note: options "/r:system.runtime.remoting.dll /r:system.dll" omitted for clarity)
-----------------------------------------------------------------
Stack Trace
-----------------------------------------------------------------
Unhandled Exception: System.InvalidCastException: Return argument has an invalid type.
at System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type
paramType)
at System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg,
Object[] outArgs, Object returnValue)
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,
IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData,
Int32 type)
at Server.FactoryClass.getUtility()
at TheClient.Main(String[] args) in D:\play\dotnet_remoting\ajm\AJMClient.cs:line 14