locked
Soap Serializer does not support serializing Generic Types.

    Question

  • I tried to serialize an object contains list (List<>) of objects and I got this exception:
    Soap Serializer does not support serializing Generic Types : System.Collections.Generic.List.

    It works fine with the BinaryFormatter.

    Thursday, June 02, 2005 7:12 PM

Answers

  • That is correct. We have decided not to invest in any significant new feature work for the SoapFormatter in Whidbey.

     -- Eugene Osovetsky
    Thursday, June 02, 2005 10:17 PM

All replies

  • That is correct. We have decided not to invest in any significant new feature work for the SoapFormatter in Whidbey.

     -- Eugene Osovetsky
    Thursday, June 02, 2005 10:17 PM
  • I don't this that is a good idea. It is a matter of consistency between the binary formmater and the SOAP formmater.
    Thursday, June 02, 2005 11:44 PM
  • We are aware of that, but the SoapFormatter is and will continue to become less important as time passes.

    If you need an Xml projection of a CLR type, the XmlSerializer is an excellent option until Indigo ships.

    Thursday, July 14, 2005 12:50 AM
  • Actually XmlSerializer IS NOT an excellent option. It basically cannot serialize private members (public properties are pretty limiting), which is an important part of the state of an object (obviously). I find this rather shocking that this made it into the final release of the product.  Indigo/WCF is a long ways off.
    Saturday, November 26, 2005 8:58 AM
  • I have to agree with Joseph on this. The XmlSerializer has some SERIOUS defficiencies that make it a very poor choice for serializing things. Aside from its inability to serialize private members, the XmlSerializer has issues serializing collections, and can't serialize anything that implements IDictionary at all. Class structures that contain circular references are also non-serializable, or their serialization is very limited.

    .NET is in dire need of a better serializer, and the SoapFormatter does pretty well, except for this lack of support for Generics. :(

    Friday, December 30, 2005 11:33 PM
  • I have to agree with the others that XmlSerializer is a poor relation - it will not serialize fields of types without a default constructor - in particular the one that is causing me frustration is the System.Uri class.

    With a class that has a System.Uri field and a generic type field, neither the SoapFormatter nor the XmlSerializer will work - the only solution seems to be to use the BinaryFormatter.

    Friday, January 13, 2006 3:36 PM
  • I Agree: I use XmlSerializer to build documentation or to share information from different application. But I use SOAP or Binary serialization to Save and Reload the whole application object graph.

    Mi application evolves in time, so the internal structure changes and i need to reload also the old save version.

    For very little changes i can handle it in the code, but for big changes it can be impossible.

    So, until some week ago, I usually write code that load the xml of the soap-serialized apllication an conver it in the new structure.

    But now I've used some generics ... and I can't serialize it in soap format. And I've not found any instrument to manipulate the output of the binary serializer.

    I've also try to use a serialization surrogate, but it dos't work in .NET 2.0 ( see my other post:http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=194553&SiteID=1).

     and now I'm scraping my heads thinking about a good solution ...

     

    Saturday, January 14, 2006 11:06 AM
  • I think the defficiencies of the XmlSerializer and sometimes the SoapFormatter are serious issues that need to be addressed in future .NET versions, or in WinFX. I havn't used Indigo, so I am not sure what kind of advancements have been made there. But its definitely something that needs to be addressed.

    I am currently working on a project where we had to ditch a months worth of work on a web services layer, and move the business logic onto the same server as our web server. There were too many issues serializing things. We now have had to slate time to design and develop our own distribution mechanism, using .NET Remoting and the BinaryFormatter, which will take another month or so to develop. All in all, the defficiencies of the XmlSerializer and .NET's native Web Service serialization capabilities have cost us several months of development time, and forced a reduction in the initial delivery of an application.

    While I do not think that Java is any better (on the contrary, it seems worse in many areas regarding serialization and web services), and we will not be changing off the .NET platform, serialization and web service capabilities in .NET are very dissapointing.

    Saturday, January 14, 2006 11:33 PM
  • This is the result of XML and WebServices being touted as a cure all for every data transmission woe we have.

    XML/SOAP has serious limitations among the most obvious being its verbosity. SOAP is PERFECT for extranet integration where you have no control over your partners' environments. It does not belong within an internal network ESPECIALLY when the communication is between two .Net applications.

    If you have two internal .Net applications that want to communicate, use .Net remoting with the binary formatter. It doesn't take much effort to switch applications that use the soap formatter over, and your network will appreciate the lighter load.

    There are even ways to get Java and .Net applications to communicate without SOAP. But that's a post for another day.

    Tuesday, January 17, 2006 9:32 PM

  • This is fine. I can live with use BinaryServerFormatterSinkProvider only.
    However, in our scenario, we are using event call back from server to client.
    So after I changed from SoapServerFormatterSinkProvider  to BinaryServerFormatter
    in my client data connection file, with the following codes like these

                    BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
                    BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();

                    //SoapServerFormatterSinkProvider serverProv = new SoapServerFormatterSinkProvider();
                    //SoapClientFormatterSinkProvider clientProv = new SoapClientFormatterSinkProvider();

                    serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
                   
                    //SoapClientFormatterSinkProvider clientProv = new SoapClientFormatterSinkProvider();

                    IDictionary props = new Hashtable();
                    props["port"] = 0;
                    props["TypeFilterLevel"] = "Full";

                    HttpChannel chan = new HttpChannel(props, clientProv, serverProv);  
                    ChannelServices.RegisterChannel( chan );

    It is working now for the client to server connection.


    however, because we do have events/delegation call back from server to client,
    so when the delegation fired, I am still getting the same error as
    "Soap Serializer does not support serializing Generic Types"


    So it looks like in the event call back, it is default using the soap serializer, is there anyway to set this to BinaryFormatter? thanks.



    Saturday, February 04, 2006 7:11 AM
  • The Binary formatter can handle callbacks and events. Check out the Remoting FAQ over here for pointers.
    Thursday, February 09, 2006 9:00 AM
  • Thanks for your reply, I followed the link but no vail.

    My probelm is in the server to client evnt call back, I am still getting a "Soap Serializer error."
    This should not happen, because if you look att the code I provided above, I have already
    set it to binaryformat in the client code...so how come a soap serializer error pop up?






    Friday, February 10, 2006 4:21 AM
  • Xinzhang, can you include the code for both sides of the wire?  Looking at what you posted, it's not obvious to me what's going wrong.

    Cheers,

    JJustice [MSFT]

    Tuesday, February 14, 2006 9:58 PM
  • Yeah, Let me post more codes about the configuration.
    What I am doing here is, I have a remoting server start, also to have the capability for a client to event call back to server, we defined a delegate and an event wrapper as the book "Advanced remoting said".

    Here is the definition:

        public interface IFactory
        {
            IWorker getNewWorker();
        }

         public delegate void PipelineDelegate(RemoteData rdo);

          public class CallbackPipeline: MarshalByRefObject
            {
                    public delegate void RealLocal(RemoteData commitData);

                    public RealLocal RealocalCall;

                    public void CallForRemote(RemoteData commitData)
                    {
                        realocalCall(commitData);
                    }  

                    public override object InitializeLifetimeService()
                    {
                        return null;
                    }
        }

    That is basically the interface definition for client and server
    Wednesday, February 15, 2006 7:36 AM
  • This the configuration in serverside,

    In serverside, we are using a config file and
    one line:  RemotingConfiguration.Configure(remoting_config_filename) to load up server.

    The config file is :
        <system.runtime.remoting>
            <application name="Data.Remoting">
                <lifetime InitialLeaseTime="5H" />
                <service>
                    <wellknown mode="Singleton" type="Data.Remoting.ImplFactory, Data.Remoting" objectUri="factory"/>
                </service>
                <channels>
                    <channel ref="tcp"  port="8016" displayName="Factory tcp channel"/>
                    <channel ref="http" port="8015" displayName="Factory http channel">
                        <serverProviders>
                            <provider  ref="wsdl"/>
                            <formatter ref="binary" typeFilterLevel="Full"/>
                        </serverProviders>
                    </channel>
                </channels>
            </application>
        </system.runtime.remoting>   

    ------------------------------------------------------------------------------------------

    In the client side, I am writing a bit codes to configure the remoting channel, which I can re-use for different clients.


    public void connect()
            {
               
                try
                {
                        serverUrl = "http://localhost:8015/factory";

                    if (ChannelServices.RegisteredChannels.GetLength(0) > 0)
                    {
                        foreach (IChannel channel in ChannelServices.RegisteredChannels)
                        {
                            ChannelServices.UnregisterChannel(channel);
                        }
                    }

                    // Ref: http://www.thinktecture.com/Resources/RemotingFAQ/Changes2003.html
                    BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
                    BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();

                    serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
                   
                    IDictionary props = new Hashtable();
                    props["port"] = 0;
                    props["TypeFilterLevel"] = "Full";
                    
                    HttpChannel chan = new HttpChannel(props, clientProv, serverProv);                 
                    ChannelServices.RegisterChannel( chan );

                    // after remoting is connected, here is the codes to set up the delegation
                    // for remoting event.
                    // all the codes below is making it possible for remoting client to get the event call back
                    remoteFactory = (IFactory) Activator.GetObject(    typeof(IFactory),serverUrl);
                    worker =  remoteFactory.getNewWorker();
                    client    = new CallbackPipeline();
                    client.realocalCall = new CallbackPipeline.realLocal(this.serverNotify);
                    worker.cltPipe   = new PipelineDelegate(client.callForRemote);
                }       
                catch
                {
                    throw;
                }
       }






    Wednesday, February 15, 2006 7:45 AM
  • the last bits of code is in the remoting server side, it is calling the delegate and send the data back to registered client (event call back)

        private PipelineDelegate pipe;
        private void TellRemoteClt(RemoteData commitData)
            {
                try
                {
                    this.pipe( commitData );
                }
                catch(Exception e)
                {
                    logg.Warn("Exception in call to client delegate:" + e.Message +" at:"+ this.identity);
                }
     
            }

    and here is the exception error it happened.

    the RemoteData is a remote data object class with some generic type defined.

    After the client configure, I can send the remote data to the server via remoting, it is no problem.

    However, after the server accept the remote data and submit the change, it also want to
    tell the registered listening clients, there is one data already changed...

    So the server is sending the remote object back to other clients via TellRemoteClt method and calls a delegate to fire it..

    Then I am getting this soap serializer problem...

    IMHO, there must be somewhere I should explicitly define use BinarySerializing... whereelse though?







    Wednesday, February 15, 2006 7:58 AM
  • Have you tried using a TcpChannel, rather than an HttpChannel? I'm not certain, but I think the HttpChannel will always format certain things with a soap envelope, where as the TcpChannel will always format things with whatever formatter you've specified. I havn't used the HttpChannel much, as I usually use the TcpChannel, so its just a thought.

    Thursday, February 23, 2006 9:38 PM
  • xinzhang, did you solve the problem? Now I have a similar one: http channel, binary formatter, remote call and return type that containes nullables (generics). And get "Soap Serializer does not support serializing Generic Types" error.
    Monday, August 28, 2006 9:18 AM
  • I got it working with TCPChannel binary formatter.
    Tuesday, August 29, 2006 12:35 AM
  • I tend to use SOAP serializer instead of Binary since it provides me with easier way to see the content - i just open it using ANY text editore and i can see if all my data passed on correctly or not.

    I don't have this ability in Binary formatter.

    XmlSerializer is NOT an option since it does NOT allow you to custom the serialization in the same way that SOAP and Binary allow using attributes and implementing ISerializable (and i don't like the idea of building my own formatter that will generate the utilize the XmlSerializer)


    Is there any tool that enable me to parse/browse the information stored in binary format?
    Thursday, January 31, 2008 11:28 AM
  • So after 2 years of posts in this thread theres still no good answer.

    I'm like everyone else here. I want the benefits of the Binary Serializer but I want the human readability that XML / Soap gives you.

    XML Serializer is WAY to verbose. I mind as well write my own serializer than use the XML one (which I'm not going to do).
    It needs to

    1) Save the private/public member (like the binary formatter) (Not the properties which is pointless)
    2) It needs to perform deep serialization (like the Bin Formatter)
    3) It needs to be human readable.
    4) It sholdn't require explicite markup of every member (like XML requires).

    MY GOD. Is there not an xml/ soap serializer that is functionaly equivalent to the Binary Serializer available?

    ANYONE?
    Wednesday, February 13, 2008 11:55 AM
  • I've searched it for a while, but at last I've build my own from scratch.

     

    I't use Reflection to find private field and write it out to an XML format using System.Xml.XmlConvert.

    So I can convert from previous version saved files using XSLT an a little bit of version indipendent code.

     

    I'm sorry but it's too binded with the structure of my application to publish it. But using Reflector an taking a look at the Rotor sources it can be developed it in few weeks.

    It can't handle all scenarios but it can persist and rebuild my application core object model graph and I can read it with my eyes to find errors and mainpulate it with my code to handle version upgrade and bug fix.

     

    Using it I was able to make a deep refactor of my application that was simply impossible using the original Binary Serialization.

     

    This is what I think people need from a Binary Serialization framework. An obscure undocumented binary blob simply can't handle all the needs of all the people.

     

    I like .NET and I hope that Microsoft people will think about this in the future.

     

    Thursday, February 14, 2008 10:43 PM
  • Solution!!!

    I found an xml serializer for on Source Forge called

    Nxmlserializer
    http://sourceforge.net/projects/nxmlserializer/

    It does a pretty good job of serializing most objcet graphs and restoring them properly.

    Notes:
    1) I think I had problems with it not recording enums properly and I was able to very quickly write my own handler for Enums.

    2) It wanted you to use its custom Attributes instead of the standard .Net ones. I once again started modifying it locally so that it would handle the .net attributes.


    Give it a try

    • Proposed as answer by asdf989 Wednesday, December 03, 2008 10:42 AM
    Wednesday, December 03, 2008 10:17 AM
  • Sadly, the Installer class appears to use the SoapFormatter to serialize items to the IDictionary used to save state. This means that you can't save state using a Generic collection in a Visual Studio InstallerClass custom action.
    Friday, April 30, 2010 2:23 PM