Francesco Geri

Il blog di Francesco Geri
posts - 94, comments - 165, trackbacks - 2

Deserializzazione di un oggetto complesso passato come parametro in un WebMethod

Se in un WebMethod si passa come parametro un oggetto complesso si può ottenere un errore del tipo:

System.Web.Services.Protocols.SoapException: System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: A circular reference was detected while serializing an object of type MyObjectType.
   at System.Xml.Serialization.XmlSerializationWriter.WriteStartElement(String name, String ns, Object o, Boolean writePrefixed, XmlSerializerNamespaces xmlns)...

 

L'errore si può verificare anche se il riferimento circolare non c'è...

Cercando un po' ho trovato in questo post una soluzione per ovviare all'inconveniente, che secondo Kirk Marple potrebbe essere dovuto al fatto che l'XML Serializer usa il metodo Equals() per capire se un'oggetto è uguale o no ad un altro oggetto.

Per cui definendo un opportuno overrides della funzione Equals dell'oggetto, che si potrebbe basare su un ObjectID as GUID aggiunto alla classe.

 

Nel mio caso il problema era su una struttura, e le cose stanno in modo un po' diverso.
Innanzi tutto l'errore c'è se non inizializzo alcune proprietà (se le imposto tutte c'è l'errore) e poi la soluzione funzionante prevede di aggiungere la sola proprietà ObjectID, senza ridefinire necessariamente la Equals...

Questo è un esmepio:

 

Public Class Service1

    Inherits System.Web.Services.WebService

 

  ''' <summary>

  ''' Restituisce un array di persone

  ''' </summary>

  <WebMethod()> Public Sub GetPersone(ByRef p() As Persona, ByVal safe As Boolean)

    ReDim p(1)

    p(0).Nome = "Paolo"

    'p(0).Cognome non impostata !

    If safe Then

      p(0).ObjectId = Guid.NewGuid

    Else

      p(0).ObjectId = Guid.Empty

    End If

    p(1).Nome = "Paolo"

    'p(1).Cognome non impostata !

    If safe Then

      p(1).ObjectId = Guid.NewGuid

    Else

      p(0).ObjectId = Guid.Empty

    End If

  End Sub

 

 

  ''' <summary>

  ''' Classe Persona

  ''' </summary>

  <Serializable()> Public Structure Persona

 

    Private _nome As String

    Private _cognome As String

    Private _objectId As Guid

 

    Public Property Nome() As String

      Get

        If _nome Is Nothing Then

          _nome = String.Empty

        End If

        Return _nome

      End Get

      Set(ByVal value As String)

        _nome = value

      End Set

    End Property

    Public Property Cognome() As String

      Get

        If _cognome Is Nothing Then

          _cognome = String.Empty

        End If

        Return _cognome

      End Get

      Set(ByVal value As String)

        _cognome = value

      End Set

    End Property

 

    ''' <summary>

    ''' GUID dell'oggetto

    ''' </summary>

    Public Property ObjectId() As Guid

      Get

        Return _objectId

      End Get

      Set(ByVal value As Guid)

        _objectId = value

      End Set

    End Property

 

  End Structure

 

End Class

Print | posted on lunedì 17 marzo 2008 04:40 | Filed Under [ Tips .Net XML ]

Powered by:
Powered By Subtext Powered By ASP.NET