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