C# Creazione classe e metodo

sabato 01 febbraio 2014 - 12.21
Tag Elenco Tags  C#

Aron Profilo | Newbie

Salve a tutti, sono abbastanza nuovo della programmazione in C# e Net, sto realizzando una piccola applicazione per testare un servizio web creato da me e vorrei una piccola delucidazione sulla gestione di un metodo.

Mi spiego meglio:

Effettuo una connessione al mio servizio tramite restsharp che mi restituisce una stringa con il contenuto della richiesta, il codice è il seguente:

RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); client.ExecuteAsync(request, response => { tbktest.Text = response.Content; });

Fin qui tutto bene, ottengo esattamente una stringa e la visualizzo nel mio TextBlock.

Ora per migliorare la leggibilità onde evitare di fare ogni volta la connessione, vorrei creare una classe che esponga un metodo che mi restituisce la stringa ottenuta in modo da utilizzarla nella mia classe principale.

Qualcuno potrebbe darmi qualche dritta?

Grazie a tutti!

--------------------Aggiornamento---------------------

Nel frattempo nel cercare di trovare una soluzione ho fatto questa prova:

Ho creato una nuova classe in questo modo:

class Connessione { public string Get() { string j = string.Empty; RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); client.ExecuteAsync(request, response => { j = response.Content; }); return j; } }

Nella classe principale ho fatto la chiamata:

Connessione prova = new Connessione(); tbktest.Text = prova.Get();

Il codice non da errori, ma non mi viene restiruito nulla, cosa mi sto perdendo?

Grazie ancora

0v3rCl0ck Profilo | Guru

ciao, quel metodo "ExecuteAsync" ritorna un Task o accetta soltando una callback?


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Non saprei dirti, l'ho trovato seguendo una guida su un testo, so che viene chiamato anonymous method che definisce l'evento callback inline.

L'alternativa sarebbe quella di creare un metodo callback apparte del tipo:

private void Callback (RestResponse restResponse)

Qualcuno nel frattempo ha qualche suggerimento per la domanda iniziale?

0v3rCl0ck Profilo | Guru

>Non saprei dirti, l'ho trovato seguendo una guida su un testo,
>so che viene chiamato anonymous method che definisce l'evento
>callback inline.

era per capire che tipo di supporto async ti da quella libreria che stai usando, ci sono diverse soluzioni, vorrei solo indicarti l'indicazione più corretta per il tuo caso.

Stai utilizzando questa libreria http://restsharp.org/ ?

ritornando al tuo codice se ritorni la variabile "j" in quel modo, e dato che è un operazione asincrona, sicuramente appena la leggi sarà vuota, perchè non sai quando la chiamata viene conclusa... se facessi un attesa prima di leggere la variabile probabilmente la troveresti valorizzata, ma non è il procedimento corretto e tanto meno elegante. Devi riuscire a sincronizzarti al metodo, e ci sono diversi modi.

una soluzione è quella di trasformare anche il tuo metodo in async, sfruttando la task programming, che è uno dei metodi più eleganti per costruire operazioni asincrone ad oggi:

void Main() { tbktest.Text = GetAsync().Result; } anche così (indispensabile su windows forms/wpf per ritornare su thread principale della gui): async void Main() { tbktest.Text = await GetAsync(); } // Define other methods and classes here public Task<string> GetAsync() { var tcs = new TaskCompletionSource<string>(); string j = string.Empty; RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); client.ExecuteAsync(request, response => { tcs.SetResult(response.Content); }); return tcs.Task; }

in pratica il TaskCompletionSource ti permette di trasformare il metodo executeasync che non ritorna task di suo, ma che accetta solo un delegato come callback, in un metodo che ritorna un task, che è molto più controllabile, e ti permette anche di sfruttare le nuove keyword async/await:

http://msdn.microsoft.com/en-us/library/hh191443.aspx


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Salve 0v3rCl0ck e grazie della risposta.

Si come indicato nel primo 3d sto utilizzando restsharp su visual studio 2013 per wp8.

Ora vedo di leggermi qualcosa riguardo la task programming e provare ad implementare la tua soluzione, potresti cortesemente spiegarmi l'esistenza dei 2 main?

Io ho il main di default:

public MainPage() { InitializeComponent(); }

dove effettuavo la chiamata.

Ora devo mantenere entrambi i main come hai scritto tu o devo sostituire il main di default con quello async?

------------------------------------------------
Altro piccolo dubbio:

In attesa di una risposta qui sol forum ho provato a fare alcune prove eliminando la classe Connessione e gestendo il mio servizio all'interno del main in questo modo:

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

La mia classe Dati è cosi:

namespace Test { public class Dati { [JsonProperty("nome")] public static string Nome { get; set; } [JsonProperty("stato")] public static string Stato { get; set; } } }

Quindi in pratica acquisisco i dati dal mio servizio in formato json, li deserializzo per popolare la mia classe dati e poi accedo alle proprietà della classe Dati e le metto nei textblock.
All'interno del Main tutto funziona correttamente, infatti visualizzo il nome presente nel json dentro il TextBlock tbkNome, per testare poi il controllo nel bottone all'interno del mio servizio esterno cambio la variabile Nome e facendo un piccolo controllo sul browser verifico che effettivamente la variabile sia cambiata ed è cosi, mentre invece quando esegueo il click sul bottone mi viene riempito solo il campo tbkStato e tbkNome rimane invariato.

In pratica non aggiorna il contenuto delle proprità all'interno della classe Dati, questo è dovuto sempre ad una questione di sincronizzazione o sto sbagliando io qualcosa nel popolare la mia classe?

Grazie ancora e scusa se mi son dilungato molto, ma volevo cercare di essere più chiaro possibile :)

0v3rCl0ck Profilo | Guru

>Salve 0v3rCl0ck e grazie della risposta.
>
>Si come indicato nel primo 3d sto utilizzando restsharp su visual
>studio 2013 per wp8.

si scusami non avevo letto bene il 3d, usi restsharp e così intanto ho scoperto come mai non ti da eccezione la callback nell'impostare la textbox, perchè guardando il codice di restsharp ho notato che sfruttano syncronization context, e lo abilitano di default per windows phone, ed è solo per questo che non ti da errore, altrimenti devi sapere che una normale esecuzione asincrona ti chiamerebbe il delegato/callback su un altro thread parallelo a quello principale, e appena tenti di impostare qualsiasi cosa sia legata alla GUI, ti da eccezione perchè sulla gui non è previsto l'accesso asincrono, ma ogni comando diretto alla gui deve essere smistato da un solo thread.

>
>Ora vedo di leggermi qualcosa riguardo la task programming e
>provare ad implementare la tua soluzione, potresti cortesemente
>spiegarmi l'esistenza dei 2 main?

i due main non c'entrano con il tuo programma, me li sono fatti per provare in un progetto console, il succo della questione sta nel fatto che se vuoi creare un metodo che al suo interno chiami una funzione asincrona, hai due possibilità:

1 - creare il metodo a sua volta asincrono, per mantenere lo stesso flusso di esecuzione, e fare capire a chi chiama il metodo che si deve aspettare un esecuzione asincrona, per cui dovrà sapere come sincronizzarsi ad esso, o con i task o con un delegato di callback o anche con eventi (se invece che un metodo fosse una classe intera, vedi il backgroundWorker che lavora ad eventi)

2 - creare il metodo sincrono, ma anche qui rispettando il flusso che ci si aspetta da un metodo sincrono, e cioè al termine dell'esecuzione mi deve garantire che il risultato sia pronto e leggibile, e per questo dovresti bloccare l'esecuzione del thread corrente, aspettando la risposta dal RestRequest, a questo punto sfruttando la chiamata sincrona Execute invece che ExecuteAsync, oppure sincronizzando sul thread corrente l'ExecuteAsync.

ovviamente nel tuo caso di wp8 hai optato per l'esecuzione asincrona, e hai fatto bene, perchè se non sbaglio anche su wp8 come per le store app di win8, l'esecuzione delle applicazioni è controllato, e non è possibile bloccare il thread principale per più di x secondi, altrimenti l'applicazione viene killata dal sistema operativo.

Ho controllato meglio RestSharp e ha anche l'interfaccia a task, quindi vediamo di sfruttare quella...

Detto questo vediamo di ripartire dal metodo asincrono che volevi creare per potere riutilizzare parti di codice:

public class Connessione { public async Task<Dati> GetAsync() { RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); var response = await client.ExecuteTaskAsync(request); Dati dati = JsonConvert.DeserializeObject<Dati>(response.Content); return dati; } }

nel metodo ExecuteTaskAsync i ragazzi della RestSharp, hanno già implementato quello che ti avevo postato precedentemente, facendo in modo di ritornare un Task, che poi ti da la possibilità di utilizzare async/await, che sono comodissimi per sincronizzarsi all'esecuzione di codice asincrono, perchè come vedi, in pratica, il codice a prima vista non cambia praticamente niente da un codice sincrono, se non che devi aggiungere async alla dichiarazione del metodo e await davanti ai metodi che lanci. Poi ovviamente ci sono importanti considerazioni che stanno alla base di tutto questo, ma ti invito a leggere un po' di documentazione sulla task programming sull'msdn.

Una volta creato il tuo metodo async è possibile richiamarlo esattamente come abbiamo fatto per ExecuteTaskAsync (sui tuoi metodi non aggiungere Task, la naming convention di default dice di aggiungere solo Async in fondo ai metodi, loro hanno dovuto aggiungere TaskAsync, per retrocompatibilità del loro stesso codice dove avevano già un interfaccia che ritornava Async però chiedendo il delegato invece che tornare il Task):

var connessione = new Connessione(); var dati = await connessione.GetAsync(); tbkNome.Text = dati.Nome; tbkStato.Text = dati.Stato;

poi dato che questo codice da quello che ho capito devi lanciarlo sia in apertura della form che successivamente alla pressione di un pulsante, tanto vale crearci un metodo (sempre async) in comune per entrambi i caricamenti:

public async Task LoadDataAsync() { var connessione = new Connessione(); var dati = await connessione.GetAsync(); tbkNome.Text = dati.Nome; tbkStato.Text = dati.Stato; }

che poi verrà chiamato all'interno del comando lanciato dal pulsante:

private async void Button_Click(object sender, RoutedEventArgs e) { await LoadDataAsync(); }

e nel costruttore, facendo particolare attenzione a salvarsi da parte un riferimento al task di inizializzazione, che potrebbe servire a chi crea la form/window, per sincronizzarsi al caricamento dei dati della form stessa:

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

infine ti allego il codice per intero:

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

>private void btStatoDisp_Click(object sender, RoutedEventArgs
>e)
> {
>RestRequest request = new RestRequest(url servizio);
> request.Method = Method.GET;
>
> RestClient client = new RestClient();
> client.ExecuteAsync(request, response =>
> {
>
>Dati dati = JsonConvert.DeserializeObject<Dati>(response.Content);
> tbkNome.Text = Dati.Nome;
>
> });
>
> tbkStato.Text = Dati.Stato;
> }
>

qui sbagli perchè "tbkStato.Text = Dati.Stato;" deve rimanere dentro alla callback, altrimenti dati, non sarà valorizzato subito, sempre per il discorso dell'asincronia dell'esecuzione. Inoltre non devi usare le statiche sulle proprietà di Dati, devi leggere dall'oggetto creato dal deserializzatore:

client.ExecuteAsync(request, response => { Dati dati = JsonConvert.DeserializeObject<Dati>(response.Content); tbkNome.Text = dati.Nome; tbkStato.Text = dati.Stato; });

>La mia classe Dati è cosi:
>
>
>namespace Test
>{
> public class Dati
> {
>
> [JsonProperty("nome")]
> public static string Nome { get; set; }
>
> [JsonProperty("stato")]
> public static string Stato { get; set; }
> }
>}
>

non fare mai proprietà static sugli oggetti che rappresentano entità, perchè altrimenti non riesci ad istanziarle, di fatto quell'oggetto così com'è, quando è istanziato, creerebbe un oggetto vuoto, perchè la definizione della classe contiene solo 2 proprietà statiche, e nemmeno una non statica, statica vuol dire che ne esiste una per tutta la durata dell'applicazione, e non va bene per quello che devi fare, quindi la classe dovrà essere come quella che ti ho postato sopra:

public class Dati { [JsonProperty("nome")] public string Nome { get; set; } [JsonProperty("stato")] public string Stato { get; set; } }

un ultimo appunto... restsharp prevede anche di serializzare e deserializzare al posto tuo, e di recente ho letto che hanno tolto nelle ultime versioni, la dipendenza su json.net, che toglie la possibilità di utilizzare alcuni attributi di serializzazione, ma embedda dentro di se un serializzatore snello e sopratutto integrato che ti permette di avere questo:

public class Connessione { public async Task<Dati> GetAsync() { RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); var response = await client.ExecuteTaskAsync<Dati>(request); Dati dati = response.Data; return dati; } } public class Dati { [DeserializeAs(Name = "nome")] public string Nome { get; set; } [DeserializeAs(Name = "stato")] public string Stato { get; set; } }

in pratica non devi fare te la serializzazione o deserializzazione a mano, ma la fa dirattamente restsharp per te, ma non sfruttando più la libreria json.net, non ti da più la possibilità di utilizzare gli attributi come JsonProperty, ma ne ha soltanto uno che è DeserializeAs che prende solo due proprietà tra cui Name, per potere cambiare nome come facevi tu, quindi nel tuo caso è più che sufficiente e potresti togliere la dipendenza a json.net dal tuo progetto, a meno che proprio non ti serva per particolari cose o perchè ti piace e basta :) e puoi comunque utilizzarlo sostituendo il default*serializer* di restsharp come spiegato nel readme:

*** IMPORTANT CHANGE IN RESTSHARP VERSION 103 ***

In 103.0, JSON.NET was removed as a dependency.

If this is still installed in your project and no other libraries depend on
it you may remove it from your installed packages.

There is one breaking change: the default Json*Serializer* is no longer
compatible with Json.NET. To use Json.NET for serialization, copy the code
from https://github.com/restsharp/RestSharp/blob/86b31f9adf049d7fb821de8279154f41a17b36f7/RestSharp/Serializers/JsonSerializer.cs
and register it with your client:

var client = new RestClient();
client.JsonSerializer = new YourCustomSerializer();

The default Json*Deserializer* is mostly compatible, but it does not support
all features which Json.NET has (like the ability to support a custom [JsonConverter]
by decorating a certain property with an attribute). If you need these features, you
must take care of the deserialization yourself to get it working.

If you run into any compatibility issues with deserialization,
please report it to http://groups.google.com/group/restsharp


Spero di averti dato tutti gli elementi per proseguire bene con il tuo lavoro, fammi sapere se hai altri dubbi.

ciao,
Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Wow mi hai dato un sacco di risposte e materiale su cui lavorare questo pomeriggio :)

Innanzitutto ti ringrazio per la disponibilità, in effetti non mi era tanto chiara la questione di restsharp con il jason.net, ma grazie a te ora ho le idee un pò più chiare ^^

Il json.net oltre che per deserializzare lo stavo usando anche per accedere direttamente ad una particolare variabile del json del servizio, ossia utilizzando questo codice

JObject json =JObject.Parse(response.Content) txtText.Text = json ["name"].ToString();

Ed anche questo il motivo, del JsonProperty, perchè il nome doveva coincidere con quello presente nel json.

Ma credo che seguendo i tuoi consigli e popolando correttamente la mia classe e aggiornando le sue proprietà correttamente posso anche fare a meno di quella funzionalità.

Ti ringrazio nuovamente! Confido nello spuntare la casella Accetta entro sera :)

0v3rCl0ck Profilo | Guru

>JObject json =JObject.Parse(response.Content)
>txtText.Text = json ["name"].ToString();
>
>
>Ed anche questo il motivo, del JsonProperty, perchè il nome doveva
>coincidere con quello presente nel json.
>
>Ma credo che seguendo i tuoi consigli e popolando correttamente
>la mia classe e aggiornando le sue proprietà correttamente posso
>anche fare a meno di quella funzionalità.

assolutamente d'accordo, dovresti il più possibile sfruttare delle belle entità chiare, come appunto la classe Dati, perchè il tutto diventa molto più pulito (e object-oriented), ed eviti anche errori di scrittura ["nameasd"] (da errore a runtime), dato che hai il compilatore che poi ti viene in aiuto dati.Nameasd da errore in compilazione :)

>
>Ti ringrazio nuovamente! Confido nello spuntare la casella Accetta
>entro sera :)

di nulla, sono felice di averti chiarito un po' la situazione, a presto
ciao,
Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Rieccomi qui in fase di test :)

Sto riscontrando un errore nel codice, e precisamente nella classe Connessione:

"'RestSharp.RestClient' non contiene una definizione di 'ExecuteTaskAsync' e non è stato trovato alcun metodo di estensione 'ExecuteTaskAsync' che accetta un primo argomento di tipo 'RestSharp.RestClient'. Probabilmente manca una direttiva using o un riferimento a un assembly."

Visual studio non mi suggerisce nessun using, oltre al fatto che ho già importato sia using restsharp che using System.Threading.Tasks;

Ed effettivamente RestSharp.RestClient mi suggerisce come metodi solo:

.ExecuteAsync
.ExecuteAsync<>
ExecuteAsyncGet
ExecuteAsyncGet<>
ExecuteAsyncPost
ExecuteAsyncPost<>

Di RestSharp utilizzo la versione 104.4.0, cosa mi son perso?

0v3rCl0ck Profilo | Guru

le using che ho sono queste:

using System.Threading.Tasks; using RestSharp; using RestSharp.Deserializers;

la versione è uguale alla tua 104.4, quindi saranno certe estensioni che non vedi... o forse mi sono dimenticato di chiederti una cosa molto importante che ho dato per scontato tu compili in fx 4.5 o 4.0? hai almeno vs2012?


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

ecco il progettino di esempio, ma non l'ho provato, è scritto a cappella:

http://we.tl/hR9p9ncl1i


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Ciao, come framework ho la 4.0 e uso visual studio 2013, ho provato ad inserire using RestSharp.Deserializers ma l'errore su ExecuteTaskAsync<Dati> rimane....

Provo a vedere la soluzione che hai postato e vediamo se risolvo...

Grazie x ora :)

Aron Profilo | Newbie

Il progetto è praticamente uguale, solo che io le classi Dati e Connessione le ho in 2 file separati, le using le ho tutte, potrebbe dipendere dal framework?

Aron Profilo | Newbie

Mi viene un dubbio, nella soluzione che hai gentilmente postato nel tuo package vedo questo:

<package id="RestSharp" version="104.4.0" targetFramework="net45" />

mentre se guardo la mia soluzione ho:

<package id="RestSharp" version="104.4.0" targetFramework="wp80" />

Come detto prima ho controllato nuovamente le versioni del framework installate sul mio pc e ho:

v2.0.50727
v3.0
v3.5
v4.0.30319

Da ignorante mi viene un dubbio, siamo sicuri che su un applicazione WP8 posso utilizzare ExecuteTaskAsync?

Prima di provare ad aggironare il framework attendo risposta :P

Aron Profilo | Newbie

Sto iniziando a non capirci piu niente :\

Con questo comando:

dir /ad /b %systemroot%\Microsoft.NET\Framework64 | findstr v

mi dice che ho il framework 4.0.30319

se invece uso questo tool "http://blogs.msdn.com/b/astebner/archive/2008/10/13/8999004.aspx"

E provo a fare una verifica sul 4.5.1 mi dice Product verification succeeded!

0v3rCl0ck Profilo | Guru

Scusa non avevo capito che fosse una wp8 ad ogni modo non credo importi la cosa più importante e che tu stia compilando in 4.5 perché è solo da quella versione del framework che esistono i Task.

Se usi vs2013 non puoi compilare il progetto in 4.5 dalle proprietà del progetto?


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Ciao, come dovrei fare?
Perchè l'unica cosa di diverso che noto è questa:

<package id="RestSharp" version="104.4.0" targetFramework="wp80" />

mentre nel tuo è: <package id="RestSharp" version="104.4.0" targetFramework="net45" />

E se provo a caricare il tuo progetto non mi da nessun errore.....

0v3rCl0ck Profilo | Guru

Nelle proprietà del progetto sotto la scheda build cosa vedi? Che target framework vedi selezionato?

Al massimo appena riesco faccio una prova su wp8


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Appurato che ho il 4.5 mi rimane comunque l'errore "'RestSharp.RestClient' non contiene una definizione di 'ExecuteTaskAsync" :\

Sto diventando matto per cercare di capire perchè se carico il tuo progetto non mi da quell'errore mentre da me si....

0v3rCl0ck Profilo | Guru

Allora mi viene da pensare che non sia presente quell'extension anche per w8 ma adesso ci guardo e ti faccio sapere


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Se vado su progetto/proprietà mi si apre una scheda dove tra le altre cose mi dice "Versione di destinazione di Windows Phone OS" e mi fa selezionare solo windows phone os 8.0"

Poi non vedo altri riferimenti al framework...

Grazie per la disponibilità attendo responso! :)

0v3rCl0ck Profilo | Guru

intanto leggi qua, perchè i concetti sono quelli e ci sono anche esempi semplici di codice anche se è c#:

https://radical.codeplex.com/wikipage?title=The%20message%20broker


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

ok wp8 ha il suo framework e non puoi cambiarlo, va in base alla versione del sistema operativo... ma ha tutte le funzionalità nuove dell'async tra cui i Task, ora vedo RestSharp


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

su restsharp wp8 non c'è ancora il supporto per i task, domani guardo come sistemare il codice, o se direttamente copiare la parte dei task di restsharp dalla parte win, penso di avere visto che su github qualcuno aveva già fatto la richiesta per wp8 parecchi mesi fa però...ad ogni modo non c'è problema al massimo si fanno con le callback


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Grazie infinite per l'interessamento, io stavo guardando questo:

http://himynameistim.wordpress.com/tag/rest-sharp/

Ma non ho capito se include anche wp8 visto che parla in modo generico di Windows Phone app, ma sopratutto, non è che l'utilizzo delle task poi potrebbe dare eventuali problemi in un eventuale pubblicazione dell'app sullo store?

0v3rCl0ck Profilo | Guru

>Grazie infinite per l'interessamento, io stavo guardando questo:
>
>http://himynameistim.wordpress.com/tag/rest-sharp/

si è esattamente quello che va fatto per abilitare il supporto dei Task, di fatto per la libreria core l'hanno già fatto, se non l'hanno fatto per wp8 è solo perchè nessuna buona anima gli ha ancora fatto la pull request della modifica.

>
>Ma non ho capito se include anche wp8 visto che parla in modo
>generico di Windows Phone app, ma sopratutto, non è che l'utilizzo
>delle task poi potrebbe dare eventuali problemi in un eventuale
>pubblicazione dell'app sullo store?
>

Lo sviluppo su windows phone 8 supporta a pieno la task programming, ecco alcune fonti piuttosto ufficiali:

http://blogs.msdn.com/b/dotnet/archive/2012/10/30/announcing-the-release-of-the-net-framework-for-windows-phone-8.aspx
http://developer.nokia.com/community/wiki/Asynchronous_Programming_For_Windows_Phone_8
http://visualstudiomagazine.com/articles/2012/10/31/new-tools-for-windows-phone-8-released.aspx

di fatto hanno estrapolato un CLRCore dal .net fx 4.5:

"
CoreCLR engine and garbage collector

Windows Phone 8 includes the CoreCLR engine instead of the .NET Compact Framework. The CoreCLR includes many of the same features and optimizations as the CLR in the .NET Framework 4.5. As a result, it is a lot faster and more efficient than the .NET Compact Framework. In particular, the CoreCLR includes our world-class auto-tuning garbage collector. These changes result in reduced startup time and higher responsiveness in your apps.
"

quindi puoi seguire quella guida e va benissimo, perchè ti permette di creare le estensioni mancanti al pacchetto wp8, sinceramente credo si possa completamente copiare l'extension dai sorgenti RestSharp per .net framework, e farlo andare tranquillamente per le dll wp8, perchè di fatto è un estensione banale, che abbraccia il vecchio pattern delegate based, e lo avvolge in un task, quando il vecchio metodo asyncrono ha finito, lancia il delegato, ma dentro al delegato non c'è altro che il set del risultato del task... in questo modo da fuori hai in mano il Task, e poi fare tutta la task programming del caso async/await oppure Task.Result oppure Task.Wait oppure Task.ContinueWith.... ecc...

Se non ti è chiaro lo vediamo insieme


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Ok, non è che mi sia del tutto chiaro....

Vediamo un po...

prendo come riferimenti questi 2 link:

http://developer.nokia.com/community/wiki/Asynchronous_Programming_For_Windows_Phone_8
http://himynameistim.wordpress.com/tag/rest-sharp/

Quello che mi pare di capire è che le funzioni non dovranno restituire l'oggetto come era stato fatto nel tuo esempio:

public class Connessione { public async Task<Dati> GetAsync() { RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); var response = await client.ExecuteTaskAsync(request); Dati dati = JsonConvert.DeserializeObject<Dati>(response.Content); return dati; } }

Ma la mia classe Connessione dovrà restituire una task, ma non mi è del tutto chiaro se devo usare ExecuteAsync o ExecuteTaskAsync, e in sostanza il task restituito conterrà la stringa del json o il mio oggetto da deserializzare per popolare la mia classe dati?

Poi altra cosa che mi sfugge è se devo creare oltre alla classe Connessione un altra che si occupa di implementare l'ExecuteTaskAsync o è proprio nella classe Connessione che devo far in modo di implementarmi il supporto per l'async e await?

Ok forse le mie idee sono un po più che confuse.....e pensare che all'inizio pensavo di dover fare solo una banale chiamata Http :\

In questo esempio

var username = await getUsername(“email@eail.com”) var token = await getToken(username); var tasks = await getTasks(token); ... public async Task<ToodledoToken> getToken(string userId) { var request = new RestRequest("account/token.php", Method.GET); return (await ExecuteAsync<ToodledoToken>(request)); }

quel return alla fin fine sta restituendo la stringa completa per popolare la classe userid?

0v3rCl0ck Profilo | Guru

>
>Quello che mi pare di capire è che le funzioni non dovranno restituire
>l'oggetto come era stato fatto nel tuo esempio:
>
>Ma la mia classe Connessione dovrà restituire una task,

anche nel mio progetto di esempio, ritornavo un task, che poi con await ti permette di nascondere il fatto che sia un task, e ti ritorna il risultato contenuto nel task non appena quest'ultimo ha finito l'esecuzione, ma dovrei spiegarti tutto dall'inizio il multi-threading per farti capire bene cosa succede dietro le quinte, ma tieni per buono che sfruttando quei metodi stai lavorando in modo asincrono scrivendo codice che assomiglia in tutto e per tutto a codice sincrono.

Leggi qualche buona fonte e cerca di capire bene come funziona il threading in c#, questa guida è ottima (anche il suo libro c# in a nutshell di albahari): http://www.albahari.com/threading/
Ti spiega a partire dai thread di sistema fino ad arrivare agli oggetti più gestiti di .net come i Task e il Parallel: http://www.albahari.com/threading/part5.aspx#_Task_Parallelism
Un consiglio, non soffermarti troppo su PLINQ e Parallel all'inizio, ma passa al Task Parallelism (ovviamente dopo avere letto le 4 parti prima) perchè sta alla base di tutto il nuovo codice che vedrai sempre di più utilizzare ovunque (appunto await/async, ma è bene sapere cosa succede dietro le quinte).

>ma non mi è del tutto chiaro se devo usare ExecuteAsync o ExecuteTaskAsync,
>e in sostanza il task restituito conterrà la stringa del json
>o il mio oggetto da deserializzare per popolare la mia classe
>dati?

il task ritorna quello che si vuole, in dettagli nel RestSharp in base a che metodo chiami di restsharp, ci sono metodi che ritornano tutta la risposta http e poi ci fai quello che vuoi (.Content ricordi?), oppure altre chiamate che già deserializzano per te, da qui nasceva tutto il discorso json.net

>
>Poi altra cosa che mi sfugge è se devo creare oltre alla classe
>Connessione un altra che si occupa di implementare l'ExecuteTaskAsync
>o è proprio nella classe Connessione che devo far in modo di
>implementarmi il supporto per l'async e await?
>

bravo! esattamente!! per il semplice fatto che per RestSharp windows phone 8, non te l'hanno ancora fatto....ma attenzione, non vorrei che tu pensassi che devi per forza fare tutto questo!! ti sto solo cercando di mostrare la via che mi sembra più opportuna per come si stanno evolvendo le cose in .net, e quindi darti già la strada nuova e non quella vecchia... ma di fatto uno vale l'altra, il problema alla base è comunque capire come funziona l'asincrono, nel caso della libreria base di RestSharp quindi senza estensioni per la task programming, esistono metodi sincroni e metodi asincroni.

I metodi sincroni quando vengono chiamati bloccano il thread corrente fino a che non hanno finito con la chiamata http, una volta finito il tuo codice continua, quindi sei sicuro di avere il risultato valorizzato:

var response = client.Execute(request); textbox1.text = response.Content;

I metodi asincroni invece, quando vengono chiamati non bloccano il thread corrente, non ritornano subito un risultato, e iniziano ad eseguire le operazioni in un altro thread, in realtà non è sempre così, ma l'importante è dire che la tua esecuzione del codice continua senza aspettare la risposta del server... e quindi chi aspetta la risposta del server? eh..nessuno, se a nessuno interessa... e se invece mi interessa? ecco perchè ti viene dato una qualche forma di sincronizzazione, nel caso base di restsharp ti viene data la possibilità di passare un delegato, che verrà chiamato quando è pronto il risultato:

client.ExecuteAsync(request, response => { textbox1.text = response.Content; });

ma se io volessi concatenare più risultati asincroni? e se più semplicemente volessi recuperare il risultato non subito quando ha finito, ma anche più avanti nell'esecuzione, rimanendo certo di avere il risultato quando lo richiedo? ecco è qui che subentrano i task! invece che dare subito un delegato che eseguirà subito codice all'arrivo del risultato, il metodo stesso non richiede più un delegato, anzi restituisce un Task, quindi finalmente abbiamo subito in mano qualcosa anche dopo l'esecuzione di codice asincrono (mentre con il delegato, il metodo è void, non ritorna niente, anzi si aspetta qualcosa in più, cioè il delegato). Il task ha diverse possibilità, ti permette di fare l'attesa al risultato Task.Wait, ti permette di leggere subito il risultato Task.Result (dentro fa prima la wait, e poi ritorna il risultato), oppure ti permette di concatenare altri task asincroni Task.ContinueWith, e passare il risultato tra un task e l'altro... quindi permettendoti di rispondere alla prima domanda (ma se io volessi concatenare più risultati asrincroni?)... poi dal 4.5 hanno introdotto le keyword async/await, async serve solo per avvisare il metodo che potrebbero essere delle operazioni di await e di prepararsi per compilare il codice in modo differente, await invece serve proprio per fare una wait del risultato, ma perchè await? perchè è un attesa asincrona! mentre la Task.Wait / Task.Result, attendono bloccando il thread corrente, l'await, spezza il metodo in più metodi, ed esegue tutto in maniera asincrona, di fatto rilasciando subito il thread corrente, ma è complicato spiegarlo in poche righe, ci sono libri interi

e quindi in restsharp per .net 4.5 hanno già messo le TaskAsync che ti permettono di fare queste operazioni:

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

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

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

attenzione a TaskScheduler.FromCurrentSynchronizationContext() perchè è importante, si assicura che l'esecuzione avvenga sul thread principale della UI.

nuovo metodo async/await introdotto in fx 4.5

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

ricorda, il metodo deve essere marcato come async!

Come vedi in realtà l'async/await tendono proprio a semplificare la vita del multi-threading e non a complicarla, solo che prima bisogna comunque capire le basi, altrimenti tutto sembra davvero complicato.


>Ok forse le mie idee sono un po più che confuse.....e pensare
>che all'inizio pensavo di dover fare solo una banale chiamata
>Http :\

non ti demoralizzare, una volta capiti i concetti, vedrai che anche fare multi-threading è diventato davvero semplice.

guarda nel tuo caso puoi fare anche così per riutilizzare il metodo, è sufficiente che il tuo metodo stesso richieda il delegato dal chiamante:

public class ConnessioneBase { public RestRequestAsyncHandle GetAsync(Action<IRestResponse<Dati>> callback) { RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); return client.ExecuteAsync<Dati>(request, callback); } }

e poi chiamarla così:

var connessione = new ConnessioneBase(); connessione.GetAsync(response => { var dati = response.Data; tbkNome.Text = dati.Nome; tbkStato.Text = dati.Stato; });

ma sforzati comunque di provare a vedere come farlo andare con i Task:

public class ConnessioneBaseTaskWrap { public Task<Dati> GetAsync() { var tcs = new TaskCompletionSource<Dati>(); RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); client.ExecuteAsync<Dati>(request, response => { if (response.ErrorException != null) tcs.TrySetException(response.ErrorException); else tcs.TrySetResult(response.Data); }); return tcs.Task; } }

poi invece che scrivere tutte le volte quella roba tcs.tryset...bla bla.... il tizio del blog ha fatto un ottimo articolo su come creare una piccola extension per attivare i task su qualsiasi chiamata:

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

con quell'estensione di fatto puoi usare il codice che ti avevo mandato in origine, devi solo implemetare anche l'altro metodo di estensione che accetta il tipo di ritorno, se vuoi che restsharp faccia lui la deserializzazione, altrimenti quella estensione torna l'oggetto http di risposta, dove hai il contenuto stringa... .Content, e non hai .Data

>
>In questo esempio
>
>
>var username = await getUsername(“email@eail.com”)
>var token = await getToken(username);
>var tasks = await getTasks(token);
>...
>
>public async Task<ToodledoToken> getToken(string userId)
>{
>var request = new RestRequest("account/token.php", Method.GET);
> return (await ExecuteAsync<ToodledoToken>(request));
>}
>
>
>quel return alla fin fine sta restituendo la stringa completa
>per popolare la classe userid?

ritorna sempre comunque un task, che conterrà un risultato di tipo ToodledoToken, perchè in quel caso RestSharp prende il response.Content e lo deserializza direttamente nell'oggetto, ad ogni modo quando chiami getToken, ti viene ritornato il Task in questo caso un task che ha anche un risultato di ritorno di un tipo preciso Task<ToodledoToken>. La magia poi sta nell'await del chiamante "var token = await getToken(username);" dove farà l'attesa in modo asincrono del task ritornato dalla getToken, altrimenti potevi fare "var token = getToken(username).Result;", e tutto gira uguale, ma apparentemente!! il codice sembra essere cambiato davvero poco, ma il fatto è che facendo .Result, come dicevo sopra, blocchi il thread corrente, mentre con l'await no!! l'await ti garantisce l'esecuzione del tuo codice nello stesso ordine in cui l'hai scritto, ma il tutto in modo asincrono, senza dovere fare a mano i continueWith o altro codice di sincronizzazione tra thread.

Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Grazie per le varie spiegazioni,stasera con molta calma vedrò di leggere bene i 2 link che mi hai postato, nel frattempo dopo aver letto 2 o 3 volte la tua risposta ho provato a fare un test con la prima soluzione che mi hai suggerito, ossia:

public class ConnessioneBase { public RestRequestAsyncHandle GetAsync(Action<IRestResponse<Dati>> callback) { RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); return client.ExecuteAsync<Dati>(request, callback); } }
e poi chiamarla così:
var connessione = new ConnessioneBase(); connessione.GetAsync(response => { var dati = response.Data; tbkNome.Text = dati.Nome; tbkStato.Text = dati.Stato; });

Ho quindi creato il Main e un bottone in questo modo:

public MainPage() { InitializeComponent(); var connessione = new Connessione(); connessione.GetAsync(response => { var dati = response.Data; tbkNome.Text = dati.Nome; }); }

private void btStato_Click(object sender, RoutedEventArgs e) { var connessione = new Connessione(); connessione.GetAsync(response => { var dati = response.Data; tbkNome.Text = dati.Nome; tbkStato.Text = dati.Stato; }); }

Ma ho lo stesso problema che avevo in precedenza, e cioè:

Avvio Emulatore, come prima cosa mi viene riempito il campo Nome, (Nome = Pippo) a questo punto vado sul webservice e modifico il nome da Pippo a Pluto, aggiorno il ws e verifico sul browser che effettivamente il mio json sia cambiato, ok ora il json è:

{
"nome":"Pluto",
"stato":0
}

Ritorno sull'emulatore e clicco sul Bottone, il risultato è che il nome è rimasto invariato e il campo stato invece è corretto, ho provato anche ad impostare un Binding sul campo ma nada. Perchè non si aggiorna se sto effettuanto una nuova connessione?

----------------------------

2° Quando dici:

"con quell'estensione di fatto puoi usare il codice che ti avevo mandato in origine, devi solo implemetare anche l'altro metodo di estensione che accetta il tipo di ritorno, se vuoi che restsharp faccia lui la deserializzazione, altrimenti quella estensione torna l'oggetto http di risposta, dove hai il contenuto stringa... .Content, e non hai .Data"

A quale metodo di estensione ti riferisci? non si era detto che si occupava restsharp della deserializzazione utilizzando solo:
Dati dati = response.Data;
return dati;

Grazie per la pazienza :P

Aron Profilo | Newbie

Non so se può essere utile, ma se esco e rientro nell'applicazione, senza chiudere l'emulatore il campo nome si aggiorna per la chiamata presente all'interno del main, mentre tramite pulsante non aggiorna la proprietà Nome :(

Nel dubbio ho provato anche a creare una nuova istanza all'interno del bottone

private void btStato_Click(object sender, RoutedEventArgs e) { var connessione = new Connessione(); Dati dato = new Dati(); connessione.GetAsync(response => { dato = response.Data; tbkNome.Text = dato.Nome; tbkStato.Text = dato.Stato; }); }

Anche qui stessa cosa, la proprità Nome non viene aggiornata :(

0v3rCl0ck Profilo | Guru

effettivamente in questo caso mi sembra strano, e quando facevi la stessa chiamata sincrona con Execute(...) invece funzionava?


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

In realtà non ho mai provato la chiamata sincrona, perché il mio esempio iniziale, quello preso dal testo utilizzava questa:
client.ExecuteAsync(request, response =>

In mattinata magari provo con un metodo sincrono, ma non so piu che pesci prendere per aggiornare sta benedetta classe, ero convinto che creando una nuova istanza avrei risolto...

Aron Profilo | Newbie

Continuando a fare dei test, ho capito che il problema non è ne la deserializzazione e ne la classe, ma l'ExecuteAsync, possibile che l'ExecuteAsync abbia qualche sorta di cache?

Ho provato a cercare di ottenere il json dopo la modifica in questo modo:

private void btTest_Click(object sender, RoutedEventArgs e) { RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); client.ExecuteAsync(request, response => { test.Text = response.Content; }); }

Quindi avvio l'applicazione, la chiamata dentro al main mi riempie il tbkNome, modifico il Nome sul web service, verifico da browser che sia cambiato e lo è, clicco il pulsante di test e come risposta ottengo il vecchio json ???
Deve esserci qualcosa all'interno dell'ExecuteAsync che non capisco e che per qualche ragione mi restituisce il vecchio dato...

Aron Profilo | Newbie

Le sto provando tutte:

private async void btTest_Click(object sender, RoutedEventArgs e) { string result = await Connect(); test.Text = result; } private async Task<string> Connect() { var json = new TaskCompletionSource<string>(); RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); client.ExecuteAsync(request, response => { json.SetResult(response.Content); }); return await json.Task; }

Compila, ma alla pressione del bottone restituisce sempre il vecchio json al posto di quello aggiornato....

Ho cercato di seguire questo:
http://www.developer.nokia.com/community/wiki/Asynchronous_Programming_For_Windows_Phone_8

Non capisco cosa sbaglio.... need help :(

0v3rCl0ck Profilo | Guru

beh intanto vedo che stai imparando ad usare i task e l'await, questo non è male hai scritto una funzione corretta, anche se potevi scriverla semplicemente così, invece che forzare un await:

private Task<string> Connect() { var json = new TaskCompletionSource<string>(); RestRequest request = new RestRequest("url servizio"); request.Method = Method.GET; RestClient client = new RestClient(); client.ExecuteAsync(request, response => { json.SetResult(response.Content); }); return json.Task; }

di fatto il TaskCompletionSource è uno strumento per simulare un task, e serve appunto in questi casi, per trasformare vecchio codice async, sfruttando i nuovi task, quindi potevi semplicemente ritornare il relativo Task associato al TaskCompletionSource. L'await ti serve quando vuoi sincronizzarti appunto ad un metodo che ritorno Task, come giustamente ai fatto nel tuo pulsante, perchè avevi bisogno di aspettare il risultato prima di settare la text.

quello che invece stai riscontrando è particolarmente strano... a volte certe funzioni, come dicevi tu, "cachano" il callback/delegate e quindi bisogna fare estrema attenzione alla documentazione, ma di solito lo specificano, e poi comunque questo non ha niente a che vedere con la response, perchè quella ti viene passata dal restclient alla fine della chiamata, e deve essere per forza la nuova risposta, al più si cacha il delegato, che nel tuo caso non comporterebbe comunque nessun problema... ma credo che stiamo parlando a vanvera

nel frattempo appena ho tempo faccio qualche prova..... anche tu potresti provare a farti una console application e vedere intanto se con la libreria fx 4.5 cambia qualcosa, ma non credo possa esserci un problema nella libreria, è improbabile... è più facile che sia un problema di UI che non vediamo


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Grazie attendo con ansia tue notizie!

Ho cercato di andare per esclusione:

request - Non può essere perchè è una nuova variabile e una nuova RestRequest
client - Non può essere perchè anche li è una nuova istanza
response - Come hai detto tu dipende dal restclient

Mi rimane solo ExecuteAsync...

Ho fatto quindi questa ulteriore prova, utilizzando l'HttpWebRequest:

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

private async void btTesthttp_Click(object sender, RoutedEventArgs e) { Jsonhttp client = new Jsonhttp(); var resp = await client.DoRequestAsync("url servizio"); string result = resp.ReadToEnd(); test.Text = result; }

Risultato Identico! Neanche cosi viene aggiornato il risultato...
Sto iniziando ad odiare profondamente WP8! Mi viene da pensare che il problema possa essere l'emulatore di vs 2013 :\

0v3rCl0ck Profilo | Guru

intanto questa codice è perfetto (sappi che tutto il fx 4.5 è stato riscritto così wrappando i vecchi metodi che per retrocompatibilità rimangono):

Task.Factory.FromAsync((cb, o) => ((HttpWebRequest)o).BeginGetResponse(cb, o), res => ((HttpWebRequest)res.AsyncState).EndGetResponse(res), req);

hai scoperto un'altra funzionalità per facilitare il compito della trasformazione di vecchio codice async in task, quel metodo serve per convertire tutti i metodi che seguono la "Asynchronous Programming Model (APM)", mentre il taskCompletitionSource per gli altri casi tipo l'event-based, trovi tutte le differenze qui: http://msdn.microsoft.com/en-us/library/jj152938(v=vs.110).aspx

tornando a noi.... penso che sia solo un problema di cache, credo che anche l'httpwebrequest ha di default attivato la cache, di conseguenza anche restsharp dovrà esprorre qualche proprietà per settare a false la cache, con in jquery che puoi disattivarla.

Nel frattempo puoi provare ad aggiungere una variabile in fondo alla chiamata rest per essere sicuri di invalidare la cache esempio:

"http://www.url.com/1/123" + "?nocache=" + DateTime.Now.Ticks


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

fammi sapere se aggiungendo il tick funziona


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

con un progettino console + un asp.net web api, non riscontro il problema, con l'api che ad ogni richiesta cambia in random la risposta (vedi allegato)


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

PERFETTO! GENIO!!!

Con "+ "?nocache=" + DateTime.Now.Ticks" adesso funzionano tutti e 3 i sistemi ^^

In pratica questa dicitura cosa fa di preciso?

Aron Profilo | Newbie

Intanto setto come risolto finalmente!

Se poi troviamo una soluzione per non aggiungere quella dicitura tanto di guadagnato :)

0v3rCl0ck Profilo | Guru

>Con "+ "?nocache=" + DateTime.Now.Ticks" adesso funzionano tutti
>e 3 i sistemi ^^
>
>In pratica questa dicitura cosa fa di preciso?

niente di speciale, aggiungendo un parametro che nessuno legge, ma che cambia l'url che stai richiedendo, sei sicuro che la pagina non c'è l'hai in cache, la stessa cosa la fa jquery quando fai una chiamata ajax passando cache:false, questo metodo è il più universale di tutti, perchè ci sarebbero anche metodi passando header speciali, ma aggiungendo il tick, sei sicuro di bypassare qualsiasi cache.

ora, restsharp essendo rest, mi viene da dire che è giusto faccia cache, perchè rest lavora con ogni tipo di risorsa che potrebbe anche essere un immagine o un file, quindi la cache è importante darla... il problema è che vorrei capire se c'è un metodo integrato in restsharp...

piccolo google "restsharp cache" "restsharp disable cache"?

via...


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

niente tutti dicono di fare come ti ho detto io.... quindi niente lascia così, magari fatti un UrlHelper.NoCacheUrl(string originalUrl) che ti ritorna la stessa url che gli passi aggiungendo il parametro "nocache" oppure come fa jquery qualcosa di più fine solo un underscore "_". Guarda la classe Uri del framework, che ti può aiutare ad aggiungere quel parametro in modo sicuro.


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic

Aron Profilo | Newbie

Ok direi proprio che lo lascerò cosi :)
Mi ha gia portato via qualche anno di vita sta app :D

Adesso non mi resta che decidere se continuare ad usare restsharp o se utilizzare l'ultimo metodo HttpWebRequest, in previsione di fare anche delle chiamate in POST oltre che in GET cosa mi consigli?

0v3rCl0ck Profilo | Guru

o restsharp che è fatto apposta per il rest.

oppure da wp7.5 hanno aggiungo l'HttpClient che forse ti consiglierei dato i download da nuget più di 1.7 milioni di download :)

http://blogs.msdn.com/b/bclteam/archive/2013/02/18/portable-httpclient-for-net-framework-and-windows-phone.aspx
http://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.110).aspx

msdn:

https://www.nuget.org/packages/Microsoft.Net.Http

anche questo è un client puro http e quindi fai tutto il rest che vuoi :)


Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic
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