alex
9/18/2004 11:55:00 PM
I get the error when using the methods you provided below. However, I have
narrowed the issue down. The error seems to appear during deserialization
only after I have recompiled the asp app but not restarted the server. The
purpose of our remoting setup is to create a centralized caching server for
our business objects. The client sends an object to the server and the
server holds the object in memory until one of the servers in the web farm
request it again.
Everything works fine if I clear out the cache on the server and then
recompile the asp end. It also works fine if I stop and restart the server
end since the objects just get cleanly populated. However, if I recompile
the asp application, and the client attempts to deserialize an object that
already exists in the server, then the error occurs again.
So I am guessing there is either a security context that gets applied to the
serialized object that can't be deserialized by a new instance of the asp
application, or that the remoting proxy gets rebuilt when recompiled and that
the rebuilt proxy does not have the same signature as the proxy that
generated the object. Does that make sense, and where might I look to
pinpoint the problem?
Thanks,
Alex
"Robert Jordan" wrote:
> Alex wrote:
>
> > OK, I still don't think I've solved this. Since I am marking the class as
> > Serializable, this marshals by value which would mean they don't need to have
> > a remote identity. If I derive from MarshalByRef, wouldn't I then have to
> > insure the class does have a remote identity on the server? I don't want to
> > do this since the server does not need to know the type of object I am
> > passing and will, in fact, be passed a number of different object types which
> > are just going to get stored in cache and then returned to the client when
> > requested.
>
> If you want to cache objects of types the server doesn't
> know about, than you have to serialize the objects
> on the client and send them as binary data to the server.
>
> you can even send the objects as a string using that
> method:
>
>
> /// <summary>
> /// Converts a serializable object to a base64 coded string
> /// representation of the serialized data.
> /// </summary>
> /// <param name="data"></param>
> /// <exception cref="SerializationException">The data is not
> serializable.
> /// </exception>
> /// <returns></returns>
> public static string SerializeToBase64(object data)
> {
> MemoryStream stream = new MemoryStream();
> BinaryFormatter formatter = new BinaryFormatter();
> formatter.Serialize(stream, data);
> stream.Position = 0;
> return Convert.ToBase64String(stream.ToArray());
> }
>
>
> /// <summary>
> /// Deserializes a string previously written by SerializeToString.
> /// </summary>
> /// <param name="data">The Base64 string.</param>
> /// <exception cref="FormatException">The specified string is
> not Base64-coded.</exception>
> /// <exception cref="SerializationException">The data cannot be
> deserialized.</exception>
> /// <returns></returns>
> public static object DeserializeFromBase64(string data,
> SerializationBinder binder)
> {
> MemoryStream stream = new
> MemoryStream(Convert.FromBase64String(data));
> stream.Position = 0;
> BinaryFormatter formatter = new BinaryFormatter();
> return formatter.Deserialize(stream);
> }
>
>
> bye
> rob
>
>
>
> >
> > I have a feeling I am misunderstanding something pretty fundamental with
> > remoting, but not sure what it is. Thanks for bearing with me.
> >
> > Alex
> >
> > "Ken Kolda" wrote:
> >
> >
> >>My guess is that you have defined the RemoteTest class twice -- once in your
> >>server assembly and once in the client assembly. Since the assembly name is
> >>part of the full name of a class (which is passed as part of the
> >>serialization info), these type definitions will not be recognized as the
> >>same, even if the namespaces and the class names are exactly the same in the
> >>client and server assemblies. To solve this, put this class definition in a
> >>separate assembly which will be shared by both client and server.
> >>
> >>That said, it looks like you must already be doing this to some degree since
> >>your able to use the IApptikRemoteCache interface (which I assume is in a
> >>separate assembly). So, if what I described above isn't the problem, let me
> >>know.
> >>
> >>Ken
> >>
> >>
> >>"Alex" <Alex@discussions.microsoft.com> wrote in message
> >>news:C7DC2C7D-30D4-457B-95E4-418037C0FE7F@microsoft.com...
> >>
> >>>I have created a simple remoting client-server setup where I am having
> >>>problems when attempting to deal with business objects. If I run the
> >>
> >>client
> >>
> >>>and server, and pass in a standard object such as a string, integer, guid,
> >>>etc., everything works fine. However, if I try to pass in a business
> >>
> >>object
> >>
> >>>that I have marked as serializable, I get the following error:
> >>>
> >>>Unable to find assembly '__codeyqhbdlhs, Version=0.0.0.0, Culture=neutral,
> >>>PublicKeyToken=null'.
> >>>
> >>>I have marked the business object as serializable and to test, I created a
> >>>simple business object that just has a couple of string fields. The error
> >>>also appears to occur when I try to run deserialize or serialize directly
> >>
> >>on
> >>
> >>>an object instead of allowing the framework to handle the serialization so
> >>>the problem seems to be serialization. The same error occurs whether I
> >>
> >>use
> >>
> >>>Binary or SOAP formatters. I am running my server as a windows app. The
> >>>relevant code to activate remoting on the server is as follows:
> >>>
> >>> private void button1_Click(object sender, EventArgs e)
> >>> {
> >>> BinaryServerFormatterSinkProvider ServerProvider = new
> >>>BinaryServerFormatterSinkProvider();
> >>> TcpServerChannel tsc = new TcpServerChannel("TCPChannel",
> >>
> >>7777,
> >>
> >>>ServerProvider);
> >>> ChannelServices.RegisterChannel(tsc);
> >>>
> >>>
> >>
> >>RemotingConfiguration.RegisterWellKnownServiceType(typeof(ApptikRemoteObject
> >>), "ApptikCache", WellKnownObjectMode.SingleCall);
> >>
> >>> infobox.Items.Add("Initializing cache server initialized");
> >>>
> >>>
> >>> stopped = false;
> >>>
> >>> }
> >>>
> >>> }
> >>>
> >>>
> >>>The relevant client portion is run from an asp page and is as follows:
> >>>
> >>>Global.asax
> >>> System.Runtime.Remoting.Channels.BinaryClientFormatterSinkProvider
> >>>ClientProvider = new
> >>>System.Runtime.Remoting.Channels.BinaryClientFormatterSinkProvider();
> >>> System.Runtime.Remoting.Channels.Tcp.TcpClientChannel tsc = new
> >>>System.Runtime.Remoting.Channels.Tcp.TcpClientChannel("TCPChannel",
> >>>ClientProvider);
> >>>
> >>
> >>System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(tsc);
> >>
> >>>appobject.aspx
> >>>
> >>> IApptikRemoteCache remoteobj =
> >>>(IApptikRemoteCache)Activator.GetObject(typeof(IApptikRemoteCache),
> >>>"tcp://localhost:7777/ApptikCache");
> >>>
> >>> RemoteTest findtestvalue = (RemoteTest)
> >>>remoteobj.Find("RemoteTestTest11");
> >>> if (findtestvalue == null)
> >>> {
> >>>
> >>> HttpContext.Current.Trace.Write("Test not found");
> >>> // if I pass a string in the next line instead of remotetest
> >>
> >>object
> >>
> >>> // then everything works fine
> >>> RemoteTest test = new RemoteTest();
> >>> remoteobj.Add("RemoteTestTest11", test, null);
> >>> }
> >>> else
> >>> {
> >>>
> >>> HttpContext.Current.Trace.Write("Test " +
> >>>findtestvalue.Test2.ToString());
> >>>
> >>> }
> >>>
> >>>The remote class that I am attempting to pass through is as follows:
> >>>
> >>>[Serializable]
> >>>public class RemoteTest {
> >>>
> >>> private string test = string.Empty;
> >>> private string test2 = string.Empty;
> >>> public string Test2
> >>> {
> >>> get
> >>> {
> >>> return test2;
> >>> }
> >>>
> >>> set
> >>> {
> >>> test2 = value;
> >>> }
> >>> }
> >>>
> >>>
> >>> public RemoteTest()
> >>> {
> >>>
> >>> test2 = "Palookaville";
> >>>
> >>> }
> >>>
> >>>}
> >>>
> >>>
> >>>
> >>
> >>
> >>
>