I did solve it by making a wrapper class for the objects and use that for the transfer instead. A bit more work, but it works. Apparently you're not supposed to be able to send entity framework generated objects through these channels.
.net remoting when passing an entity framework generated object
-
29-06-2022 - |
Question
I have a problem with .net remoting (and yes, it is my first attempt at using it, so I'm sorry if this is a stupid problem with an easy solution) and I've been searching for two days now and can't find any solution to my problem, so i apologize in advance if I've somehow missed the answer somewhere.
I'm building a server/client system using this code:
Server:
public Server() {
DbConnector db = new DbConnector();
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Full;
IDictionary props = new Hashtable();
props["port"] = DbConnector.PORT;
TcpChannel channel = new TcpChannel(props, null, provider);
ChannelServices.RegisterChannel(channel, true);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(DbConnector), "test",
WellKnownObjectMode.SingleCall);
}
Client:
public Form1() {
InitializeComponent();
BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
provider.TypeFilterLevel = TypeFilterLevel.Full;
IDictionary props = new Hashtable();
props["port"] = 0;
props["ip"] = DbConnector.IP;
TcpChannel channel = new TcpChannel(props, null, provider);
ChannelServices.RegisterChannel(channel, true);
db = (DbConnector)Activator.GetObject(typeof(DbConnector), "tcp://188.x.x.x/test");
InitRest();
}
Whenever I try it locally (both with localhost but also with WAN IP) everything works fine, but as soon as I try it on separate machines, the client throws an exception.
{System.Net.Sockets.SocketException (0x80004005): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 192.168.0.100:9090
Server stack trace:
ved System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
ved System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
ved System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket(EndPoint ipEndPoint)
ved System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket()
ved System.Runtime.Remoting.Channels.RemoteConnection.GetSocket()
ved System.Runtime.Remoting.Channels.SocketCache.GetSocket(String machinePortAndSid, Boolean openNew)
ved System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.SendRequestWithRetry(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream)
ved System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, ITransportHeaders& responseHeaders, Stream& responseStream)
ved System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)
Exception rethrown at [0]:
ved ECTunes.Database_Reader.Form1.InitRest() i d:\Dropbox\visual studio 2012\Projects\ECTunes\Database Communicator v0.2\Database Reader\Form1.cs:linje 69
ved ECTunes.Database_Reader.Form1..ctor() i d:\Dropbox\visual studio 2012\Projects\ECTunes\Database Communicator v0.2\Database Reader\Form1.cs:linje 56
ved ECTunes.Database_Reader.Program.Main() i d:\Dropbox\visual studio 2012\Projects\ECTunes\Database Communicator v0.2\Database Reader\Program.cs:linje 16
ved System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
ved System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
ved Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
ved System.Threading.ThreadHelper.ThreadStart_Context(Object state)
ved System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
ved System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
ved System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
ved System.Threading.ThreadHelper.ThreadStart()}
I'm printing out come text whenever the constructor for the DbConnector is called and I can see that the client contacts the server, but I'm stuck at that.
After a bit more testing it seems that the problem is not with the connection itself but rather when I call a function that returns an object from the entity framework part of the system which is generated code. I've already modified the classes with [Serializable] and :MarshalByRefObject as shown:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Database
{
using System;
using System.Collections.Generic;
[Serializable]
public partial class customer: MarshalByRefObject
{
public customer()
{
this.car = new HashSet<car>();
}
public int customerId { get; set; }
public string name { get; set; }
public virtual ICollection<car> car { get; set; }
}
}
Yet when the client program calls a function that returns a 'customer' object and tries to access it the client throws the above exception.
My guess is that as the class is deriving from MarshalByRefObject it's the callback part that goes belly-up.
I've tried to use a specific port for the client channel as well, but to no avail.
I hope someone has a solution for this, in the end it's probably just me who's missing a key part.
Solution 2
OTHER TIPS
I think I found it, thanks to you providing your sample!
ChannelServices.RegisterChannel(channel, true);
Set the ensureSecurity to false
ChannelServices.RegisterChannel(channel, false);