NHibernate proxy serialization using NetDataContractSerializer in WCF service
-
Monday, July 02, 2007 7:58 AM
Hi
I am currently trying to get NHibernate working with WCF using the NetDataContractSerializer in a WCF service. I'm hosting in a windows service (console app for debugging) using the NetTcpBinding. I have a strange problem with NHibernate proxy serialization. NHibernate uses Castle's DynamicProxy for lazy loading behaviour. I have had success with a proxy for a single association, the proxy gets serialized over the serivice fine and is created on the client, if you try to access it then failure occurs (no access to the database / nhibernate session) which is expected and what i want. However another case has an OrganisationUnit -> DefaultCostCentre -> Approvers Collection. I load the OrganisationUnit's (tree) and leave the DefaultCostCentre association (to CostCentre object) as a proxy (don't load data from db). I get the error in the code snippit below on the client while trying to deserialize the data.
I have serialized the same to a memory stream using the NetDataContractSerializer and it works fine. So there is something else in play when using the WCF service. Also a strange thing is that if I add another method to the WCF service that returns a CostCentre object (the type proxy is for on the organisation unit) it works again! Finally If I don't serialize the Approvers collection (IList<User>) of the CostCentre it's fine.
I know this may require some knowledge of NHibernate and DynamicProxy but is there anything obvious some one can see as to the described behaviour from a WCF perspective?
Cheers
Duncan
Code SnippetSystem.ArgumentException was unhandled
Message="Object of type 'System.Boolean' cannot be converted to type 'System.Collections.Generic.IList`1[Finance.Core.User]'."
Source="mscorlib"
StackTrace:
Server stack trace:
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.RtFieldInfo.InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, Boolean doVisibilityCheck, Boolean doCheckConsistency)
at System.Runtime.Serialization.FormatterServices.SerializationSetValue(MemberInfo fi, Object target, Object value)
at System.Runtime.Serialization.FormatterServices.PopulateObjectMembers(Object obj, MemberInfo[] members, Object[] data)
at Castle.DynamicProxy.Serialization.ProxyObjectReference.RecreateClassProxy(SerializationInfo info, StreamingContext context)
at Castle.DynamicProxy.Serialization.ProxyObjectReference.RecreateProxy(SerializationInfo info, StreamingContext context)
at Castle.DynamicProxy.Serialization.ProxyObjectReference..ctor(SerializationInfo info, StreamingContext context)
at ReadProxyObjectReferenceFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.XmlFormatClassReaderDelegate.Invoke(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadOrganisationUnitFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.XmlFormatClassReaderDelegate.Invoke(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadArrayOfOrganisationUnitFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
at System.Runtime.Serialization.XmlFormatCollectionReaderDelegate.Invoke(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString itemName, XmlDictionaryString itemNamespace, CollectionDataContract collectionContract)
at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadArrayOfOrganisationUnitFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.XmlFormatClassReaderDelegate.Invoke(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadCollectionEntryFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.XmlFormatClassReaderDelegate.Invoke(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadPersistentGenericBagOfOrganisationUnit7xzRVzM_SFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.XmlFormatClassReaderDelegate.Invoke(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadOrganisationUnitFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.XmlFormatClassReaderDelegate.Invoke(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces)
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserializeInSharedTypeMode(XmlReaderDelegator xmlReader, Int32 declaredTypeID, Type declaredType, String name, String ns)
at System.Runtime.Serialization.XmlObjectSerializerReadContextComplex.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, String name, String ns)
at System.Runtime.Serialization.NetDataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName)
at System.Runtime.Serialization.NetDataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameter(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameters(XmlDictionaryReader reader, PartInfo[] parts, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeReply(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at Finance.Core.AppServices.IOrganisationManagementService.GetOrganisationTree(OrganisationUnit& department)
at Finance.Core.OrganisationManagement.OrganisationManagementForm.OrganisationManagementForm_Load(Object sender, EventArgs e) in C:\Working\WorkflowV2\Core\src\Finance.Core.Client\OrganisationManagement\OrganisationManagementForm.cs:line 15
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.SafeNativeMethods.ShowWindow(HandleRef hWnd, Int32 nCmdShow)
at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
at System.Windows.Forms.Control.set_Visible(Boolean value)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
at System.Windows.Forms.Form.ShowDialog()
at Finance.Core.OrganisationManagement.OrganisationManagementController.Run() in C:\Working\WorkflowV2\Core\src\Finance.Core.Client\OrganisationManagement\OrganisationManagementController.cs:line 25
at Finance.Core.CoreController.Command_LaunchOrganisationManagement(Object sender, EventArgs e) in C:\Working\WorkflowV2\Core\src\Finance.Core.Client\CoreController.cs:line 44
at Microsoft.Practices.CompositeUI.Commands.Command.OnExecuteAction(Object sender, EventArgs e)
at Microsoft.Practices.CompositeUI.Commands.CommandAdapter.FireCommand()
at Microsoft.Practices.CompositeUI.Commands.EventCommandAdapter`1.InvokerEventHandler(Object sender, EventArgs e)
at System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
at System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
at System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
at System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.ToolStripDropDown.OnMouseUp(MouseEventArgs mea)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ToolStrip.WndProc(Message& m)
at System.Windows.Forms.ToolStripDropDown.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Microsoft.Practices.CompositeUI.WinForms.FormShellApplication`2.Start()
at Microsoft.Practices.CompositeUI.CabApplication`1.Run()
at Finance.FSC.ShellApplication.RunInDebugMode() in C:\Working\WorkflowV2\Core\src\Finance.FSC\ShellApplication.cs:line 57
at Finance.FSC.ShellApplication.Main() in C:\Working\WorkflowV2\Core\src\Finance.FSC\ShellApplication.cs:line 31
All Replies
-
Monday, July 02, 2007 9:01 PMCan't see anything obvious, is it possible that you can share some code that will reproduce this problem? that will make it easier to find out what is the issue.
-
Tuesday, July 03, 2007 6:05 AM
Hi,
Thanks for your time on this. I have made a little solution the reproduces the error. There is a Readme.txt that shows how to set it up.
You can download from:
http://files-upload.com/342627/WCFSerializationTest.zip.html
Cheers
Duncan
-
Wednesday, July 04, 2007 12:53 PM
Hi
If anyone could take a look at this I would really appreciate it. I just can't explain why serialization fails over the service but not when directly using the NetDataContractSerializer to a memory stream?? Also, can anyone point me in the direction of information on differences / upgrade path from .Net Remoting to WCF with NetDataContractSerializer.
Cheers
Duncan
-
Sunday, July 08, 2007 8:28 AMCan someone PLEASE take a look at the sample I posted. Either I have not hooked up the wcf service correctly, or the NetDataContractSerializer approach does not work with complex object graphs... I'm hoping it's the former as otherwise i'm going to have to consider developing my new solution with .NET Remoting... Seriously, this is extremely frustrating!!
-
Monday, July 09, 2007 3:26 AM
Hi
Ok, I have the same problem with with .NET Remoting, so it is not WCF and NetDataContractSerializer at the heart of the problem. BinaryFormatter can serialize fine in a test but same error moving the data accross a .NET Remoting service. I'll keep looking, but maybe not worth anyones time on this forum.
Cheers
Duncan -
Wednesday, July 11, 2007 1:11 AM
Hi
Just to conclude on this. It's not a problem with WCF or .Net Remoting, instead the problem is in the custom serialization / deserialization with DynamicProxy. It gets the order of members it is serializing / deserializing mixed up for some reason. I was able to get around the problem by implementing ISerializable on my proxied classes so this responsibililty is delegated to my class to handle and all is good now.
Cheers
Duncan
-
Monday, July 30, 2007 12:20 PM
Duncan,
Thank you so much for posting your problem and following it up with the actual solution too
I've been scratching my head with the same issue thinking it must be down to the Castle Dynamic proxies, but not realising the cause. I thought there might be very little I could do about it so you've saved me a lot of time.
Cheers,
Ben.
-
Wednesday, August 08, 2007 6:16 AM
No worries Ben,
I'm glad to see i'm not the only one to have encountered this problem and I'm happy I was able to save you some time as this had me scratching my head for some time too.
Cheers
Duncan
-
Friday, August 08, 2008 1:53 PM
any one have the NetDataContractSerilizer works in Vb - as I found code in c# and i am transfering it to VB but I am not sure how to convert this line
public
class NetDataContractAttribute : Attribute, IOperationBehaviorto VB
any help is appriciated
-
Friday, August 08, 2008 2:42 PM
found this line so instead of the : you put the word implement
but how do you transfer this line to VB
DataContractSerializerOperationBehavior
dcsOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>(); -
Wednesday, September 03, 2008 11:14 AM
got the program now working thanks to Steve Seymour at
http://thoughtshapes.com/WCF/ExampleTwo.htm#comment-649
check my coments there in his blog to find what I was doing wrong
just use .Net Reflector to transfer the code to VB it will do it automaticlly
by clicking on tools menue then Disambale
finally we have some examples on how to use .NetContractSeriliaser in VB

