Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1894, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

lunedì 13 febbraio 2017

Xamarin, Azure e il Visual Studio Mobile Center - Autenticazione

Dopo aver parlato di sincronizzazione offline nel post precedente, in quest'ultimo post della mini serie dedicata al Visual Studio Mobile Center per Xamarin parliamo di autenticazione, login e accesso autorizzato ai dati.

Come promesso, il codice completo della solution con accesso al backend, sincronizzazione offline e autenticazione è disponibile su GitHub.

Tipologie di autenticazione

Gestire l'autenticazione con gli Azure Mobile App tramite il Mobile Center è semplicissimo se utilizziamo uno dei provider previsti. Si tratta di Microsoft Account, Facebook, Twitter, Google+ oltre alla Azure Active Directory. Ovviamente è possibile implementare l'autenticazione anche nei confronti di Web API custom, ma eventualmente ne riparlermo in quanto al di fuori dei discorsi su questi servizi. Capiamo prima bene quanti e quali provider vogliamo utilizzare. L'autenticazione avviene tramite il metodo LoginAsync della classe MobileServiceClient, a cui passiamo il provider di autenticazione. Poi fa tutto lui, posto che tutto sia stato configurato lato server. Restituisce un oggetto MobileServiceUser che contiene il token e lo user id dell'utente riconosciuto.

L'autenticazione nel servizio

Il primo passaggio da fare è abilitare l'autenticazione nel Mobile Service e assegnarla alle tabelle. Nel Mobile Center entriamo nell'area della nostra app, quindi click su Identity nel menu laterale. Ci verrà proposto l'elenco di provider, scegliamo Microsoft Account perché sicuramente ce l'avete. I passaggi sono comunque simili anche per gli altri provider e possiamo selezionarne più di uno:



Come vedete vengono chieste due info: application id e client secret. Per ciascun provider ci sono luoghi e portali diversi in cui generarli, ma per ognuno il Mobile Center vi fornisce link e documentazione. Nel caso di Microsoft Account, andate nel portale di gestione delle app e fate click su Add an app. Specificate un nome, poi verrà generato l'application id e se fate click su Generate New Password otterrete anche il client secret:


Entrambi andranno copia-incollati nel Mobile Center. Nota molto bene: in questo portale, il client secret lo vedrete solo la volta in cui viene generato. Sempre in questo portale, sotto Platforms, cliccate su Add New Platform, poi selezionate Web. Bisogna infatti fornire l'URL di redirect che, nel caso del MS Account, ha la forma visibile in figura:



Dove mobile-app-id.azurewebsites.net andrà sostituito con l'URL del vostro servizio di backend. Salvate le modifiche, tornate nel Mobile Center, salvate tutto anche li.

Autorizzazione sulle tabelle

Fate click su Tables, quindi sulla tabella Book (o su altra di vostro interesse). In alto a destra, cliccate sul pulsante coi tre punti sospensivi e dal menu contestuale scegliete Change Permissions. Per ciascuna operazione, potrete definire il livello di autenticazione tra Authenticated, Anonymous, Disabled:



Accertatevi che tutte abbiano lo stesso livello e che sia selezionata l'opzione Per-user data. Se vi ricordate, all'inizio della serie vi dissi che quest'opzione aggiunge una colonna chiamata userId di tipo stringa che consentirà di filtrare i dati sulla base dell'utente autorizzato. Lo potrete facilmente verificare dopo aver fatto click su Save.

Codice - il Model

Sono necessarie varie modifiche al codice della solution su cui stavamo lavorando. La prima riguarda la classe TableBase, che ora deve includere la proprietà UserId:

E questo è il primo passo.

Codice - l'autenticazione
L'autenticazione è in realtà platform-specific. Quindi, in una cartella chiamata Authentication del progetto PCL, definiamo la seguente interfaccia:


Essa demanda a ciascun progetto l'implementazione dell'autenticazione. Creiamo le relative classi Authentication nei progetti Droid e iOS.

Android:


iOS:

Ciò che cambia è, di fatto, il contesto di UI che il metodo LoginAsync riceve. Come vedete, è sufficiente cambiare un valore dell'enumerazione MobileServiceAuthenticationProvider per autenticare l'utente con un diverso provider. In entrambi i casi viene restituito il MobileUser col suo id e il suo token.

Codice - il ViewModel

Anche il ViewModel subisce modifiche. Ha senso definire due proprietà UserId e IsUserAuthenticated per poter memorizzare l'id utente da usare nelle query e nel salvataggio dei dati e per capire se l'utente può avviare le azioni richieste. Ovviamente la logica di determinazione se l'utente è autenticato è poi custom. Eccolo modificato:

E' anche evidente come venga esposto il metodo LoginAsync che chiama il suo omonimo su ciascuna piattaforma.

Codice - l'accesso ai dati

In realtà, avendo demandato al ViewModel l'inserimento dello user id in nuovi oggetti, l'unica vera modifica nella classe DataManager riguarda il metodo LoadAsync, che esegue una query filtrando il risultato proprio per user id. Ad ogni modo, per praticità, riporto l'intero codice della classe:


Codice - la UI

L'ultima parte riguarda il code-behind della pagina MainPage.xaml.cs, dove in OnAppearing verificheremo che l'utente sia autenticato e, se non lo è, invocheremo il metodo di autenticazione:


Lo facciamo qui piuttosto che nel costruttore perché vogliamo verificare l'autenticazione ogni volta che si arriva sulla pagina, che magari è andata solo in sospensione.

Un passaggio preliminare

C'è un piccolo difetto ad oggi nel Mobile Center che impedirebbe all'autenticazione di funzionare. Ciò che dovete fare è:

  1. andare nel portale di Azure
  2. cliccare su App Services e selezionare l'id corrispondente al vostro servizio
  3. cliccare su Authentication
  4. selezionare l'Enable token store
Speriamo che questa opzione venga presto importata nel Mobile Center.

Il risultato

Ecco cosa otterremo a questo punto nell'app:



Quindi, con pochi passaggi e poche righe, abbiamo introdotto l'autenticazione nella nostra app Xamarin sfruttando i servizi di Azure e il Mobile Center.

La solution completa

Tutta la solution completa è disponibile a questo indirizzo su GitHub.

Alessandro

posted @ lunedì 1 gennaio 0001 00:00 | Filed Under [ Windows Azure and SQL Azure Xamarin ]

Xamarin, Azure e il Visual Studio Mobile Center - Sincronizzazione offline

Nel post precedente abbiamo visto come sfruttare i servizi di backend di Azure esposti dal Visual Studio Mobile Center per creare una tabella a cui un'app scritta con Xamarin può accedere per memorizzare e recuperare dati.

Nota: il codice sorgente completo sarà fornito nel prossimo post, in cui parlo di autenticazione.

Quell'approccio ha un limite: non memorizza i dati localmente e richiede sempre connettività per poter lavorare. Per fortuna, l'SDK Azure Mobile Client e i servizi di Azure Mobile App offrono anche l'infrastruttura per poter avere dati locali e per sincronizzarli quando online.

(Nota: quanto vedremo in questo post non è legato al Visual Studio Mobile Center, ma è un arricchimento della serie di post).

Per fare questo, l'SDK si avvale di SQLite in locale ed espone il necessario attraverso la classe MobileServiceClient. La cosa bella è che non è necessario installare le apposite librerie di SQLite, perché ci pensa l'SDK a mappare gli oggetti giusti. Quindi, alla solution lasciata in sospeso la volta scorsa aggiungiamo un pacchetto NuGet chiamato Microsoft.Azure.Mobile.Client.SQLiteStore.

Il percorso del db locale
La prima cosa da fare è stabilire il percorso del db locale. Il file system è platform-specific, quindi non sotto lo strato unificato di Xamarin.Forms. Quindi si ricorre al dependency service, dapprima definendo un'interfaccia che stabilisce il contratto (e che creo nella cartella DataAccess della solution):

Fatto questo, vado a definire una classe chiamata DataConnection, che implementa l'interfaccia, su entrambe le piattaforme di mio interesse (Android e iOS perché sono le due ad oggi supportate dal Mobile Center). Ovviamente, su Windows il discorso è analogo.

Android:


iOS:

Ottenuto il percorso del db locale, andremo poi a crearlo e gestirlo.

Utilizzo del db locale
L'accesso al db locale avviene mediante la classe MobileServiceClient, ma il db fisico è rappresentato dalla classe MobileServiceSQLiteStore che va istanziata passando il percorso del file. Una volta istanziata, si invoca il metodo DefineTable<T> tante volte quante sono le tabelle che abbiamo bisogno di generare in locale. Questo metodo crea ma non sovrascrive una tabella. Fatto questo, bisogna inizializzare il meccanismo di sincronizzazione attraverso il metodo SyncContext.InitializeAsync della classe MobileServiceClient, a cui viene passata l'istanza della MobileServiceSQLiteStore e, opzionalmente, un cosiddetto handler che influisca sulla comunicazione. Per esempio, header di autenticazione tramite Web API o informazioni aggiuntive sulla serializzazione JSON.

Altra piccola modifica richiesta è l'utilizzo del metodo GetSyncTable<T> al posto di GetTable. Con GetSyncTable, la libreria sa che deve gestire anche una tabella locale e non solo remota. Poi le operazioni vengono fatte ugualmente con InsertAsync, UpdateAsync, ecc. Solo che il risultato rimane in locale finché non viene invocato PushAsync sul contesto. Questo metodo cercherà di inviare i dati alla tabella remota.

In fase di caricamento dei dati, invece, prima di fare una query o di ottenere un insieme tramite ToListAsync/ToEnumerableAsync, si invoca PullAsync sulla table. Questo metodo effettua una reale sincronizzazione tra remoto e locale e crea una query sulla tabella specificando un nome che serve al sync incrementale. Il nome è libero, in più bisogna passare il risultato di CreateQuery come secondo parametro. Tutto il succo di questo discorso è visibile nel seguente codice e vedrete che i cambiamenti sono davvero pochi, sebbene il codice risulti più lungo per via delle eccezioni da gestire:


Eccezioni e proprietà di sync
Le operazioni di sync possono ovviamente causare eccezioni. I motivi possono essere molto vari, come mancanza di connettività non gestita, differenze tra schema locale e schema remoto (soprattutto se il db remoto è SQL Server), ecc. Le eccezioni che tipicamente andranno gestite sono MobileServicePushFailedException e MobileServiceInvalidOperationException, la prima con la sua proprietà PushResult che contiene un elenco di Errors a rappresentare i vari problemi rilevati. Può anche essere utile conoscere il valore della proprietà PendingOperations, che espone il numero di operazioni in locale che non sono state ancora sincronizzate, per esempio per invocare poi PushAsync. L'ultimissima modifica è l'inizializzazione dello storage per piattaforma. Sia in MainActivity.cs (Android) che in AppDelegate.cs (iOS), prima della chiamata a LoadApplication va aggiunta la seguente riga:

Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init(); 

Null'altro è richiesto!

L'aver progettato l'app secondo MVVM non rende necessarie modifiche né al ViewModel né alla UI.

Test da fare

Per verificare il meccanismo di sync, provate ad avviare l'app e ad usarla col device disconnesso dalla rete. Poi provate a chiuderla, riconnettere la rete, riavviarla. Ovviamente in scenari reali dovreste prevedere la possibilità di un sync automatico, ad esempio tramite la tecnica del pull-to-refresh sulla ListView.

Questo è tutto. Vi ritroverete un db locale che vi consentirà di lavorare offline e una tabella remota con cui i dati verranno sincronizzati. Nel prossimo post concluderemo parlando di autenticazione.

Alessandro

posted @ lunedì 1 gennaio 0001 00:00 | Filed Under [ Windows Azure and SQL Azure Xamarin ]

Powered by:
Powered By Subtext Powered By ASP.NET