none
Consumare un web service da codice C# RRS feed

  • Domanda

  • Salve,

    avrei la necessità di realizzare del codice C# per accedere ad un web service messo a disposizione

    dall'ente VIES per validare le partite iva europee, in realtà la nostra applicazione è in VB6 e fin'ora

    abbiamo usato senza problemi una chiamata SOAP; tuttavia da qualche settimana ho dei problemi

    e l'ente non mi ha saputo dare risposte adeguate se non che ultimamente hanno effettuato upgrade

    di sicurezza.

    Comunque, quello che avrei intenzione di fare sarebbe fare una piccola utility in C# che

    si collega a questo web service e mi restituisce un esito; questa utility la debbo potere interrogare da VB6

    , potergli inviare dei parametri e ricevere un esito.

    E' possibile ? Se sì che tipo di progetto C# devo creare ? Come accedere al web service dal progetto ?

    Se vi può essere d'aiuto vi fornisco il codice VB6 che ho adoperato fin'ora :

    Public Function CheckValidVat(ByVal sPaese As String, ByVal sVat As String, dData, bValid, sDenominazione, sIndirizzo, bManaged) As Boolean
        
        Dim SoapObj                 As Object
        
        Const sUrlWsdl              As String = "http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl"
        
        Screen.MousePointer = vbHourglass
        
        CheckValidVat = False
        
        If Len(Convalida(sPaese)) < 2 Then GoTo Uscita
        If Len(Convalida(sVat)) = 0 Then GoTo Uscita
        
        'Se Partita IVA Fittizia bypassiamo i controlli
        If sPaese = "OO" And Trim(sVat) = String(11, "9") Then
            bValid = True: CheckValidVat = True: Exit Function
        End If
        
        On Error GoTo Errore
        
        Set SoapObj = CreateObject("MSSOAP.SoapClient30")
            
        SoapObj.MSSoapInit (sUrlWsdl)
        
        Call SoapObj.CheckVat(sPaese, sVat, dData, bValid, sDenominazione, sIndirizzo)
        
        'MsgBox "Valid VAT = " & CStr(bValid) & vbCrLf & "Name VAT = " & sDenom & vbCrLf & "Address VAT = " & sAddress, vbInformation
        
    Uscita:
        
        bManaged = True
        
        CheckValidVat = True
        
        Screen.MousePointer = vbDefault
        
        Exit Function
     
    Errore:
        
        Screen.MousePointer = vbDefault
        
        If Err.Number <> 0 Then
        
            Select Case Err.Number
            
                Case 429
                    Resume Uscita
                    
                Case -2147467259
                
                    MsgBox "Non è stato possibile validare la partita iva" & vbCrLf & "in quanto momentaneamente il servizio non è disponibile.", vbExclamation, "Tabula"
                    
                    bValid = True
                    
                    Resume Uscita
                    
                Case Else
                    MsgBox Err.Description, vbCritical
            
            End Select
            
        End If
        
        Exit Function
     
    End Function

    grazie per eventuali risposte, salve.

    lunedì 18 maggio 2020 14:14

Risposte

  • Per le guid in teoria può anche toglierle proprio, le ho lasciate per abitudine (oltretutto nemmeno tanto “sana”). La dll va registrata nel computer di destinazione, ma non so se xp supporti net standard, se non erro ha necessità di framework > 4 e se non ricordo male xp arriva al 4. In ogni caso il framework standard credo vada più “basso” tipo standard 1, oppure puoi fare la dll direttamente in net e non standard.. Il post elaborazione è solo un consiglio visto che dovrai fare debug, quindi è molto più rapido compilare e provare al posto di dovere occuparsi anche della registrazione, ma ovviamente vale se puoi fare debug nella stessa macchina. Come strumento dovresti utilizzare RegAsm.exe come da righe di comando post elaborazione. Regsvr32 mi sa che era appunto dei vecchi framework.. Per il resto non usando più vb non potrei nemmeno testarlo. Inoltre non ho nemmeno più xp disponibile... quindi dovrai vedere un po’ tu. Ultima cosa: le dll mancanti devono stare nella cartella dentro release, una sotto cartella con la versione di standard, (tipo release\netstandard2.0)
    • Contrassegnato come risposta AngeloF giovedì 21 maggio 2020 15:44
    martedì 19 maggio 2020 09:55

Tutte le risposte

  • Ciao Angelo,

    a quanto pare ci si "rincontra".

    Devi creare una libreria e renderla visibile come oggetto COM.

    Crea un nuovo progetto (ad esempio DLL .Net Standard 2.0), chiamalo ServicePI (poi i nomi li cambi quando inquadri meglio)

    Clicca su "connected services" col tasto destro e scegli "aggiungi servizio connesso" e scegli "Microsoft WCF service reference provider"

    nella finestrella che ti si apre inserisci l'indirizzo "http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl" e sotto al posto di ServiceReference1 metti PIVA.

    A questo punto visual studio ti dovrebbe creare i riferimenti per il servizio con il namespace PIVA, quindi puoi utilizzarlo.

    Ora devi renderlo visibile tramite la decorazione della classe con alcuni attributi, oltre a dover creare le interfacce:

    using Newtonsoft.Json;
    using System;
    using System.Runtime.InteropServices;
    
    namespace ServicePI
    {
        [ComVisible(true)]
        [InterfaceType(ComInterfaceType.InterfaceIsDual)]
        [Guid("3884D59D-AB76-41E7-82B6-21C68DBDCBF3")]
        public interface IClient
        {
            string checkJson(string country = "IT", string PI = "08106710158");
            PIResult checkObject(string country = "IT", string PI = "08106710158");
        }
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.None)]
        [Guid("3884D59D-AB76-41E7-82B6-21C66DBDCBF3")]
        [ProgId("ServicePI.Client")]
        public class Client : IClient
        {
            public string checkJson(string country = "IT", string PI = "08106710158")
            {
                PIVA.checkVatPortTypeClient client = new PIVA.checkVatPortTypeClient();
                client.OpenAsync();
                return JsonConvert.SerializeObject(client.checkVatAsync(new PIVA.checkVatRequest(country, PI)).Result);
            }
            public PIResult checkObject(string country = "IT", string PI = "08106710158")
            {
                return JsonConvert.DeserializeObject<PIResult>(checkJSon(country, PI));
            }
        }
        [ComVisible(true)]
        [InterfaceType(ComInterfaceType.InterfaceIsDual)]
        [Guid("3884D59D-AB76-41E7-82B6-21C76DBDCBF3")]
        public interface IPIResult
        {
            string CountryCode { get; set; }
            string VatNumber { get; set; }
            string RequestDate { get; set; }
            bool Valid { get; set; }
            string Name { get; set; }
            string Address { get; set; }
        }
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.AutoDual)]
        [Guid("CF4EFB82-6EE1-4A84-9CA9-07B135888B68")]
        [ProgId("ServicePI.PIResult")]
        public class PIResult : IPIResult
        {
            public string CountryCode { get; set; }
            public string VatNumber { get; set; }
            public string RequestDate { get; set; }
            public bool Valid { get; set; }
            public string Name { get; set; }
            public string Address { get; set; }
        }
    }

    Ora la devi registrare, quindi è comodo mettere tutto nella riga di comando di post-compilazione.

    Clicca con il tasto destro sul progetto e scegli "proprietà", poi seleziona la scheda "eventi di compilazione" e nella seconda casella (post-compilazione appunto) metti questo:

    %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /tlb /codebase "$(TargetPath)"
    %SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe /tlb /codebase "$(TargetPath)"

    Questo registrerà la tua DLL quando la compili in release. Ovviamente puoi cambiare la versione del framework, in questo caso è "v4.0.30319".

    Ora è possibile che crei qualche rogna perché magari non trova qualche DLL di qualche pacchetto nuget, quindi non dovrai far altro che procurarti le DLL (apri il gestore nuget e cerca i nomi, una volta trovato ed installato ti dovrebbe mettere le DLL nella cartella packages/^nome^ nella radice) che ti segnala e metterle nella cartella release.

    Fatto ciò, io non ho più nulla che abbia a che fare con vb6 da qualche tempo e non ricordo molto ormai, quindi mi limito a farti un esempio con vba eseguito come macro di Office/OpenOffice, testa poi un po tu e dimmi quali problemi trovi:

    Sub Main
    On Error GoTo myError
       Set client =  New ServicePI.Client
       set res = client.checkObject("IT","03660670963") 'questo restituisce un oggetto'  
       MsgBox res.VatNumber & " " & res.Name & " " & res.Address & " " &  res.Valid & " " & res.RequestDate
       'set res = client.checkJson("IT","03660670963") ''questo restituisce in formato json 
       'MsgBox res '
       Exit Sub
     myError:
       MsgBox "Sorry, an unexpected error occurred!"
    End Sub
    • Modificato U 235 martedì 19 maggio 2020 00:27
    martedì 19 maggio 2020 00:17
  • Grazie, farò in questi giorni delle prove e ti farò sapere.

    PS: non ricordo quando ci siamo incontrati l'ultima volta, puoi ricordarmenlo ??

    Saluti

    martedì 19 maggio 2020 07:30
  • Vecchi post... qualcosa che aveva a che fare con WCF FullDuplex.

    Buon Lavoro.

    martedì 19 maggio 2020 07:33
  • Sto facendo qualche prova e mi sono sorti 2 dubbi :

    1. nelle interfacce per gestire il Client al servizio hai messo dei GUID come attributi, nel mio progetto quali devo usare? Li debbo creare con qualche utility e sostituirli a quelli che mi hai fornito ?

    2. Sto creando questa DLL in un computer diverso da quello nel quale ho installato VB6 (qui ho ancora un SO Win XP), servono

    ugualmente gli eventi di post-compilazione ? Visto che devo testare questa DLL in un SO Win XP posso usare tranquillamente come 'framework'

    .NET Standard 2.0 ? Debbo registrare questa DLL in Win XP come le altre DLL , cioè usufruendo del comando 'Regsvr32.....' ?

    Grazie

    martedì 19 maggio 2020 08:01
  • Compilando ricevo questo errore nonostante abbia inserito la dll 'System.Reflection.DispatchProxy' nelle cartelle Debug e Release. Ho provato a cercare la versione 4.0.4.0 ma riesco a trovare altre versioni e l'ultima è la 4.7.0 che è quella che uso .
    martedì 19 maggio 2020 08:34
  • Per le guid in teoria può anche toglierle proprio, le ho lasciate per abitudine (oltretutto nemmeno tanto “sana”). La dll va registrata nel computer di destinazione, ma non so se xp supporti net standard, se non erro ha necessità di framework > 4 e se non ricordo male xp arriva al 4. In ogni caso il framework standard credo vada più “basso” tipo standard 1, oppure puoi fare la dll direttamente in net e non standard.. Il post elaborazione è solo un consiglio visto che dovrai fare debug, quindi è molto più rapido compilare e provare al posto di dovere occuparsi anche della registrazione, ma ovviamente vale se puoi fare debug nella stessa macchina. Come strumento dovresti utilizzare RegAsm.exe come da righe di comando post elaborazione. Regsvr32 mi sa che era appunto dei vecchi framework.. Per il resto non usando più vb non potrei nemmeno testarlo. Inoltre non ho nemmeno più xp disponibile... quindi dovrai vedere un po’ tu. Ultima cosa: le dll mancanti devono stare nella cartella dentro release, una sotto cartella con la versione di standard, (tipo release\netstandard2.0)
    • Contrassegnato come risposta AngeloF giovedì 21 maggio 2020 15:44
    martedì 19 maggio 2020 09:55
  • Grazie, ti faccio sapere, ciao

    martedì 19 maggio 2020 10:52
  • Ciao 👋
    martedì 19 maggio 2020 16:00
  • Ciao,

    Costruendo la DLL con '.NET Standard 2.0' avevo continuamente problemi nella registrazione della DLL con RegAsm.exe,

    sulla base del tuo consiglio e, cioè che in Win XP è installato al max '.NET Framework 4.0' ho scelto di costruire la mia DLL COM

    come 'Libreria di classi .NET Framework' scegliendo come framework di destinazione proprio '.NET Framework 4'.

    Ho seguito più o meno i passi che mi hai indicato : in questo tipo di progetto non compare fra i Servizi Connessi 'Microsoft WCF Web Service Provider', per cui ho scelto 'Aggiungi Riferimento al Servizio', ho valorizzato il campo url con il wsdl, ho valorizzato il campo dello spazio dei nomi, poi andando in avanzate ho spuntato le operazioni asincrone e ho dato l'ok a tutto. Effettivamente mi ha creato un file 'Reference.cs' con le varie classi/interfacce per accedere al Web Service ma, non non ho trovato il metodo CheckVatAsync, mi sono industriato ed ho creato

    delle mi interfacce/classi per gestire il metodo checkVat del file Reference.cs, ho compilato, registrato con RegAsm.exe su XP e l'ho testato il Late Binding e funziona perfettamente.

    Questo è il codice che ho realizzato :

    using srvCheckVAT.pivans;
    using System.Runtime.InteropServices;

    namespace srvCheckVAT
    {

        [Guid("DD213FC4-2E30-4ABC-8532-00F2FF9488F8")]
        [ComVisible(true)]
        [InterfaceType(ComInterfaceType.InterfaceIsDual)]
        public interface IRequest
        {
            string CountryCode { get; set; }
            string VatNumber { get; set; }
        }

        [Guid("38E2C14A-D6ED-42F5-8D17-8E8E2B2798AE")]
        [ComVisible(true)]
        [InterfaceType(ComInterfaceType.InterfaceIsDual)]
        public interface IResponse
        {
            string CountryCode { get; set; }
            string VatNumber { get; set; }
            string RequestDate { get; set; }
            bool Valid { get; set; }
            string Name { get; set; }
            string Address { get; set; }
        }


        [Guid("0D664CB4-FAF3-46C3-A3A3-89484F249A77")]
        [ComVisible(true)]
        [InterfaceType(ComInterfaceType.InterfaceIsDual)]
        public interface IClientN
        {
            [DispId(1)]
            IResponse checkVat(IRequest req);
            //checkVatResponse checkVat(checkVatRequest req);
        }

        [Guid("24E24E83-0A52-46E6-887D-D518C756C584")]
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.None)]
        [ComSourceInterfaces(typeof(IClientN))]
        public class ClientN : IClientN
        {

            public IResponse checkVat(IRequest req)
            {
                checkVatPortTypeClient client = new checkVatPortTypeClient();

                checkVatRequest input = new checkVatRequest(req.CountryCode, req.VatNumber);
                
                checkVatResponse output = client.checkVat2(input);

                IResponse res = new Response()
                {
                    CountryCode = output.countryCode
                    ,VatNumber = output.vatNumber
                    , Address = output.address
                    ,Name = output.name
                    , RequestDate = output.requestDate
                    , Valid = output.valid
                };

                return res;
            }

        }

        [Guid("CFDC9BDF-0BAC-475B-83B9-025C1AFDD6CA")]
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.None)]
        public class Response : IResponse
        {
            public string CountryCode { get; set; }
            public string VatNumber { get; set; }
            public string RequestDate { get; set; }
            public bool Valid { get; set; }
            public string Name { get; set; }
            public string Address { get; set; }
        }

        [Guid("A72E630E-0D8C-4268-AB15-45EB816C3615")]
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.None)]
        public class Request : IRequest
        {
            public string CountryCode { get; set; }
            public string VatNumber { get; set; }
        }

    }

    Questo il Client VB6 per testarlo :

                Private Function ConvalidaVAT(ByVal sPaese As String, ByVal sVat As String) As Boolean

                    On Error GoTo Uscita
                
                    'Dim objServiceClient            As srvCheckVAT.ClientN
                    'Dim objReq                      As srvCheckVAT.Request
                    'Dim objRes                      As srvCheckVAT.Response
                
                    Dim objServiceClient                As Object
                    Dim objReq                              As Object
                    Dim objRes                              As Object

                    Set objServiceClient = CreateObject("srvCheckVAT.ClientN")
                    Set objReq = CreateObject("srvCheckVAT.Request")

                    objReq.CountryCode = "IT"
                    objReq.VatNumber = "03660670963"

                    Set objRes = objServiceClient.checkVat(objReq)

                    MsgBox "VAT Number : " & objRes.VatNumber & vbCrLf & "Azienda : " & objRes.Name & vbCrLf & "Indirizzo : " & objRes.Address & vbCrLf & "Valido : " & objRes.Valid & vbCrLf & "Data richiesta : " & Format(objRes.RequestDate, "dd/mm/yyyy")

                    ConvalidaVAT = True

                    Exit Function
                    
                Uscita:
                    MsgBox "Errore!" + vbCrLf + Err.Description

                    Exit Function
                    
                End Function

    Grazie come sempre dell'aiuto. Alla prossima.

    giovedì 21 maggio 2020 15:44
  • Ciao,

    mi fa molto piacere che abbia risolto.

    Grazie per aver condiviso la soluzione finale.

    Alla prossima!

    giovedì 21 maggio 2020 17:59
  • A titolo informativo :

    mi è venuta in mente questa soluzione che però devo testare ancora su vari SO, perchè la soluzione VB6 che usavamo

    e che ti propongo, da qualche settimana dava errore :

    Public Function CheckValidVat(ByVal sPaese As String, ByVal sVat As String, dData, bValid, sDenominazione, sIndirizzo, bManaged) As Boolean
        
        'MODIFICA AF, 12102017, Funzione che verifica tramite WebService VIES se una Partita IVA Europea è cessata/valida oppure no
        'Nota: Funzione presente in KngAnagrafiche.FunzioniAnagrafica.bas e in KngBaseClasses.RoutineGenerali.bas
        'Input
        'Dim sPaese                  As String
        'Dim sPIVA                   As String
        
        'Output
        'Dim dData                   As Date     'Data
        'Dim bValid                  As Boolean  'Valid
        'Dim sDenom                  As String   'Ragione Sociale
        'Dim sAddress                As String   'Indirizzo
        
        Dim SoapObj                 As Object
        
        Const sUrlWsdl              As String = "http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl"
        
        Screen.MousePointer = vbHourglass
        
        CheckValidVat = False
        
        If Len(Convalida(sPaese)) < 2 Then GoTo Uscita
        If Len(Convalida(sVat)) = 0 Then GoTo Uscita
        
        'MODIFICA AF, 08052020, Temporaneamente bypassiamo i controlli, fino a risposta VIES
        bValid = True: CheckValidVat = True: Exit Function
        'MODIFICA FINE
        
        'Se Partita IVA Fittizia bypassiamo i controlli
        If sPaese = "OO" And Trim(sVat) = String(11, "9") Then
            bValid = True: CheckValidVat = True: Exit Function
        End If
        
        On Error GoTo Errore
        
        Set SoapObj = CreateObject("MSSOAP.SoapClient30")
            
        SoapObj.MSSoapInit (sUrlWsdl)
        
        Call SoapObj.CheckVat(sPaese, sVat, dData, bValid, sDenominazione, sIndirizzo)
        
        'MsgBox "Valid VAT = " & CStr(bValid) & vbCrLf & "Name VAT = " & sDenom & vbCrLf & "Address VAT = " & sAddress, vbInformation
        
    Uscita:
        
        bManaged = True
        
        CheckValidVat = True
        
        Screen.MousePointer = vbDefault
        
        Exit Function

    Errore:
        
        Screen.MousePointer = vbDefault
        
        If Err.Number <> 0 Then
        
            Select Case Err.Number
            
                Case 429
                    Resume Uscita
                    
                Case -2147467259
                
                    MsgBox "Non è stato possibile validare la partita iva" & vbCrLf & "in quanto momentaneamente il servizio non è disponibile.", vbExclamation, "Tabula"
                    
                    bValid = True
                    
                    Resume Uscita
                    
                Case Else
                    MsgBox Err.Description, vbCritical
            
            End Select
            
        End If
        
        Exit Function

    End Function

    Come vedi in questa funzione adoperavo l'oggetto "MSSOAP.SoapClient30" in Late Binding che stranamente ha cominciato a dare errore per richieste che partivano da alcuni SO come Win Server 2012 ecc.

    A te viene in mente qualcosa in merito, così senza impegno ??

    Grazie


    venerdì 22 maggio 2020 08:08
  • Ciao

    ti da errore solo su alcuni server e su altri no? Che errore restituisce? Inoltre sei certo che l'errore sia restituito a livello di comunicazione e che la richiesta verso il webservice avvenga?

    hai provato a chiamare checkVat con due soli parametri e recuperare il risultato dal return della funzione?

    venerdì 22 maggio 2020 14:06