none
NHibernate proxy serialization using NetDataContractSerializer in WCF service

    Question

  • 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 Snippet
    System.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

     


    Monday, July 02, 2007 7:58 AM

Answers

  • 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

    Wednesday, July 11, 2007 1:11 AM

All replies

  • Can'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.
    Monday, July 02, 2007 9:01 PM
  • 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

    Tuesday, July 03, 2007 6:05 AM
  • 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

    Wednesday, July 04, 2007 12:53 PM
  • Can 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!!
    Sunday, July 08, 2007 8:28 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

    Monday, July 09, 2007 3:26 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

    Wednesday, July 11, 2007 1:11 AM
  • 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.

    Monday, July 30, 2007 12:20 PM
  • 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

    Wednesday, August 08, 2007 6:16 AM
  • 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, IOperationBehavior

     

    to VB

     

    any help is appriciated

    Friday, August 08, 2008 1:53 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>();

     

    Friday, August 08, 2008 2:42 PM
  •  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

    Wednesday, September 03, 2008 11:14 AM