Bug 3050 - Objects with Generic Dictionary throw "Object must implement IConvertible." when remoting cross platform
Summary: Objects with Generic Dictionary throw "Object must implement IConvertible." w...
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: System (show other bugs)
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-01-24 16:59 UTC by chris.derrick
Modified: 2016-10-21 10:20 UTC (History)
7 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments

Description chris.derrick 2012-01-24 16:59:43 UTC
On Mono 2.6.7 my code works great, I tried running it on 2.10.5 and it looks like I can no longer send an Object containing a Generic Dictionary through remoting from a Linux machine to Windows.  Now it throws an "Object must implement IConvertible." exception.  It however still works correctly when the client and server are on Linux, or when both are on a Windows machine.

I wrote a simple program to illustrate the issue.  The program shows that sending a generic dictionary through remoting works fine if it is not encapsulated within another object, but when it tries to send an object with a generic dictionary inside "Object must implement IConvertible." is thrown when a Windows client tries to get a GenericDictionaryWrapper object from a Linux machine.


--Server Code (running on Linux)--

using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

class Program
{
	static void Main(string[] args)
	{
		Server();
	}
	
	static void Server()
	{
		Console.WriteLine("Server Started");
		
		TcpChannel tcpChannel = new TcpChannel(9998);
		ChannelServices.RegisterChannel(tcpChannel, false);
		
		Type commonInterfaceType = Type.GetType("RemoteClass");
		
		RemotingConfiguration.RegisterWellKnownServiceType(commonInterfaceType,
		"RemotingTest", WellKnownObjectMode.SingleCall);
		
		System.Console.WriteLine("Press ENTER to stop the server");
		System.Console.ReadLine();
	}
}

[Serializable]
public class GenericDictionaryWrapper
{
	public GenericDictionaryWrapper() { }

    private Dictionary<string, object> m_properties = new Dictionary<string, object>();
}

//private Dictionary<string, object> m_properties = new Dictionary<string, object>();
public interface RemotingInterface
{
	string ModifyString(string message);
	Dictionary<string, object> ModifyGenericDictionary(Dictionary<string, object> genericDictionary);
	GenericDictionaryWrapper GetGenericDictionaryWrapper();
}

public class RemoteClass : MarshalByRefObject, RemotingInterface
{
	public string ModifyString(string message)
	{		
		return message.ToUpper();
	}
	
	public Dictionary<string, object> ModifyGenericDictionary(Dictionary<string, object> genericDictionary)
	{
		genericDictionary.Add("addition", "new message");// WORKS
		//genericDictionary.Add("addition", new GenericDictionaryWrapper());// FAILS
		return genericDictionary;
	}
	
	public GenericDictionaryWrapper GetGenericDictionaryWrapper()
	{
		return new GenericDictionaryWrapper();
	}
}


--Client Code (Running on Windows)--

using System;
using System.Collections.Generic;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

class MyClient
{
	public static void Main()
	{
		TcpChannel tcpChannel = new TcpChannel();
		ChannelServices.RegisterChannel(tcpChannel, false);
		
		Type remoteType = typeof(RemotingInterface);
		
		RemotingInterface remoteObject = (RemotingInterface)Activator.GetObject(remoteType,
		"tcp://localhost:9998/RemotingTest");
		
		string message = "The original message";
		Console.WriteLine("The Message: "+message);
		Console.WriteLine("Has Become: "+ remoteObject.ModifyString(message));
		
		Dictionary<string, object> genericDictionary = new Dictionary<string, object>();
		genericDictionary.Add("NewMessage", message);
		genericDictionary = remoteObject.ModifyGenericDictionary(genericDictionary);
		Console.WriteLine("Successfully Modified Generic Dictionary:");
		foreach(object obj in genericDictionary.Values)
		{
			Console.WriteLine("\t"+obj.ToString());
		}
		
		Console.WriteLine("Getting A GenericDictionaryWrapper");
		//This next line is where the error is thrown
		GenericDictionaryWrapper dictionary = remoteObject.GetGenericDictionaryWrapper();
		Console.WriteLine("Successfully Got A GenericDictionaryWrapper");
		
		Console.WriteLine("All Tests Completed Successfully");
	}
}


Note: The Client code depends on the Server code (so it knows about the remotely accessible methods and the GenericDictionaryWrapper object).  So you need to reference the server's executable, I just built both executables on both machines to simplify this.
Comment 1 chris.derrick 2012-01-24 17:34:41 UTC
Others have experienced this issue as well, but as far as I could tell they never actually logged the bug:

http://www.smuxi.org/issues/show/589
Comment 2 Zoltan Varga 2012-01-25 01:13:05 UTC
-> class libs.
Comment 3 Bartek 2012-08-26 06:53:05 UTC
The problem still exists in Mono 2.10.8.1 running on Ubuntu 
(Mono JIT compiler version 2.10.8.1 Debian 2.10.8.1-1ubuntu2.2)

I've tested this sample code: 
* Running both server and client on Windows: OK
* Running both server and client on Linux Ubuntu (): OK
* Running server on Ubuntu and client on Windows -> Object must implement IConvertible exception

Note: In the sample code I've uncommented section marked as 'FAILS'
Comment 4 dennis 2013-01-10 16:17:30 UTC
I can confirm this issue, too.

Server: (Linux)
$ mono --version
Mono JIT compiler version 3.0.2 (tarball Fri Dec  7 21:53:57 UTC 2012)
Copyright (C) 2002-2012 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  x86
	Disabled:      none
	Misc:          softdebug 
	LLVM:          supported, not enabled.
	GC:            Included Boehm (with typed GC and Parallel Mark)


Client: (Windows)
.Net Runtime v4.0.30319
same with .Net Runtime v2.0.50727

Note You need to log in before you can comment on or make changes to this bug.