Visualizzazione dei risultati da 1 a 10 su 28

Hybrid View

  1. #1
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    54
    Ciao sspintuxe grazie nuovamente per il tempo dedicatomi

    Data la mia scarsa conoscenza dei web services in generale richiamati da un'applicazione Desktop standard Vb.Net, gli argomenti trattati nella tua risposta mi risultano un pochino ostici...devo trovarmi un po' di tempo per approfondire.
    Il problema di deserializzare (come fatto per l'errore) è che, il Web Service, non mi restituisce tutti i campi della classe ma solo quelli effettivamente riempiti; non posso quindi utilizzare il tool "xsd" sull'XML ritornato dal WS perchè mi genererebbe delle classi prive dei campi nulli per quella specifica richiesta. Dovrei quindi mettermi a definire manualmente tutte le decine di strutture che costituiscono le possibili risposte del Web Service
    Per questo motivo, qualora non si possa richiamare direttamente i metodi del servizio web importato per riferimento (a causa dell'autenticazione UserToken), chiedevo se era possibile trasformare l'oggetto ottentuo mediante la "GetResponse" nella classe (che conosco a priori) definita mediante l'importazione del riferimento al servizio.

    Non mi resta che cercare online le modalità da Te suggerite.
    Grazie di nuovo e Buona giornata

  2. #2
    Quote Originariamente inviata da mmjc23 Visualizza il messaggio
    ....
    Non mi resta che cercare online le modalità da Te suggerite.
    .....
    ho visto l'header di sicurezza richiesto.
    Fossi in te mi concentrerei su quanto ti indicato al punto 2) del messaggio precedente
    e lascerei perdere la request costruita a manina

  3. #3
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    54
    Ciao sspintux
    Ti dirò...io ho provato a dare un'occhiata al link che mi hai postato, ma non c'ho capito una mazza...
    O meglio...non sono riuscito a capire come valorizzare gli oggetti "OperationContextScope" e "MessageHeader"; ho trovato anche altri esempi online che utilizzavano l'oggetto "SoapClient" ma, pur avendo cercato in lungo e in largo, non c'è stato verso di capire come dichiarare (in VS2010 e Framework 4.0) un oggetto "SoapClient" e passargli gli oggetti "Binding" e "EndPoint"

    Alla fine, la botta di ( | )...da un post di un Forum che avevo già letto ma che non riuscivo ad utilizzare...

    Posto qui la soluzione, qualora potesse essere utilie in futuro a qualcun altro...mi rimane ancora da capire come modificare l'app.config runtime (visto che l'indirizzo di EndPoint ed username e password del servizio li carico all'avvio dell'applicazione)

    Quindi:
    -Ho aggiunto il riferimento al servizio web mediante il suo WSDL (questa operazione, mi va a creare un file app.config all'interno del progetto)
    -All'interno dell'app.config, viene creata una sezione "client" relativa ai servizi importati come mostrato di seguito
    codice:
    <client>
                <endpoint address="https://e-servizicoll.dtt.ilportaledellautomobilista.it:443/Info-ws-sh/services/dettaglioAutoveicoloComproprietariTrasferimentiRes/"
                    binding="basicHttpBinding" bindingConfiguration="dettaglioAutoveicoloComproprietariTrasferimentiResSoap11"
                    contract="Autoveicolo.dettaglioAutoveicoloComproprietariTrasferimentiRes"
                    name="dettaglioAutoveicoloComproprietariTrasferimentiResSoap11">
                    </endpoint>
    </client>
    -Dopo il Tag "name", è bastato aggiungere l'header richiesto dal Web Service in questo modo:
    codice:
    <client>
                <endpoint address="https://e-servizicoll.dtt.ilportaledellautomobilista.it:443/Info-ws-sh/services/dettaglioAutoveicoloComproprietariTrasferimentiRes/"
                    binding="basicHttpBinding" bindingConfiguration="dettaglioAutoveicoloComproprietariTrasferimentiResSoap11"
                    contract="Autoveicolo.dettaglioAutoveicoloComproprietariTrasferimentiRes"
                    name="dettaglioAutoveicoloComproprietariTrasferimentiResSoap11">
                    <headers>
                        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                            <wsse:UsernameToken>
                                <wsse:Username>MY_USERNAME</wsse:Username>
                                <wsse:Password>MY_PASSWORD</wsse:Password>
                            </wsse:UsernameToken>
                        </wsse:Security>
                    </headers>
                </endpoint>
    </client>
    -A questo punto, si passa allo sviluppo VB: innanzi tutto, visto che il servizio web richiede un certificato, l'ho "imbrogliato" in questo modo:
    codice:
     'Evento di avvio del form
        Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
            'Imposto (all'avvio per sempre) l'autenticazione Ssl3 e la risposta forzata a "True" alla richiesta di certificato necessari per il servizio di motorizzazione
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
            ServicePointManager.ServerCertificateValidationCallback = New System.Net.Security.RemoteCertificateValidationCallback(AddressOf AcceptAllCertifications)
        End Sub
    
        'Callback richiesta certificato
        Private Function AcceptAllCertifications(ByVal sender As Object, ByVal certification As System.Security.Cryptography.X509Certificates.X509Certificate, ByVal chain As System.Security.Cryptography.X509Certificates.X509Chain, ByVal sslPolicyErrors As System.Net.Security.SslPolicyErrors) As Boolean
            'Restituisce True qualsiasi certificato venga richiesto
            Return True
        End Function
    -Ora, nella routine dove si deve consumare il servizio Web, è necessario dichiarare una variabile del tipo importato mediante l'importazione servizio Web, SPECIFICANDO NEL "NEW" IL PARAMETRO "name" CHE ABBIAMO VISTO PRIMA NEL FILE app.config
    codice:
     Dim myClient As New Autoveicolo.dettaglioAutoveicoloComproprietariTrasferimentiResClient("dettaglioAutoveicoloComproprietariTrasferimentiResSoap11")
            Dim rq As New Autoveicolo.DettaglioAutoveicoloBaseType
            Dim tg As New Autoveicolo.TargaType
            tg.numeroTarga = "AA123ZZ"
            rq.dettaglioAutoveicoloBaseInput = New Autoveicolo.DettaglioAutoveicoloBaseInputType
            rq.dettaglioAutoveicoloBaseInput.Item = tg
            Dim lg As New Autoveicolo.LoginType
            lg.codicePin = ""
            rq.login = lg
            rq.pdf = False
            Dim rs As Autoveicolo.DettaglioAutoveicoloComproprietariTrasferimentiResResponseType
            rs = myClient.dettaglioAutoveicoloComproprietariTrasferimentiRes(rq)
    ...e finalmente, mi ritrovo l'oggetto "rs" valorizzato con tutti i parametri ritornati dal Web Service.
    Questo è quanto...non posso purtroppo dare eventuale supporto perchè non c'ho capito molto nemmeno io e probabilmente ci sarà dei modi più eleganti per farlo, ma è sempre meglio che analizzare riga per riga, tag per tag, la risposta "GetResponseStream".

    Non mi rimane che capire come modificare l'app.config runtime in base a EndPoint e Username/Password letti da file config XML.

    Ti ringrazio infinitamente per il supporto e per il tempo dedicatomi
    Buona serata

  4. #4
    Quote Originariamente inviata da mmjc23 Visualizza il messaggio
    Ciao sspintux
    Ti dirò...io ho provato a dare un'occhiata al link che mi hai postato, ma non c'ho capito una mazza...
    ....
    Alla fine, la botta di ( | )...da un post di un Forum che avevo già letto ma che non riuscivo ad utilizzare...
    .......

    Non mi rimane che capire come modificare l'app.config runtime in base a EndPoint e Username/Password letti da file config XML.
    Ciao,
    a me sembra che tu stia girando intorno al problema riuscendo ogni volta a creartene uno nuovo;
    tra parentesi incomincio ad avere il sospetto che anche la deserializzazione a manina dell'errore sia inutile.

    Non ho provato , ma questo è un custom binging che dovrebbe andare bene nel tuo caso
    visto che usi https:
    codice:
    <bindings>
      <customBinding>
     <binding name="CustomSoapBinding">
       <security includeTimestamp="false"
        authenticationMode="UserNameOverTransport"
        defaultAlgorithmSuite="Basic256"
        requireDerivedKeys="false"
        messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
       </security>
       <textMessageEncoding messageVersion="Soap11"></textMessageEncoding>
       <httpsTransport />
     </binding>
      </customBinding>
    </bindings>
    username e password li imposti con un codice tipo questo :
    codice:
    var proxy = new ServiceRef.ServizioClient();
    proxy.ClientCredentials.UserName.UserName = "user";
    proxy.ClientCredentials.UserName.Password = "Password";
    Non funzionerebbe con il protocollo http perché per impostazione predefinita WCF
    non permette l'invio di username e password in chiaro senza una qualche forma di protezione,
    motivo per cui ti avevo suggerito il punto 2) che funziona anche in questo caso e che , sempre senza aver provato e senza controllo errori, suona più o meno così:

    codice:
    using (var proxy = new ServiceRef.ServizioClient())
    {
     using (new OperationContextScope(proxy.InnerChannel))
     {
      string headerText =
         "<wsse:UsernameToken  xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\"> " +
         "<wsse:Username>{0}</wsse:Username> " +
         "<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">{1}</wsse:Password> " +
         "</wsse:UsernameToken> ";
    
    
      headerText = string.Format(headerText, "user", "pwd");
    
    
      XmlDocument MyDoc = new XmlDocument();
      MyDoc.LoadXml(headerText);
      XmlElement myElement = MyDoc.DocumentElement;
    
    
      System.ServiceModel.Channels.MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", myElement, true);
      OperationContext.Current.OutgoingMessageHeaders.Add(myHeader);
    
    ....
    
    }
    Se non dovesse funzionare o se occorre un maggior controllo su come formare l'header di sicurezza
    si può fare una cosa del genere :
    codice:
    using (var proxy = new ServiceRef.ServizioClient())
    {
     using (new OperationContextScope(proxy.InnerChannel))
     {
      var sh = new ClientSecurityHeader(utente, password);
      OperationContext.Current.OutgoingMessageHeaders.Add(sh);
      ....
     }
    }
    dove ClientSecurityHeader è una classe che eredita da MessageHeader
    ed in cui puoi eseguire l'override dei suoi vari metodi :
    OnWriteHeaderContent, OnWriteStrartHeader .... e compagnia bella.

    .... infine, sicuro che non ti basti questo per risolvere alla radice
    il problema della derializzazione dell'errore ?
    codice:
    // in pseudocodice
    se il tipo della risposta ricevuto è errotype 
       'casta' la risosta in errortype
    altrimenti 
       'castala' in ripostatype

    HTH
    Ultima modifica di sspintux; 15-01-2016 a 10:04

  5. #5
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    54
    Ciao,
    a me sembra che tu stia girando intorno al problema riuscendo ogni volta a creartene uno nuovo;
    Eh...purtroppo, ci si ritrova a dover sviluppare funzionalità a tempo zero senza avere il tempo di andare a fondo delle questioni.
    Ci si ritrova quindi spesso a copiare pezzi di codice sperando che facciano al caso tuo, cercando di capirci il più possibile...si fa quel che si può!

    [QUOTE]
    tra parentesi incomincio ad avere il sospetto che anche la deserializzazione a manina dell'errore sia inutile.
    [QUOTE]

    Esatto! "Errore", non è altro che una parte della classe "dettaglioAutoveicoloComproprietariTrasferimentiRe sClient" importata mediante il riferimento al servizio Web. Quando la richiesta effettuata al servizio Web genera un errore, il web service risponde solo con i parametri della classe valorizzati e quindi, in caso di errore, solo con la "struttura" errore. Adesso che sono riuscito (come illustrato sopra) a richiamare direttamente il metodo del Web Service, qualora la richiesta generi un errore, mi ritrovo in risposta sempre un oggetto "dettaglioAutoveicoloComproprietariTrasferimentiRe sClient" completo ma con solo i parametri "Errore" valorizzati.

    Purtroppo, fatico a capire il codice da Te postato...già alla prima riga dove viene definita la variabile proxy, mi genera l'errore "Il binding su system.serviceModel/bindings/basicHttpBinding non dispone di un binding configurato con nome 'dettaglioAutoveicoloComproprietariTrasferimentiRe sSoap11'. Valore non valido per bindingConfiguration."....comunque...

    Una volta arrivato a far funzionare tutto il codice postato, non vedo comunque una chiamata diretta al metodo del servizio Web che, alla fine, è quello che mi consente, con un'unica chiamata, di ritrovarmi in risposta un oggetto di tipo "DettaglioAutoveicoloComproprietariTrasferimentiRe sResponse" valorizzata con tutti i parametri restituiti dal servizio.

    Per come funziona il codice che ho postato sopra, mi ritengo soddisfatto del risultato, nel senso...con una banale modifica del file app.config e la definizione dei "4" oggetti propri del Web Service, richiamo il suo metodo e mi ritrovo in risposta la classe/oggetto "DettaglioAutoveicoloComproprietariTrasferimentiRe sResponse" riempita di tutti i valori disponibili.

    Considero quindi il problema di inviare l'autenticazione SOAP al web service risolta, e in modo "pulito"...in quanto, come ho fatto sopra, non mi devo impelagare nella definizione di decine di oggetti VB per costruirmi l'Header da passare/associare ad altri oggetti.
    Mi basta aggiungere (in modo statico e definitivo) quelle 4 righe nel tag "<client>" del app.config e sono a posto
    Siccome però l'indirizzo di EndPoint, Username e Password sono configurabili (nell'applicativo), devo solo capire come modificare l'app.config runtime (prima che venga letto dall'oggetto che richiama il servizio) o eventualmente, come modificare questi parametri a posteriori una volta che l'istruzione "Dim myClient As New Autoveicolo.dettaglioAutoveicoloComproprietariTras ferimentiResClient("dettaglioAutoveicoloComproprie tariTrasferimentiResSoap11")" se li è già caricati dal file app.config.

    Mamma mia che pazienza che c'hai...Grazie mille e Buona serata

  6. #6
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    54
    Ciao sspintux...ce l'ho fatta.

    Partendo dal codice che mi avevi postato (con alcune variazioni alla stringa di Header) e senza modificare il file app.config.

    Ecco il codice:
    codice:
    Private Sub GetWS(StringaUriEndpoint as string, StringaUsername as string, StringaPassword as string)
     Dim binding As New CustomBinding()
            Dim security As TransportSecurityBindingElement = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement()
            security.IncludeTimestamp = False
            security.DefaultAlgorithmSuite =ServiceModel.Security.SecurityAlgorithmSuite.Basic256
            security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10
            security.SetKeyDerivation(False)
            Dim encoding As New TextMessageEncodingBindingElement
            encoding.MessageVersion = MessageVersion.Soap11
            Dim transport As New HttpsTransportBindingElement()
            binding.Elements.Add(security)
            binding.Elements.Add(encoding)
            binding.Elements.Add(transport)
            Dim EP As New EndpointAddress(StringaUriEndpoint)
    
            Dim proxy As New Autoveicolo.dettaglioAutoveicoloComproprietariTrasferimentiResClient(binding, EP)
            proxy.ClientCredentials.UserName.UserName = StringaUsername
            proxy.ClientCredentials.UserName.Password = StringaPassword
    
            Using New OperationContextScope(proxy.InnerChannel)
    
                Dim strHeader As String = "<wsse:Security xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""> " & _
                                              "<wsse:UsernameToken> " & _
                                                  "<wsse:Username>{0}</wsse:Username> " & _
                                                  "<wsse:Password>{1}</wsse:Password> " & _
                                              "</wsse:UsernameToken> " & _
                                          "</wsse:Security>"
    
                strHeader = String.Format(strHeader, StringaUsername, StringaPassword)
                Dim MyDoc As New XmlDocument
                MyDoc.LoadXml(strHeader)
                Dim MyElement As XmlElement = MyDoc.DocumentElement
                Dim Header As MessageHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", MyElement, True)
                OperationContext.Current.OutgoingMessageHeaders.Add(Header)
    
                Dim rq As New Autoveicolo.DettaglioAutoveicoloBaseType
                Dim tg As New Autoveicolo.TargaType
                tg.numeroTarga = "AJ307EY"
                rq.dettaglioAutoveicoloBaseInput = New Autoveicolo.DettaglioAutoveicoloBaseInputType
                rq.dettaglioAutoveicoloBaseInput.Item = tg
                Dim lg As New Autoveicolo.LoginType
                lg.codicePin = ""
                rq.login = lg
                rq.pdf = False
                Dim rs As Autoveicolo.DettaglioAutoveicoloComproprietariTrasferimentiResResponseType
                rs = proxy.dettaglioAutoveicoloComproprietariTrasferimentiRes(rq)
            End Using
        End Sub
    Ultima modifica di mmjc23; 16-01-2016 a 12:55

  7. #7
    Quote Originariamente inviata da mmjc23 Visualizza il messaggio
    Ciao sspintux...ce l'ho fatta.
    ...
    Emmmmhhh...

    guarda... se mi dici che funziona .... ok! , non ho difficoltà a crederlo, ma non è proprio bello
    da vedere perché con il tuo ultimo codice stai aggiungendo *due* header di sicurezza:

    il primo *implicitamente* tramite il custom binding che ti ho suggerito

    ed il secondo *a manina* con OperationContext.Current.OutgoingMessageHeaders.Ad d(Header)
    ( ... su cui , a dire il vero, ho anche qualche dubbio)

    Ne basta solo uno !


    P.S.
    per curiosità ( ... ed anche perché se continui a lavorare con i web service ti servirà)
    potresti mostrare l'xml del messaggio soap generato ?

    Puoi impostare i log di wcf, o usare Fiddler
    ...da tenere presente anche soapUI con la comoda funzionalità del "Generate MockService"

    Ultima modifica di sspintux; 16-01-2016 a 18:50

  8. #8
    Utente di HTML.it
    Registrato dal
    May 2006
    Messaggi
    54
    Sapevo che mi avresti bacchettato....

    Inizialmente, avevo lasciato solo l'header "a manina" con OperationContext, ma durante l'esecuzione del codice mi veniva generato un errore che mancavano i parametri di Login se non mettevo proxy.ClientCredentials.UserName.UserName = StringaUsername proxy.ClientCredentials.UserName.Password = StringaPassword.

    Allora ho provato a togliere quello a manina e lasciare solo quello dell'OperationContext ma....altro errore. Solo con entrambi funziona correttamente.

    Purtroppo, non posso postarti gli errori ed il codice xml ritornato fino a domani...non ho qui il PC
    Buona Domenica

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.