CURL e WebClient

di il
18 risposte

CURL e WebClient

E' il mio primo intervento quindi chiedo scusa se sbaglio qualcosa. Devo replicare una serie di comandi CURL in VB.NET. Per adesso ho gestito bene le CURL PUT, usando UploadData e i vari Headers.Add necessari.
Adesso devo gestire una DELETE e non so come. Il comando è di questo tipo:

curl -X DELETE "https://api.be-in.it/api/utenti/100" -H "accept: */*" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ"

Qualcuno ha una dritta?

18 Risposte

  • Re: CURL e WebClient

    Mi sbaglierò, ma non basta usare il metodo della classe HttpClient?
  • Re: CURL e WebClient

    In effetti credo di sì, spero ancora però di cavarmela nell'ambito della classe WebClient, anche perché ho già cominciato a implementare una classe derivata per gestire l'interfaccia con un server specifico. Sono stato indeciso se partire con l'una o con l'altra, poi ho deciso la WebClient per una serie di ragioni, più che altro perché mi pareva più semplice per le mie necessità.
    Magari cambio. Grazie.
  • Re: CURL e WebClient

    Mi studierò la HttpClient, in effetti è anche consigliato. Volendo fare in fretta si fa peggio, ormai dovrei averlo imparato!
  • Re: CURL e WebClient

    Antonio_S_54 ha scritto:


    ho deciso la WebClient per una serie di ragioni, più che altro perché mi pareva più semplice per le mie necessità.
    In fondo, fai chiamate HTTP, quindi non ci vedo nulla di male nell'uso di HttpClient.
  • Re: CURL e WebClient

    Giusto per la cronaca, ho riscritto la mia classe usando la HttpClient, dove effettivamente l'operazione di delete è banale. Però i metodi sono tutti asincroni, e con le funzioni asincrone si lavora male. Le funzioni restituiscono sempre Task, e se uno vuole ottenere un valore di ritorno (tipo un numero di record o anche un semplice flag di ok tutto bene) deve prevedere una variabile apposita, public o incapsulata che sia.
    Poi il costruttore di una classe non può essere il solito New trasparente perché non può contenere chiamate a metodi o funzioni asincrone, quindi bisogna prevedere un metodo di inizializzazione con altro nome.
    Oppure ho capito male?

    In ogni caso mi va bene aver fatto il lavoro, tutta esperienza. Grazie Alka.
  • Re: CURL e WebClient

    Antonio_S_54 ha scritto:


    Però i metodi sono tutti asincroni, e con le funzioni asincrone si lavora male.
    Per molti è il modo corretto di lavorare oggi, tutt'altro che "male".

    Antonio_S_54 ha scritto:


    Le funzioni restituiscono sempre Task, e se uno vuole ottenere un valore di ritorno (tipo un numero di record o anche un semplice flag di ok tutto bene) deve prevedere una variabile apposita, public o incapsulata che sia.
    Non è necessario, perché puoi tranquillamente accedere al valore restituito dal Task, ossia al Result, e tutto torna come prima.

    Meglio ancora però lavorare con le estensioni del linguaggio per la programma asincrona e usare le parole chiave async/await.

    Antonio_S_54 ha scritto:


    Poi il costruttore di una classe non può essere il solito New trasparente perché non può contenere chiamate a metodi o funzioni asincrone, quindi bisogna prevedere un metodo di inizializzazione con altro nome.
    Oppure ho capito male?
    Non ho capito bene a cosa ti riferisci. Io darei prima un'occhiata ai link indicati sopra, poi eventualmente in caso di "dubbi residui", posta anche il codice così c'è qualcosa a cui fare riferimento.

    Ciao!
  • Re: CURL e WebClient

    Grazie, ho visto per le funzioni Task, mi era sfuggito il Return imperativo, dichiarando AS Task(of .....). Quindi questo problema si risolve.
    Per async e await le ho già usate, spero bene.
    Infine per il New, la mia classe eredita HttpClient, e quando istanzio un oggetto devo andare a chiedere un Token di autenticazione, per cui devo fare una Post. Essendo il metodo asincrono non lo posso fare. Per cui ho creato la funzione Initiazlize, che chiamo dopo aver istanziato l'oggetto.
  • Re: CURL e WebClient

    Antonio_S_54 ha scritto:


    la mia classe eredita HttpClient, e quando istanzio un oggetto devo andare a chiedere un Token di autenticazione, per cui devo fare una Post.
    Mi sembra una cattiva idea: la tua logica di business si articola sulla chiamata ai metodi di un oggetto HttpClient, quindi estendere la classe di fatto non ti da nessun vantaggio particolare se non legarti eccessivamente a una gerarchia di oggetti.

    In questi casi, meglio utilizzare la composizione, ossia creare una nuova classe che implementa i servizi di cui si ha bisogno e che, al proprio interno, crea una istanza di HttpClient per gestire le chiamate HTTP previste dalla logica.

    In sintesi, è una implementazione all'incirca del pattern Adapter.

    Antonio_S_54 ha scritto:


    Essendo il metodo asincrono non lo posso fare.
    Per forza: il costruttore ha l'obiettivo di inizializzare un oggetto per il successivo utilizzo, ovvero impostare il valore iniziale dei campi e predisporre l'istanza per la successiva chiamata dei metodi che offre. In questo contesto, andare a fare delle chiamate HTTP all'interno di un costruttore è un serio problema di "bad design" a livello di OOP, tant'è vero che ti ostacola con questi impedimenti pratici ma anche sensati e comprensibili.

    Antonio_S_54 ha scritto:


    Metto il codice della classe, se qualcuno vede delle ingenuità.
    Aarg! Formatta il codice usando l'apposito pulsante qui sopra, altrimenti non si riesce a leggere nulla del codice.
    Tra l'altro, meglio limitarsi alle sue parti significative in base all'aspetto su cui ci si vuole concentrare.

    Ciao!
  • Re: CURL e WebClient

    Come faccio a formattare il codice?
  • Re: CURL e WebClient

    
    Imports System.Text
    Imports Newtonsoft.Json
    Imports System.Net.Http
    
    Public Class HttpClientBein
            Inherits HttpClient
            Public IsSuccesfull As Boolean
            Private strTemp As String
            
            Public Async Function Initialize(strUser As String, strPsw As String) As Task
                Try
                    BaseAddress = New Uri("https://api.be-in.it/api/")
                    strTemp = "username=" & strUser & "&password=" & strPsw
                    Using contentPost As HttpContent = New StringContent(strTemp, Encoding.ASCII, "application/x-www-form-urlencoded")
                        Using response As HttpResponseMessage = Await PostAsync("userLogin", contentPost)
                            If response.IsSuccessStatusCode Then
                                strTemp = Await response.Content.ReadAsStringAsync()
                                Dim jsnResult = Linq.JObject.Parse(strTemp)
                                strTemp = jsnResult.Item("access_token").ToString
                                DefaultRequestHeaders.Add("Authorization", "Bearer " & strTemp)
                                IsSuccesfull = True
                            End If
                        End Using
                    End Using
                Catch ex As Exception
                    IsSuccesfull = False
                End Try
            End Function
            
            Public Async Function InsCondominio(strName As String, strAddr As String, strCity As String, strProv As String, intZip As Integer) As Task(Of Integer)
                Dim intKeyId As Integer = 0
                IsSuccesfull = False
                Try
                    Dim Condominio As New Condomini
                    With Condominio
                        .code = 0
                        .comp_name = strName
                        .address = strAddr
                        .city = strCity
                        .provincia = strProv
                        .zip = intZip
                    End With
                    strTemp = JsonConvert.SerializeObject(Condominio)
                    Using contentPost As HttpContent = New StringContent(strTemp, Encoding.ASCII, "application/json")
                        Using response As HttpResponseMessage = Await PostAsync("condomini", contentPost)
                            If response.IsSuccessStatusCode Then
                                strTemp = Await response.Content.ReadAsStringAsync()
                                Dim jsnResult = Linq.JObject.Parse(strTemp)
                                intKeyId = Integer.Parse(jsnResult.Item("code"))
                                IsSuccesfull = True
                            End If
                        End Using
                    End Using
                    Condominio = Nothing
                    Return intKeyId
                Catch ex As Exception
                    Return 0
                End Try
            End Function
            
            Public Async Function InsAbitante(strName As String, strFamily As String, strAddr As String, strCodF As String, intCond As Integer, intId As Integer) As Task(Of Integer)
                Dim intKeyId As Integer = 0
                IsSuccesfull = False
                Try
                    Dim Abitante As New Abitanti
                    With Abitante
                        .id = intId
                        .name = strName
                        .familyname = strFamily
                        .address = strAddr
                        .fiscalnumber = strCodF
                        .code_condominio = intCond
                    End With
                    strTemp = JsonConvert.SerializeObject(Abitante)
                    Using contentPost As HttpContent = New StringContent(strTemp, Encoding.ASCII, "application/json")
                        strTemp = "utenti" & IIf(intId = 0, "", "/" & intId)
                        Using response As HttpResponseMessage = Await PostAsync(strTemp, contentPost)
                            If response.IsSuccessStatusCode Then
                                strTemp = Await response.Content.ReadAsStringAsync()
                                Dim jsnResult = Linq.JObject.Parse(strTemp)
                                intKeyId = Integer.Parse(jsnResult.Item("id"))
                                IsSuccesfull = True
                            End If
                        End Using
                    End Using
                    Abitante = Nothing
                    Return intKeyId
                Catch ex As Exception
                    Return 0
                End Try
            End Function
            
            Public Async Function DelAbitante(intId As Integer) As Task(Of Integer)
                Dim intKeyId As Integer = 0
                IsSuccesfull = False
                Try
                    Using response As HttpResponseMessage = Await DeleteAsync("utenti/" & intId)
                        If response.IsSuccessStatusCode Then
                            intKeyId = intId
                            IsSuccesfull = True
                        End If
                    End Using
                    Return intKeyId
                Catch ex As Exception
                    Return 0
                End Try
            End Function
            
            Private Class Condomini
                Public code As Integer
                Public comp_name As String
                Public address As String
                Public city As String
                Public provincia As String
                Public zip As Integer
            End Class
            
            Private Class Abitanti
                Public id As Integer
                Public name As String
                Public familyname As String
                Public address As String
                Public fiscalnumber As String
                Public code_condominio As Integer
            End Class
        End Class
        
  • Re: CURL e WebClient

    Sono riuscito

    Ecco l'istanziazione

    Dim wbBein = New HttpClientBein
    Await wbBein.Initialize("USER", "password")

    Ecco un inserimento di un record tramite POST

    intPostCodeIns = Await wbBein.InsCondominio(rdrDb("STAdescri"), rdrDb("STAindiri"), rdrDb("STAcitind"), rdrDb("STAproind"), rdrDb("STAcapind"))

    dove rdrDb è un reader

    Direi che è semplice da usare. Ho usato per altre classi la composizione, in questo caso mi pareva che una classe ereditata fosse la soluzione più elegante. Quali inconvenienti vedi?
  • Re: CURL e WebClient

    Antonio_S_54 ha scritto:


    Direi che è semplice da usare. Ho usato per altre classi la composizione, in questo caso mi pareva che una classe ereditata fosse la soluzione più elegante. Quali inconvenienti vedi?
    Dal punto di vista del "funzionare", inconvenienti non ce ne sono.

    La problematica è solo nel fatto che ereditare una classe è una scelta più "stringente" rispetto a quella di utilizzarla semplicemente istanziandola. Una modifica nella classe da cui derivi può avere ripercussioni dirette sulla tua, poiché sono strettamente legate.

    Tra l'altro, dal punto di vista del "design", a mio parere non è corretto che chi usa la tua classe - che è quella che dovrebbe fornire i metodi per interfacciarsi col servizio esposto via HTTP - possa richiamare metodi che nulla hanno a che vedere con questa interazione: in pratica, avendo ereditato da HttpClient, oltre ai metodi che hai aggiunto posso comunque invocare potenzialmente tutti i metodi ereditati da HttpClient, e quindi mandare comandi HTTP al server o alterare lo stato del componente affinché i tuoi metodi non funzionino più come si deve, questo perché nel contesto di cui stiamo parlando, quei metodi dovrebbero idealmente essere privati.

    Ciao!
  • Re: CURL e WebClient

    Tra l'altro, dal punto di vista del "design", a mio parere non è corretto che chi usa la tua classe - che è quella che dovrebbe fornire i metodi per interfacciarsi col servizio esposto via HTTP - possa richiamare metodi che nulla hanno a che vedere con questa interazione: in pratica, avendo ereditato da HttpClient, oltre ai metodi che hai aggiunto posso comunque invocare potenzialmente tutti i metodi ereditati da HttpClient, e quindi mandare comandi HTTP al server o alterare lo stato del componente affinché i tuoi metodi non funzionino più come si deve, questo perché nel contesto di cui stiamo parlando, quei metodi dovrebbero idealmente essere privati.
    Su questo hai sicuramente ragione. Oggi ormai non posso più, domattina provo a cambiare vediamo quello che viene fuori!

    Grazie per ora. Si è sempre in tempo a imparare, anche alla mia età!!! Ciao.
  • Re: CURL e WebClient

    Ecco la mia nuova classe "composta". Ho lasciato la gestione di un'unico tipo record per semplificare. Grazie in anticipo per eventuali osservazioni migliorative.
    
    Imports System.Text
    Imports Newtonsoft.Json
    Imports System.Net.Http
    Module Module1
    
        Public Class HttpClientBein
            Implements IDisposable
            Public IsSuccesfull As Boolean
            Private HttpC As New HttpClient
            Private strTemp As String
            
            Public Sub Dispose() Implements IDisposable.Dispose
                HttpC = Nothing
            End Sub
            
            Public Async Function Initialize(strUser As String, strPsw As String) As Task
                Try
                    HttpC.BaseAddress = New Uri("https://api.be-in.it/api/")
                    strTemp = "username=" & strUser & "&password=" & strPsw
                    Using contentPost As HttpContent = New StringContent(strTemp, Encoding.ASCII, "application/x-www-form-urlencoded")
                        Using response As HttpResponseMessage = Await HttpC.PostAsync("userLogin", contentPost)
                            If response.IsSuccessStatusCode Then
                                strTemp = Await response.Content.ReadAsStringAsync()
                                Dim jsnResult = Linq.JObject.Parse(strTemp)
                                strTemp = jsnResult.Item("access_token").ToString
                                HttpC.DefaultRequestHeaders.Add("Authorization", "Bearer " & strTemp)
                                IsSuccesfull = True
                            End If
                        End Using
                    End Using
                Catch ex As Exception
                    IsSuccesfull = False
                End Try
            End Function
    
            Public Async Function InsCondominio(strName As String, strAddr As String, strCity As String, strProv As String, intZip As Integer) As Task(Of Integer)
                Dim intKeyId As Integer = 0
                IsSuccesfull = False
                Try
                    Dim Condominio As New Condomini
                    With Condominio
                        .code = 0
                        .comp_name = strName
                        .address = strAddr
                        .city = strCity
                        .provincia = strProv
                        .zip = intZip
                    End With
                    strTemp = JsonConvert.SerializeObject(Condominio)
                    Using contentPost As HttpContent = New StringContent(strTemp, Encoding.ASCII, "application/json")
                        Using response As HttpResponseMessage = Await HttpC.PostAsync("condomini", contentPost)
                            If response.IsSuccessStatusCode Then
                                strTemp = Await response.Content.ReadAsStringAsync()
                                Dim jsnResult = Linq.JObject.Parse(strTemp)
                                intKeyId = Integer.Parse(jsnResult.Item("code"))
                                IsSuccesfull = True
                            End If
                        End Using
                    End Using
                    Condominio = Nothing
                    Return intKeyId
                Catch ex As Exception
                    Return 0
                End Try
            End Function
    
            Private Class Condomini
                Public code As Integer
                Public comp_name As String
                Public address As String
                Public city As String
                Public provincia As String
                Public zip As Integer
            End Class
    
        End Class
    
    End Module
    
Devi accedere o registrarti per scrivere nel forum
18 risposte