Creazione WebServices and xml

lunedì 10 marzo 2008 - 23.30

bluelions Profilo | Senior Member

Gentilissimi amici del forum,
vi scrivo per chiedere un vostro aiutino in merito alla creazione di un webservice che mi permette di leggere una struttura di un file xml.
Vi spiego in dettaglio il problema:
Devo creare un WebMethod che prende in input un file xml del tipo
<miofile>
<nome>pippo</nome>
<cognome>pluto</cognome>
<datanascita>01/01/2005</datanascita>
</miofile>
e passandolo al mio metodo devo leggermi questi dati per fare poi una serie di operazioni, dopo fatto cio devo creare io un xml di ritorno secondo uno schema da me definito.
Avevo pensato di farmi un webmethod che mi restituisce in xmldocument e come parametro gli passo sempre un xmldocument. Però non sono riuscito a capire come cavolo leggermi la struttura xml e come creare il nuovo file xml di ritorno.
Stavo cercando di utilizzare i deseralize, ma volevo un aiuto da parte vostra e magari qualche esempio.
Vi ringrazio anticipatamente.

Saluti

rossimarko Profilo | Guru

Ciao,

io per un discorso di robustezza dell'applicazione ti consiglio di crearti delle classi serializzabili invece che usare un xml document.

Ti riporto un esempio di una classe che rappresenta l'xml da te postato:
[Serializable, System.Xml.Serialization.XmlRoot("miofile")] public class MioFile { string _Nome; string _Cognome; string _DataNascita; [System.Xml.Serialization.XmlElement("nome")] public string Nome { get { return _Nome; } set { _Nome = value; } } [System.Xml.Serialization.XmlElement("cognome")] public string Cognome { get { return _Cognome; } set { _Cognome = value; } } [System.Xml.Serialization.XmlElement("datanascita")] public string DataNascita { get { return _DataNascita; } set { _DataNascita = value; } } }

Come puoi vedere con l'attributo "XmlElement" puoi definire il nome dell'elemento che verrà generato. Il parametro DataNascita l'ho volutamente lasciato come stringa perchè ho visto che la data la riporti nel formato italiano. Se lo trasformi in datetime la data verrà serializzata in xml secondo lo standard ISO.

Poi puoi decidere di:
- utilizzare direttamente le classi come parametri del webservice
Ad esempio
[WebMethod] public bool ProvaFile(MioFile par) { //codice }

- uppure utilizzare dei parametri stringa che conterranno l'xml della classe serializzata
[WebMethod] public bool ProvaFile(string classXML) { //codice }


Nel secondo caso dovrai usare le funzioni per la serializzazione/deserializzazione xml e gestire bene le varie casistiche di errore (potrebbero ad esempio passarti una stringa non valida).
Ti giro un paio di link utili sulla serializzazione
http://support.microsoft.com/default.aspx/kb/316730 (VB.Net)
http://support.microsoft.com/default.aspx/kb/815813 (C#)

Io ho postato gli esempi in c# non sapendo che linguaggio usi. Se serve ti converto il tutto in VB.Net

PS: la soluzione delle stringhe può essere adottata anche nel caso in cui tu voglia usare un xmldocument. Basta che all'interno del webmethod crei un xmldocument e carichi la stringa xml che ti è stata passata. Ovviamente dovrai gestire tutti i possibili errori (stringa vuota, contenuto errato ecc.)
Io preferisco sempre tipizzare il più possibile i webmethod però molto dipende dalle tue esigenze.

Se ci sai dire da chi e come verrà utilizzato il webservice (WinApp .net, applicazione Java ecc) magari riusciamo a definire meglio quale sia la strada migliore da seguire.

bluelions Profilo | Senior Member

Gentile amico
purtroppo la cosa che non riesco a fare è la serializzazione, nel senso che creando una classe che poi mi dovrebbe restitutire lo schema da me scelto....non riesco proprio a farla funzionare.Quando istanzio il metodo serialize non mi chiama la classe.

rossimarko Profilo | Guru

Ma non ti restituisce nessun errore?
Puoi postare il codice che usi per la serializzazione così guardiamo cosa può essere?

bluelions Profilo | Senior Member

Questa è la classe:

using System;
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace Ws.Ordine
{
[Serializable()]
public class OrderStatusRequest
{
#region DICHIARAZIONI

string _descrizioneordine = string.Empty;
string _stato = string.Empty;
string _importorichiesto = string.Empty;

#endregion

public LocalADVOrderStatusRequest()
{
}

#region "PROPRIETA'"

public string descrizioneordine
{
get{return _descrizioneordine;}
set{_descrizioneordine = value;}
}
public string stato
{
get{return _stato;}
set{_stato = value;}
}
public string importorichiesto
{
get{return _importorichiesto;}
set{_importorichiesto = value;}
}

#endregion
}

}

Questo sono i due metodi serialize e deserialize
using System;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace Ws
{
public class Process
{
public Process()
{

}

#region SerializeObject
public static string SerializeObject(object Obj, Type _Type)
{
string Xml = string.Empty;

try
{
XmlSerializer serializer = new XmlSerializer(_Type);

MemoryStream ms = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter (ms,System.Text.Encoding.UTF8);

serializer.Serialize(writer,Obj);


writer.Flush();
writer.Close();

}
catch(Exception Ex)
{
throw Ex;
}
finally
{
}

return Xml;
}
#endregion

#region DeserializeXml
public static object DeserializeXml(string Xml, Type _Type)
{
object _obj = null;

try
{
XmlSerializer serializer = new XmlSerializer(_Type);

TextReader readerXml = new StringReader(Xml);

try
{
_obj = serializer.Deserialize(readerXml);
}
catch( Exception ex )
{
throw ex;
}
finally
{
readerXml.Close();
}
}
catch(Exception Ex)
{
throw Ex;
}
finally
{
}

return _obj;
}
#endregion
}
}

E poi dal WebMethod faccio la chiamata
Ordine.Response _Response = null;
Process.SerializeObject(_Response,typeof(Ordine.Response));

il Deserialize funziona, ma non riesco a serializzare
Grazie

rossimarko Profilo | Guru

Ciao,

ho provato la tua routine di serializzazione ed in effetti non funziona. Il problema è dovuto al fatto che non viene valorizzata la variabile
string Xml
che poi viene ritornata dalla funzione.

Ho modificato la tua procedura come segue:

public static string SerializeObject(object Obj, Type _Type) { try { XmlSerializer serializer = new XmlSerializer(_Type); System.Text.StringBuilder sb = new System.Text.StringBuilder(); using (StringWriter sw = new StringWriter(sb)) { using (XmlTextWriter writer = new XmlTextWriter(sw)) { serializer.Serialize(writer, Obj); writer.Close(); } } return sb.ToString(); } catch (Exception Ex) { throw; } }

Ho usato la classe StringWriter per scrivere il contenuto dello stream all'interno di uno StringBuilder.

A me funziona correttamente, fammi sapere se ci sono altri problemi.

bluelions Profilo | Senior Member

funziona,però non mi crea i tag xml all'interno. In pratica il tipo di classe che ho creato non me la chiama e pertanto non mi crea la formattazione dell'Xml

rossimarko Profilo | Guru

Rileggendo il codice che hai mandato penso che il problema sia dovuto al fatto che non valorizzi la classe prima di serializzarla:

Ordine.Response _Response = null; Process.SerializeObject(_Response,typeof(Ordine.Response));

Io ho fatto una prova con questo codice:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

e dentro a str trovo i dati della classe.

Se il problema non fosse questo, puoi mandare il codice completo della funzione in cui richiami la serializzazione?

PS: ho usato la classe OrderStatusRequest perchè non ho la tua classe Ordine.Response

bluelions Profilo | Senior Member

Ora funziona, ma la classe la devo inizializzare per forza?
Anche perchè nel metodo deserialize mi imposto l'oggetto (classe) a nulla e deserializzo il file xml.
Mi potresti spiegare in dettaglio come funziona veramente?
Te ne sarei grato

rossimarko Profilo | Guru

Si la devi inizializzare e valorizzare, altrimenti l'oggetto risulta vuoto.

Cerco di spiegarmi meglio con un esempio pratico.
Supponiamo che tu debba ritornare un xml di questo tipo:

<MioOggetto> <Proprieta1>pippo</Proprieta1> <Proprieta2>pluto</Proprieta2> </MioOggetto>

Per ritornare questo xml dovrai:
- creare una nuova instanza della classe e valorizzarne le proprietà:
MioOggetto p = new MioOggetto();
- valorizzarne le proprietà
p.Proprieta1 = "pippo"; p.Proprieta2 = "pluto";
- serializzare l'oggetto in una stringa xml

Alla fine ti troverai l'xml con i valori che desideri.

Questo per quanto riguarda la procedura di serializzazione, che è da utilizzare quando vuoi creare un xml con i valori contenuti in un oggetto. Se invece devi leggere un xml allora devi usare la deserializzazione.


bluelions Profilo | Senior Member

ho capito, quindi quando lo devo deserializzare io imposto l'istanza della classe a null.
Però quando mi creo l'Xml lo trovo in questo formato:

<?xml version="1.0" encoding="utf-16" ?>
- <LocalADVOrderResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<IdOrdine>1Z-PCR56</IdOrdine>
<esito>0</esito>
<messaggio>OK</messaggio>
</LocalADVOrderResponse>

Mentre io lo vorrei nel formato:
<?xml version="1.0" encoding="utf-16" ?>
- <LocalADVOrderResponse>
<IdOrdine>1Z-PCR56</IdOrdine>
<esito>0</esito>
<messaggio>OK</messaggio>
</LocalADVOrderResponse>

Ho letto da qualche parte che devo utilizzare l'encoding o mi sbaglio?

rossimarko Profilo | Guru

Se vuoi togliere i namespace devi usare la classe XmlSerializerNamespaces, aggiungendo un namespace vuoto.

Ti riporto la funzione di serializzazione completa:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5