DotNetNewsgroup.com  
web access to complete list of Microsoft.NET newsgroups
   home   |   control panel login   |   archive  |  
 
  carried group
academic
adonet
aspnet
aspnet.announcements
aspnet.buildingcontrols
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
assignment_manager
datatools
dotnet.distributed_apps
dotnet.general
dotnet.myservices
dotnet.nternationalization
dotnet.scripting
dotnet.security
dotnet.vjsharp
dotnet.vsa
dotnet.xml
dotnetfaqs
framework
framework.clr
framework.compactframework
framework.component_services
framework.controls
framework.databinding
framework.drawing
framework.enhancements
framework.interop
framework.odbcnet
framework.performance
framework.remoting
framework.sdk
framework.setup
framework.webservices
framework.windowsforms
framework.wmi
frwk.windowsforms.designtime
lang.csharp
lang.jscript
lang.vb
lang.vb.controls
lang.vb.data
lang.vb.upgrade
lang.vc
lang.vc.libraries
  
 
start date: Wed, 22 Aug 2007 16:48:34 -0000,    posted on: microsoft.public.dotnet.framework.remoting        back       

Thread Index
  1    Gord Tanner


Problem with HTTP BinaryFormatter and KeyedCollection<K,V>   
Hello,

I have noticed a really weird problem regarding remoting and the
KeyedCollection class.

I am noticing that the keyed collection is returned to the client but
isn't fully initialized.
For example the .Items readonly property is null any any method that
attempts to use it
fails (example .Count)

It comes down to where if the version of the assembly the collection
is defined in isn't the same on
both ends, instead of throwing a serialization error, you get a
collection that is half initialized
and will throw null excpetions if you attempt to use it.

Testcase:

- ReBuild RemotingServer
- Copy output directory to another location and run it from there
- ReBuild RemotingClient (will rebuild RemotingLib with another
version)
- Run RemotingClient and notice that:
	string[] names = new string[Count];
	throws a null exception on accessing Count. This is unexpected as I
am expecting
	ether a fully constructed object or a serialization exception.

If you set the version of RemotingLib to 1.0.0.0 and do the above
steps it will work fine. Also
if you derive PersonCollection from
System.Collections.ObjectModel.KeyedCollection<K,V> it will
also work fine. It is only once you have it inherit from our own
KeyedCollection.

Thanks,

Gord

Example code:

RemotingLib (Class Library)
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

using System;
using System.Collections.Generic;
using System.Text;

namespace RemotingLib
{
	[Serializable]
	public abstract class KeyedCollection<TKey, TItem> :
System.Collections.ObjectModel.KeyedCollection<TKey, TItem>
	{
	}

	[Serializable]
	public class Person
	{
		private string m_id;
		private string m_name;

		public string ID
		{
			get { return m_id; }
			set { m_id = value; }
		}

		public string Name
		{
			get { return m_name; }
			set { m_name = value; }
		}

		public Person(string id, string name)
		{
			ID = id;
			Name = name;
		}

	}

	[Serializable]
	public class PersonCollection : RemotingLib.KeyedCollection<string,
Person>
	{
		protected override string GetKeyForItem(Person item)
		{
			return item.ID;
		}

		public string[] GetAllNames()
		{
			string[] names = new string[Count];

			for (int x = 0; x < Items.Count; x++)
			{
				names[x] = Items[x].Name;
			}

			return names;
		}
	}

	public class Service : MarshalByRefObject
	{
		public PersonCollection GetPeople()
		{
			PersonCollection people = new PersonCollection();

			people.Add(new Person("1","Alice"));
			people.Add(new Person("2", "Bob"));

			return people;
		}
	}
}

RemotingClient (Console App)
Project reference to RemotingLib
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

namespace RemotingClient
{
	class Program
	{
		static void Main(string[] args)
		{
			HttpClientChannel channel = new HttpClientChannel("httpbin", new
BinaryClientFormatterSinkProvider());

			ChannelServices.RegisterChannel(channel, false);

			RemotingLib.Service serv =
(RemotingLib.Service)Activator.GetObject(
				typeof(RemotingLib.Service),
				"http://localhost:8080/Service.rem");

			if (serv == null)
			{
				Console.WriteLine("Error, unable to locate Server");
			}
			else
			{
				RemotingLib.PersonCollection people = serv.GetPeople();

				Console.WriteLine(people.GetAllNames().Length);
			}

			Console.ReadLine();
		}
	}
}

RemotingServer (Console App)
Project reference to RemotingLib
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

namespace RemotingTest
{
	class Program
	{
		static void Main(string[] args)
		{
			Hashtable settings = new Hashtable();

			settings.Add("name", "httpbin");
			settings.Add("port", "8080");

			HttpChannel channel = new HttpChannel(settings, new
BinaryClientFormatterSinkProvider(), new
BinaryServerFormatterSinkProvider());

			ChannelServices.RegisterChannel(channel,false);

			RemotingConfiguration.RegisterWellKnownServiceType(
				typeof(RemotingLib.Service),
				"Service.rem",
				WellKnownObjectMode.SingleCall);

			System.Console.WriteLine("Press enter to stop server");
			System.Console.ReadLine();
		}
	}
}
Date:Wed, 22 Aug 2007 16:48:34 -0000   Author:  

Google
 
Web dotnetnewsgroup.com


COPYRIGHT ?2005, EUROFRONT WORLDWIDE LTD., ALL RIGHT RESERVE  |   Contact us