in

dotNet Umbria [DNU]

Il primo User Group in Umbria sul mondo .Net
Latest post 10-22-2008 10:47 AM by danyolgiax. 5 replies.
Page 1 of 1 (6 items)
Sort Posts: Previous Next
  • 10-20-2008 6:04 PM

    Web Services...

     Ciao a tutti!

    sto creando alcuni web services con VS 2008 e ho un dubbio... in verità più di uno, ma iniziamo con questo:

    Sia l'applicazione client che il progetto dei web services utilizzano la medesima libreria di oggetti. Uno di questi oggetti
    è "Utente" che contiene i dati dell'utente loggato.
    Nel client il tipo è MyLibrary.Utente e nella firma del metodo del WS è ancora MyLibrary.Utente.
    Il problema sorge nel momento di chiamata del metodo; il parametro Utente diventa WebServiceNamespace.Utente!!!

    Perchè??

    In prima battuta non gli avevo dato peso ma poi ho notato che tra questi oggetti non riesco a fare nemmeno il cast!!
    Se inizio ad instaziare oggetti di tipo WebServiceNamespace.Utente inizio poi ad avere problemi di "nomi ambigui"!

    Sbaglio io? Spero di essere stato chiaro!

    Grazie

  • 10-20-2008 11:13 PM In reply to

    Re: Web Services...

     

    Ciao, se sviluppi un webservice classico è abbastanza normale questo comportamento.
    Il problema non sta nel modo in cui hai sviluppato tu il servizio, ma è il modo in cui il generatore di codice ha interpretato il WSDL.

    Ogni WS infatti contiene un documento XML che descrive attraverso un formato standard (WebServiceDefinitionLanguage) come è costruito il servizio e quali sono i tipi che il servizio stesso espone.
    VS2008 utilizza un tool per leggere il WSDL e per generare al posto tuo il codice necessario per comunicare con il webservice.
    Il tool tuttavia non riesce a capire che i tipi che hai esposto attravero il webservice sono gli stessi che hai gia all'interno della tua soluzione, perchè la descrizione del tipo non espone completamente l'oggetto, ma descrive soltanto le parti serializzabili dell'oggetto.
    Quindi ricrea un nuovo oggetto con la firma descritta dal WSDL all'interno dello spazio dei nomi del WebService.

    Il modo migliore per progettare un'applicazione utilizzando i WebService è evitare di inserire sia lato client che lato server le librerie che contengono gli oggetti per il trasporto dati.
    Il client dovrebbe utilizzare direttamente i tipi che vengono creati dal tool.

    Questo è abbastanza normale perchè non è detto che il client abbia a disposizione le DLL che sono presenti all'interno del server. E quindi il WebService mette a disposizione del client le informazioni necessarie per creare le strutture di comunicazione.

    C'è una soluzione per modificare questo comportamento, ovvero per forzare il client ad utilizzare la libreria al posto degli oggetti autogenerati.

    1. Nella solution clicca il pulsante della toolbar per visualizzare tutti i file. Vedrai che la reference del tuo servizio diventa espandibile ed al suo interno ci sono alcuni file CS.
    2. Modificare i tipi di oggetti all'interno del file CS eliminando le classi autogenerate e correggere il codice al fine di utilizzare le classi che hai in locale.

    Sinceramente ti sconsiglio questa soluzione perchè ti costringe a rimettere le mani all'interno di codice che generalmente viene autogenerato.

    Ti consiglio piuttosto di utilizzare WCF (Windows Communication Foundation) per creare il tuo servizio.

    WCF oltre ad introdurre numerose migliorie e migliori performance rispetto ai WebService classici, introduce un modello di programmazione differente basato su interfacce e contratti.
    Oltre ad essere maggiormente flessibile, hai una chiarezza migliore dell'utilizzo delle classi fin dallo sviluppo e non ti trovi ad affrontare questo tipo di problemi.

    Ciao

     

  • 10-21-2008 8:04 AM In reply to

    Re: Web Services...

    Sei stato chiarissimo!!!

    Grazie ora proverò con WCF!

    Daniele

  • 10-21-2008 9:04 AM In reply to

    Re: Web Services...

     ...penso di essere da capo a piedi! :-(

    utilizzando WCF ottengo questo errore:

    System.Runtime.Serialization.InvalidDataContractException: Type 'PandaLibrary.Beans.Utente' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.
       in System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type)
       in System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)
       in System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
       in System.Runtime.Serialization.DataContract.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
       in System.Runtime.Serialization.DataContract.GetDataContract(RuntimeTypeHandle typeHandle, Type type, SerializationMode mode)
       in System.Runtime.Serialization.DataContract.GetDataContract(RuntimeTypeHandle typeHandle, Type type)
       in System.Runtime.Serialization.DataContract.GetDataContract(Type type)
       in System.Runtime.Serialization.XsdDataContractExporter.GetSchemaTypeName(Type type)
       in System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.ValidateDataContractType(Type type)
       in System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreatePartInfo(MessagePartDescription part, OperationFormatStyle style, DataContractSerializerOperationBehavior serializerFactory)
       in System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreateMessageInfo(DataContractFormatAttribute dataContractFormatAttribute, MessageDescription messageDescription, DataContractSerializerOperationBehavior serializerFactory)
       in System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter..ctor(OperationDescription description, DataContractFormatAttribute dataContractFormatAttribute, DataContractSerializerOperationBehavior serializerFactory)
       in System.ServiceModel.Description.DataContractSerializerOperationBehavior.GetFormatter(OperationDescription operation, Boolean& formatRequest, Boolean& formatReply, Boolean isProxy)
       in System.ServiceModel.Description.DataContractSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
       in System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch)
       in System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)
       in System.ServiceModel.ServiceHostBase.InitializeRuntime()
       in System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
       in System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
       in System.ServiceModel.Channels.CommunicationObject.Open()
       in Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)

     

    Ho provato a marcare la class con [DataContract] ma per farlo penso debba essere all'interno del progetto WCF e, a questo punto, tornerei al punto di partenza!

    Le mie classi sono inoltre già marcate [Serializeble] e dovrebbero rimanerci (utilizzo delle trasformazioni xsl per le stampe pdf) a meno che [DataContract] e [Serializable] non siano equivalenti nella serializzazione.

    Daniele

  • 10-22-2008 12:43 AM In reply to

    Re: Web Services...

    Ciao, puoi marcare le tue classi sia con DataContract che con Serializable. Uno non esclude l'altro.
    Semplicemente Serializable dice al serializzatore standard del framework che le tue classi sono serializzabili, l'altro dice a WCF che la tua classe fa parte di un contratto per lo scambio di dati WCF.

    Inoltre non è necessario che le tue classi risiedano nel progetto server. Solitamente la soluzione WCF assume questa struttura:

    1) Progetto Server.
    2) Progetto per lo scambio di dati.
    3) Progetto client

    Il progetto 2 è referenziato sia dal progetto 1 che dal progetto 3 ma rimane a se stante. questo ti consente la mobilità necessaria senza la necessità di spostare lato client anche tutta la logica del server.
    Il fatto che l'attributo DataContract risieda nelle DLL che compongono la struttura di WCF è indifferente alla struttura della tua soluzione.
    Semplicemente aggiungi la reference alle librerie WCF a tutti e 3 i progetti della tua soluzione.

    Magari se posti un esempio del lavoro che stai facendo , oppure riesci a riprodurre la problematica in un esempio staccato dal tuo lavoro, possiamo fare esempi più concreti.

    Ciao

     

  • 10-22-2008 10:47 AM In reply to

    Re: Web Services...

     intanto voglio ringraziare per la pazienza!

    Ho compilato i tre progetti e se lancio il progetto WCF in debug da solo mi esce la finestra di test e sembra che tutto funzioni, anche i dati vengono restituiti correttamente.

    Ho provato ad aggiungere la reference nel client e qualcosa non gli è piaciuto.

    Quando arrivo alla form con la lista dei service e il namespace in fondo cliccando su OK ricevo il seguente errore:

    Object reference not set to an instance of an object.

    Nella lista il service appare con tutte i suoi metodi!

    La reference non si aggiunge!

    Idee?

Page 1 of 1 (6 items)
dotNet Umbria 2007-2008
Powered by Community Server (Commercial Edition), by Telligent Systems