Så här använder du den hanterade klienten för Azure Mobile Apps
Översikt
Den här guiden visar hur du utför vanliga scenarier med hjälp av det hanterade klientbiblioteket för Azure App Service Mobile Apps för Windows- och Xamarin-appar. Om du är nybörjare på Mobile Apps bör du börja med att slutföra självstudien om Azure Mobile Apps snabbstart . I den här guiden fokuserar vi på den hanterade SDK:n på klientsidan. Mer information om SDK:er på serversidan för Mobile Apps finns i dokumentationen för .NET Server SDK eller Node.js Server SDK.
Referensdokumentation
Referensdokumentationen för klient-SDK finns här: Azure Mobile Apps .NET-klientreferens. Du kan också hitta flera klientexempel på lagringsplatsen Azure-Samples GitHub-exempel.
Plattformar som stöds
.NET-plattformen stöder följande plattformar:
- Xamarin Android-versioner för API 19 till och med 24 (KitKat till Noreleaset)
- Xamarin iOS-versioner för iOS-version 8.0 och senare
- Universell Windows-plattform
- Windows Phone 8.1
- Windows Phone 8.0 förutom Silverlight-program
"Serverflödesautentisering" använder en WebView för det användargränssnitt som visas. Om enheten inte kan presentera ett WebView-användargränssnitt krävs andra autentiseringsmetoder. Detta SDK lämpar sig därför inte för enheter av visningstyp eller liknande begränsade enheter.
Installation och krav
Vi förutsätter att du redan har skapat och publicerat mobilapps-backend-projektet, som innehåller minst en tabell. I koden som används i det här avsnittet heter tabellen TodoItem
och har följande kolumner: Id
, Text
och Complete
. Den här tabellen är samma tabell som skapades när du slutför snabbstarten för Azure Mobile Apps.
Motsvarande typ av klientsida i C# är följande klass:
public class TodoItem
{
public string Id { get; set; }
[JsonProperty(PropertyName = "text")]
public string Text { get; set; }
[JsonProperty(PropertyName = "complete")]
public bool Complete { get; set; }
}
JsonPropertyAttribute används för att definiera PropertyName-mappningen mellan klientfältet och tabellfältet.
Mer information om hur du skapar tabeller Mobile Apps serverservern finns i avsnittet .NET Server SDK eller avsnittetNode.js Server SDK. Om du har skapat mobilappsbackend i Azure Portal med hjälp av snabbstarten kan du också använda inställningen Enkla tabeller i Azure Portal.
Gör så här: Installera det hanterade klient-SDK-paketet
Använd någon av följande metoder för att installera det hanterade KLIENT-SDK-paketet för Mobile Apps från NuGet:
-
Visual Studio högerklickar på projektet, klickar du på Hantera NuGet-paket, söker efter
Microsoft.Azure.Mobile.Client
paketet och klickar sedan på Installera. -
Xamarin Studio Högerklicka på projektet, klicka på Lägg till>Lägg till NuGet-paket, sök efter paketet
Microsoft.Azure.Mobile.Client
och klicka sedan på Lägg till paket.
Kom ihåg att lägga till följande using-instruktion i din huvudaktivitetsfil :
using Microsoft.WindowsAzure.MobileServices;
Anteckning
Observera att alla supportpaket som det refereras till i ditt Android-projekt måste ha samma version. SDK:n är Xamarin.Android.Support.CustomTabs
beroende av Android-plattformen, så om ditt projekt använder nyare supportpaket måste du installera det här paketet med den version som krävs direkt för att undvika konflikter.
Gör så här: Arbeta med felsökningssymboler i Visual Studio
Symbolerna för namnområdet Microsoft.Azure.Mobile finns på SymbolSource. Se instruktionerna för SymbolSource för att integrera SymbolSource med Visual Studio.
Skapa Mobile Apps klienten
Följande kod skapar objektet MobileServiceClient som används för att få åtkomst till mobilappens backend-enhet.
var client = new MobileServiceClient("MOBILE_APP_URL");
I föregående kod ersätter du MOBILE_APP_URL
med URL:en för mobilappsserverdel som finns på bladet för mobilappsserverdel i Azure Portal. MobileServiceClient-objektet ska vara en singleton-enhet.
Arbeta med tabeller
Följande avsnitt beskriver hur du söker efter och hämtar poster och ändrar data i tabellen. Följande avsnitt tas upp:
- Skapa en tabellreferens
- Söka i data
- Filtrera returnerade data
- Sortera returnerade data
- Returnera data på sidor
- Välj specifika kolumner
- Leta upp en post efter ID
- Hantera otypade frågor
- Infoga data
- Uppdatera data
- Ta bort data
- Konfliktlösning och optimistisk samtidighet
- Binda till en Windows Användargränssnitt
- Ändra sidstorlek
Gör så här: Skapa en tabellreferens
All kod som kommer åt eller ändrar data i en backend-tabell anropar funktioner i MobileServiceTable
-objektet. Hämta en referens till tabellen genom att anropa metoden GetTable enligt följande:
IMobileServiceTable<TodoItem> todoTable = client.GetTable<TodoItem>();
Det returnerade objektet använder den typade serialiseringsmodellen. En otypad serialiseringsmodell stöds också. I följande exempel skapas en referens till en otypad tabell:
// Get an untyped table reference
IMobileServiceTable untypedTodoTable = client.GetTable("TodoItem");
I otypade frågor måste du ange den underliggande OData-frågesträngen.
Gör så här: Fråga efter data från din mobilapp
I det här avsnittet beskrivs hur du utfärdar frågor till mobilapps-backend, som innehåller följande funktioner:
- Filtrera returnerade data
- Sortera returnerade data
- Returnera data på sidor
- Välj specifika kolumner
- Leta upp data efter ID
Anteckning
En serverdriven sidstorlek tillämpas för att förhindra att alla rader returneras. Växling ser till att standardbegäranden för stora datamängder inte påverkar tjänsten negativt. Om du vill returnera fler än 50 rader använder du Skip
metoden och Take
enligt beskrivningen i Returnera data på sidor.
Gör så här: Filtrera returnerade data
Följande kod visar hur du filtrerar data genom att inkludera en - Where
sats i en fråga. Den returnerar alla objekt från todoTable
vars Complete
egenskap är lika med false
. Funktionen Where tillämpar ett radfiltrerings predikat för frågan mot tabellen.
// This query filters out completed TodoItems and items without a timestamp.
List<TodoItem> items = await todoTable
.Where(todoItem => todoItem.Complete == false)
.ToListAsync();
Du kan visa URI:en för begäran som skickas till backend-datorn med hjälp av programvara för meddelandegranskning, till exempel utvecklarverktyg för webbläsare eller Fiddler. Observera att frågesträngen ändras om du tittar på URI:en för begäran:
GET /tables/todoitem?$filter=(complete+eq+false) HTTP/1.1
Denna OData-begäran översätts till en SQL fråga av Server SDK:
SELECT *
FROM TodoItem
WHERE ISNULL(complete, 0) = 0
Funktionen som skickas till metoden Where
kan ha ett godtyckligt antal villkor.
// This query filters out completed TodoItems where Text isn't null
List<TodoItem> items = await todoTable
.Where(todoItem => todoItem.Complete == false && todoItem.Text != null)
.ToListAsync();
Det här exemplet skulle översättas till en SQL fråga av Server SDK:
SELECT *
FROM TodoItem
WHERE ISNULL(complete, 0) = 0
AND ISNULL(text, 0) = 0
Den här frågan kan också delas upp i flera satser:
List<TodoItem> items = await todoTable
.Where(todoItem => todoItem.Complete == false)
.Where(todoItem => todoItem.Text != null)
.ToListAsync();
De två metoderna är likvärdiga och kan användas synonymt. Det tidigare alternativet – att sammanfoga flera predikat i en fråga – är mer kompakt och rekommenderas.
- Where
satsen stöder åtgärder som översätts till OData-deluppsättningen. Här är några åtgärder:
- Relationsoperatorer (==, !=, <, <=, >, >=),
- Aritmetiska operatorer (+, -, /, *, %)
- Talprecision (Math.Floor, Math.Ceiling),
- Strängfunktioner (Length, Substring, Replace, IndexOf, StartsWith, EndsWith),
- Datumegenskaper (år, månad, dag, timme, minut, sekund),
- Åtkomstegenskaper för ett objekt och
- Uttryck som kombinerar någon av dessa åtgärder.
När du överväger vad Server SDK stöder kan du läsa OData v3-dokumentationen.
Gör så här: Sortera returnerade data
Följande kod visar hur du sorterar data genom att inkludera en OrderBy- eller OrderByDescending-funktion i frågan. Den returnerar objekt todoTable
från sorterade stigande efter Text
fältet.
// Sort items in ascending order by Text field
MobileServiceTableQuery<TodoItem> query = todoTable
.OrderBy(todoItem => todoItem.Text)
List<TodoItem> items = await query.ToListAsync();
// Sort items in descending order by Text field
MobileServiceTableQuery<TodoItem> query = todoTable
.OrderByDescending(todoItem => todoItem.Text)
List<TodoItem> items = await query.ToListAsync();
Gör så här: Returnera data på sidor
Som standard returnerar backend endast de första 50 raderna. Du kan öka antalet returnerade rader genom att anropa metoden Take . Använd Take
tillsammans med metoden Hoppa över för att begära en specifik "sida" av den totala datauppsättningen som returneras av frågan. När följande fråga körs returneras de tre översta objekten i tabellen.
// Define a filtered query that returns the top 3 items.
MobileServiceTableQuery<TodoItem> query = todoTable.Take(3);
List<TodoItem> items = await query.ToListAsync();
Följande ändrade fråga hoppar över de tre första resultaten och returnerar de kommande tre resultaten. Den här frågan skapar den andra "sidan" med data, där sidstorleken är tre objekt.
// Define a filtered query that skips the top 3 items and returns the next 3 items.
MobileServiceTableQuery<TodoItem> query = todoTable.Skip(3).Take(3);
List<TodoItem> items = await query.ToListAsync();
Metoden IncludeTotalCount begär det totala antalet för alla poster som skulle ha returnerats, och ignorerar alla angivna sidnumrerings-/gränssats:
query = query.IncludeTotalCount();
I en verklig app kan du använda frågor som liknar föregående exempel med en sidkontroll eller ett jämförbart användargränssnitt för att navigera mellan sidor.
Anteckning
Om du vill åsidosätta gränsen på 50 rader i en Mobilapp-server måste du också tillämpa EnableQueryAttribute på den offentliga GET-metoden och ange växlingsbeteendet. När det tillämpas på metoden anger följande det högsta antal rader som returneras till 1 000:
[EnableQuery(MaxTop=1000)]
Gör så här: Välj specifika kolumner
Du kan ange vilken uppsättning egenskaper som ska ingå i resultatet genom att lägga till en Select-sats i frågan. Följande kod visar till exempel hur du bara väljer ett fält och hur du väljer och formaterar flera fält:
// Select one field -- just the Text
MobileServiceTableQuery<TodoItem> query = todoTable
.Select(todoItem => todoItem.Text);
List<string> items = await query.ToListAsync();
// Select multiple fields -- both Complete and Text info
MobileServiceTableQuery<TodoItem> query = todoTable
.Select(todoItem => string.Format("{0} -- {1}",
todoItem.Text.PadRight(30), todoItem.Complete ?
"Now complete!" : "Incomplete!"));
List<string> items = await query.ToListAsync();
Alla funktioner som beskrivs hittills är additiva, så vi kan fortsätta att länka dem. Varje länkat anrop påverkar mer av frågan. Ytterligare ett exempel:
MobileServiceTableQuery<TodoItem> query = todoTable
.Where(todoItem => todoItem.Complete == false)
.Select(todoItem => todoItem.Text)
.Skip(3).
.Take(3);
List<string> items = await query.ToListAsync();
Gör så här: Söka efter data efter ID
Funktionen LookupAsync kan användas för att söka efter objekt från databasen med ett visst ID.
// This query filters out the item with the ID of 37BBF396-11F0-4B39-85C8-B319C729AF6D
TodoItem item = await todoTable.LookupAsync("37BBF396-11F0-4B39-85C8-B319C729AF6D");
Gör så här: Köra otypade frågor
När du kör en fråga med ett otypat tabellobjekt måste du uttryckligen ange OData-frågesträngen genom att anropa ReadAsync, som i följande exempel:
// Lookup untyped data using OData
JToken untypedItems = await untypedTodoTable.ReadAsync("$filter=complete eq 0&$orderby=text");
Du får tillbaka JSON-värden som du kan använda som en egenskapsde påse. Mer information om JToken och Newtonsoft Json.NET finns på Json.NET webbplats.
Gör så här: Infoga data i en mobilapps-backend
Alla klienttyper måste innehålla en medlem med namnet ID, vilket som standard är en sträng. Detta ID krävs för att utföra CRUD-åtgärder och för offlinesynkronisering. Följande kod illustrerar hur du använder metoden InsertAsync för att infoga nya rader i en tabell. Parametern innehåller de data som ska infogas som ett .NET-objekt.
await todoTable.InsertAsync(todoItem);
Om ett unikt anpassat ID-värde inte ingår i under todoItem
en infogning genereras ett GUID av servern.
Du kan hämta det genererade ID:t genom att granska objektet när anropet returneras.
Om du vill infoga otypade data kan du dra nytta av Json.NET:
JObject jo = new JObject();
jo.Add("Text", "Hello World");
jo.Add("Complete", false);
var inserted = await table.InsertAsync(jo);
Här är ett exempel på hur du använder en e-postadress som ett unikt sträng-ID:
JObject jo = new JObject();
jo.Add("id", "myemail@emaildomain.com");
jo.Add("Text", "Hello World");
jo.Add("Complete", false);
var inserted = await table.InsertAsync(jo);
Arbeta med ID-värden
Mobile Apps har stöd för unika anpassade strängvärden för tabellens ID-kolumn . Med ett strängvärde kan program använda anpassade värden, till exempel e-postadresser eller användarnamn för ID:t. Sträng-ID ger dig följande fördelar:
- ID genereras utan att göra en tur och retur till databasen.
- Poster är enklare att sammanfoga från olika tabeller eller databaser.
- ID-värden kan integreras bättre med ett programs logik.
När ett sträng-ID-värde inte har angetts för en infogad post genererar mobilapps-backend ett unikt värde för ID:t. Du kan använda metoden Guid.NewGuid för att generera dina egna ID-värden, antingen på klienten eller i backend.
JObject jo = new JObject();
jo.Add("id", Guid.NewGuid().ToString("N"));
Gör så här: Ändra data i en mobilapps-backend
Följande kod illustrerar hur du använder metoden UpdateAsync för att uppdatera en befintlig post med samma ID med ny information. Parametern innehåller de data som ska uppdateras som ett .NET-objekt.
await todoTable.UpdateAsync(todoItem);
Om du vill uppdatera otypade data kan du dra nytta av Json.NET på följande sätt:
JObject jo = new JObject();
jo.Add("id", "37BBF396-11F0-4B39-85C8-B319C729AF6D");
jo.Add("Text", "Hello World");
jo.Add("Complete", false);
var inserted = await table.UpdateAsync(jo);
Ett id
fält måste anges när du gör en uppdatering. Backend använder fältet för id
att identifiera vilken rad som ska uppdateras. Fältet id
kan hämtas från resultatet av anropet InsertAsync
. En ArgumentException
utlöses om du försöker uppdatera ett objekt utan att ange id
värdet.
Gör så här: Ta bort data i en mobilapps-backend
Följande kod visar hur du använder metoden DeleteAsync för att ta bort en befintlig instans. Instansen identifieras av fältet id
som anges på todoItem
.
await todoTable.DeleteAsync(todoItem);
Om du vill ta bort otypade data kan du dra nytta Json.NET på följande sätt:
JObject jo = new JObject();
jo.Add("id", "37BBF396-11F0-4B39-85C8-B319C729AF6D");
await table.DeleteAsync(jo);
När du gör en borttagningsbegäran måste ett ID anges. Andra egenskaper skickas inte till tjänsten eller ignoreras i tjänsten. Resultatet av ett anrop DeleteAsync
är vanligtvis null
. ID:t som ska överföras kan hämtas från resultatet av anropet InsertAsync
. En MobileServiceInvalidOperationException
visas när du försöker ta bort ett objekt utan att ange id
fältet.
Gör så här: Använd optimistisk samtidighet för konfliktlösning
Två eller flera klienter kan skriva ändringar till samma objekt samtidigt. Utan konfliktidentifiering skulle den senaste skriven skriva över alla tidigare uppdateringar. Optimistisk samtidighetskontroll förutsätter att varje transaktion kan genomföra och därför inte använder någon resurslåsning. Innan du utför en transaktion verifierar optimistisk samtidighetskontroll att inga andra transaktioner har ändrat data. Om data har ändrats återställs den transaktion som genomförs.
Mobile Apps stöd för optimistisk version
samtidighetskontroll genom att spåra ändringar i varje objekt med hjälp av systemegenskapskolumnen som har definierats för varje tabell i mobilapps-backend. Varje gång en post uppdateras Mobile Apps anger egenskapen version
för posten till ett nytt värde. Under varje uppdateringsbegäran jämförs version
egenskapen för den post som ingår i begäran med samma egenskap för posten på servern. Om versionen som skickades med begäran inte matchar backend-versionen gäller ett undantag i klientbiblioteket MobileServicePreconditionFailedException<T>
. Den typ som ingår i undantaget är posten från serverversionen som innehåller serverversionen av posten. Programmet kan sedan använda den här informationen för version
att bestämma om uppdateringsbegäran ska köras igen med rätt värde från backend för att genomföra ändringar.
Definiera en kolumn i tabellklassen för systemegenskapen version
för att aktivera optimistisk samtidighet. Till exempel:
public class TodoItem
{
public string Id { get; set; }
[JsonProperty(PropertyName = "text")]
public string Text { get; set; }
[JsonProperty(PropertyName = "complete")]
public bool Complete { get; set; }
// *** Enable Optimistic Concurrency *** //
[JsonProperty(PropertyName = "version")]
public string Version { set; get; }
}
Program som använder otypade tabeller aktiverar optimistisk samtidighet genom att ange Version
flaggan i SystemProperties
tabellen enligt följande.
//Enable optimistic concurrency by retrieving version
todoTable.SystemProperties |= MobileServiceSystemProperties.Version;
Förutom att aktivera optimistisk samtidighet måste du även fånga upp undantaget MobileServicePreconditionFailedException<T>
i koden när du anropar UpdateAsync. Lös konflikten genom att tillämpa rätt på den version
uppdaterade posten och anropa UpdateAsync med den lösta posten. Följande kod visar hur du löser en skrivkonflikt när den har identifierats:
private async void UpdateToDoItem(TodoItem item)
{
MobileServicePreconditionFailedException<TodoItem> exception = null;
try
{
//update at the remote table
await todoTable.UpdateAsync(item);
}
catch (MobileServicePreconditionFailedException<TodoItem> writeException)
{
exception = writeException;
}
if (exception != null)
{
// Conflict detected, the item has changed since the last query
// Resolve the conflict between the local and server item
await ResolveConflict(item, exception.Item);
}
}
private async Task ResolveConflict(TodoItem localItem, TodoItem serverItem)
{
//Ask user to choose the resolution between versions
MessageDialog msgDialog = new MessageDialog(
String.Format("Server Text: \"{0}\" \nLocal Text: \"{1}\"\n",
serverItem.Text, localItem.Text),
"CONFLICT DETECTED - Select a resolution:");
UICommand localBtn = new UICommand("Commit Local Text");
UICommand ServerBtn = new UICommand("Leave Server Text");
msgDialog.Commands.Add(localBtn);
msgDialog.Commands.Add(ServerBtn);
localBtn.Invoked = async (IUICommand command) =>
{
// To resolve the conflict, update the version of the item being committed. Otherwise, you will keep
// catching a MobileServicePreConditionFailedException.
localItem.Version = serverItem.Version;
// Updating recursively here just in case another change happened while the user was making a decision
UpdateToDoItem(localItem);
};
ServerBtn.Invoked = async (IUICommand command) =>
{
RefreshTodoItems();
};
await msgDialog.ShowAsync();
}
Mer information finns i avsnittet offline-Data Sync i Azure Mobile Apps.
Gör så här: Mobile Apps data till Windows ett användargränssnitt
Det här avsnittet visar hur du visar returnerade dataobjekt med hjälp av gränssnittselement i Windows app. Följande exempelkod binder till källan för listan med en fråga efter ofullständiga objekt. MobileServiceCollection skapar en Mobile Apps-medveten bindningssamling.
// This query filters out completed TodoItems.
MobileServiceCollection<TodoItem, TodoItem> items = await todoTable
.Where(todoItem => todoItem.Complete == false)
.ToCollectionAsync();
// itemsControl is an IEnumerable that could be bound to a UI list control
IEnumerable itemsControl = items;
// Bind this to a ListBox
ListBox lb = new ListBox();
lb.ItemsSource = items;
Vissa kontroller i den hanterade körningen stöder ett gränssnitt som kallas ISupportIncrementalLoading. Med det här gränssnittet kan kontroller begära extra data när användaren rullar. Det finns inbyggt stöd för det här gränssnittet för universella Windows-appar via MobileServiceIncrementalLoadingCollection, som automatiskt hanterar anropen från kontrollerna. Använd MobileServiceIncrementalLoadingCollection
i Windows på följande sätt:
MobileServiceIncrementalLoadingCollection<TodoItem,TodoItem> items;
items = todoTable.Where(todoItem => todoItem.Complete == false).ToIncrementalLoadingCollection();
ListBox lb = new ListBox();
lb.ItemsSource = items;
Om du vill använda den nya samlingen Windows Phone 8- och Silverlight-appar använder du tilläggsmetoderna ToCollection
på IMobileServiceTableQuery<T>
och IMobileServiceTable<T>
. Anropa för att läsa in LoadMoreItemsAsync()
data.
MobileServiceCollection<TodoItem, TodoItem> items = todoTable.Where(todoItem => todoItem.Complete==false).ToCollection();
await items.LoadMoreItemsAsync();
När du använder samlingen som skapats genom att anropa ToCollectionAsync
eller ToCollection
får du en samling som kan bindas till ui-kontroller. Den här samlingen är växlingsmedveten. Eftersom samlingen läser in data från nätverket misslyckas ibland inläsningen. Om du vill hantera sådana fel åsidosätter du metoden OnException
på för MobileServiceIncrementalLoadingCollection
att hantera undantag som är resultatet av anrop till LoadMoreItemsAsync
.
Överväg om tabellen har många fält men du bara vill visa några av dem i din kontroll. Du kan använda vägledningen i föregående avsnitt "Välj specifika kolumner" för att välja specifika kolumner som ska visas i användargränssnittet.
Ändra sidstorleken
Azure Mobile Apps returnerar högst 50 objekt per begäran som standard. Du kan ändra växlingsstorleken genom att öka den maximala sidstorleken på både klienten och servern. Om du vill öka den begärda sidstorleken anger du PullOptions
när du använder PullAsync()
:
PullOptions pullOptions = new PullOptions
{
MaxPageSize = 100
};
Förutsatt att du har gjort PageSize
lika med eller större än 100 inom servern returnerar en begäran upp till 100 objekt.
Arbeta med offlinetabeller
Offlinetabeller använder ett lokalt SQLite-lager för att lagra data för användning när de är offline. Alla tabellåtgärder utförs mot det lokala SQLite-arkivet i stället för fjärrserverarkivet. Om du vill skapa en offlinetabell förbereder du först projektet:
I Visual Studio högerklickar du på lösningen Hantera NuGet-paket för lösning... och söker sedan efter och installerar Microsoft.Azure.Mobile.Client.SQLiteStore NuGet-paketet > för alla projekt i lösningen.
(Valfritt) För att Windows enheter installerar du något av följande SQLite-körningspaket:
- Windows 8.1 Runtime: Installera SQLite för Windows 8.1.
- Windows Phone 8.1: Installera SQLite för Windows Phone 8.1.
- Universell Windows-plattform Installera SQLite för Universal Windows.
(Valfritt). För Windows-enheter > klickar du på Referenser Lägg till referens..., expanderar Windows-mappen>Tillägg och aktiverar sedan lämplig SQLite för Windows SDK tillsammans med Visual C++ 2013 Runtime för Windows SDK. SQLite SDK-namnen varierar något med varje Windows plattform.
Innan du kan skapa en tabellreferens måste du förbereda det lokala arkivet:
var store = new MobileServiceSQLiteStore(Constants.OfflineDbPath);
store.DefineTable<TodoItem>();
//Initializes the SyncContext using the default IMobileServiceSyncHandler.
await this.client.SyncContext.InitializeAsync(store);
Lagringsinitieringen görs vanligtvis omedelbart efter att klienten har skapats. OfflineDbPath bör vara ett filnamn som lämpar sig för användning på alla plattformar som du stöder. Om sökvägen är en fullständigt kvalificerad sökväg (det vill säga att den börjar med ett snedstreck) används den sökvägen. Om sökvägen inte är fullständigt kvalificerad placeras filen på en plattformsspecifik plats.
- För iOS- och Android-enheter är standardsökvägen mappen "Personliga filer".
- För Windows enheter är standardsökvägen den programspecifika mappen "AppData".
En tabellreferens kan hämtas med hjälp av GetSyncTable<>
metoden :
var table = client.GetSyncTable<TodoItem>();
Du behöver inte autentisera för att använda en offlinetabell. Du behöver bara autentisera när du kommunicerar med backend-tjänsten.
Synkronisera en offlinetabell
Offlinetabeller synkroniseras inte med backend som standard. Synkroniseringen är uppdelad i två delar. Du kan push-överför ändringar separat från att hämta nya objekt. Här är en typisk synkroniseringsmetod:
public async Task SyncAsync()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
await this.client.SyncContext.PushAsync();
await this.todoTable.PullAsync(
//The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
//Use a different query name for each unique query in your program
"allTodoItems",
this.todoTable.CreateQuery());
}
catch (MobileServicePushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}
// Simple error/conflict handling. A real application would handle the various errors like network conditions,
// server conflicts and others via the IMobileServiceSyncHandler.
if (syncErrors != null)
{
foreach (var error in syncErrors)
{
if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
{
//Update failed, reverting to server's copy.
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// Discard local change.
await error.CancelAndDiscardItemAsync();
}
Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
}
}
}
Om det första argumentet till PullAsync
är null används inte inkrementell synkronisering. Varje synkroniseringsåtgärd hämtar alla poster.
SDK:n utför en implicit innan PushAsync()
posterna dras.
Konflikthantering sker på en PullAsync()
metod. Du kan hantera konflikter på samma sätt som onlinetabeller. Konflikten skapas när anropas PullAsync()
i stället för under infogning, uppdatering eller borttagning. Om flera konflikter inträffar paketeras de i en enda MobileServicePushFailedException. Hantera varje fel separat.
Arbeta med ett anpassat API
Med ett anpassat API kan du definiera anpassade slutpunkter som exponerar serverfunktioner som inte mappar till en infognings-, uppdaterings-, borttagnings- eller läsåtgärd. Genom att använda ett anpassat API kan du få mer kontroll över meddelanden, inklusive läsning och inställning av HTTP-meddelandehuvuden och definiera ett annat meddelandetextformat än JSON.
Du anropar ett anpassat API genom att anropa någon av metoderna InvokeApiAsync på klienten. Följande kodrad skickar till exempel en POST-begäran till completeAll-API :et på backend:en:
var result = await client.InvokeApiAsync<MarkAllResult>("completeAll", System.Net.Http.HttpMethod.Post, null);
Det här formuläret är ett typbestämt metod-anrop och kräver att returtypen MarkAllResult har definierats. Både skrivna och otypade metoder stöds.
Metoden InvokeApiAsync() förbereder "/api/" till det API som du vill anropa om inte API:et börjar med ett "/". Till exempel:
-
InvokeApiAsync("completeAll",...)
anropar /api/completeAll på backend -
InvokeApiAsync("/.auth/me",...)
anropar /.auth/me på backend
Du kan använda InvokeApiAsync för att anropa alla WebAPI, inklusive de WebAPIs som inte har definierats med Azure Mobile Apps. När du använder InvokeApiAsync(), skickas lämpliga huvuden, inklusive autentiseringshuvuden, med begäran.
Autentisera användare
Mobile Apps stöder autentisering och auktorisering av appanvändare med hjälp av olika externa identitetsproviders: Facebook, Google, Microsoft-konto, Twitter och Azure Active Directory. Du kan ange behörigheter för tabeller för att begränsa åtkomsten för specifika åtgärder till endast autentiserade användare. Du kan också använda identiteten för autentiserade användare för att implementera auktoriseringsregler i serverskript. Mer information finns i självstudierna Lägg till autentisering till din app.
Två autentiseringsflöden stöds: klient-hanterat ochserver-hanterat flöde. Det server-hanterade flödet ger den enklaste autentiseringsupplevelsen eftersom det förlitar sig på providerns webbautentiseringsgränssnitt. Det klient-hanterade flödet möjliggör djupare integrering med enhetsspecifika funktioner eftersom det förlitar sig på providerspecifika enhetsspecifika SDK:er.
Anteckning
Vi rekommenderar att du använder ett klient-hanterat flöde i dina produktionsappar.
Om du vill konfigurera autentisering måste du registrera din app med en eller flera identitetsproviders. Identitetsprovidern genererar ett klient-ID och en klienthemlighet för din app. Dessa värden anges sedan i serveruppsättningen för att aktivera Azure App Service autentisering/auktorisering. Mer information finns i de detaljerade anvisningarna i självstudien Lägga till autentisering i din app.
Följande avsnitt tas upp i det här avsnittet:
Klient-hanterad autentisering
Din app kan oberoende kontakta identitetsprovidern och sedan ange den returnerade token under inloggningen med din backend. Med det här klientflödet kan du tillhandahålla enkel inloggning för användare eller hämta ytterligare användardata från identitetsprovidern. Klientflödesautentisering är att föredra framför att använda ett serverflöde eftersom identitetsproviderns SDK ger en mer inbyggd UX-känsla och möjliggör ytterligare anpassning.
Exempel finns för följande autentiseringsmönster för klientflöde:
Autentisera användare med Active Directory-autentiseringsbibliotek
Du kan använda Active Directory-autentiseringsbibliotek (ADAL) för att initiera användarautentisering från klienten med hjälp Azure Active Directory autentisering.
Konfigurera mobilappens backend för AAD inloggning genom att följa självstudien Så här konfigurerar du App Service för Active Directory-inloggning. Se till att slutföra det valfria steget för att registrera ett inbyggt klientprogram.
I Visual Studio eller Xamarin Studio öppnar du projektet och lägger till en referens till
Microsoft.IdentityModel.Clients.ActiveDirectory
NuGet-paketet. Ta med förhandsversioner när du söker.Lägg till följande kod i ditt program enligt den plattform som du använder. Gör följande ersättningar i var och en:
Ersätt INSERT-AUTHORITY-HERE med namnet på den klientorganisation där du etablerade programmet. Formatet ska vara https://login.microsoftonline.com/contoso.onmicrosoft.com. Det här värdet kan kopieras från fliken Domän i Azure Active Directory i Azure Portal.
Ersätt INSERT-RESOURCE-ID-HERE med klient-ID:t för din mobilapps backend. Du kan hämta klient-ID:t på fliken Avancerat under Azure Active Directory Inställningar på portalen.
Ersätt INSERT-CLIENT-ID-HERE med det klient-ID som du kopierade från det interna klientprogrammet.
Ersätt INSERT-REDIRECT-URI-HERE med webbplatsens /.auth/login/done-slutpunkt med hjälp av HTTPS-schemat. Det här värdet bör likna https://contoso.azurewebsites.net/.auth/login/done.
Koden som behövs för varje plattform följer:
Windows:
private MobileServiceUser user; private async Task AuthenticateAsync() { string authority = "INSERT-AUTHORITY-HERE"; string resourceId = "INSERT-RESOURCE-ID-HERE"; string clientId = "INSERT-CLIENT-ID-HERE"; string redirectUri = "INSERT-REDIRECT-URI-HERE"; while (user == null) { string message; try { AuthenticationContext ac = new AuthenticationContext(authority); AuthenticationResult ar = await ac.AcquireTokenAsync(resourceId, clientId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto, false) ); JObject payload = new JObject(); payload["access_token"] = ar.AccessToken; user = await App.MobileService.LoginAsync( MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload); message = string.Format("You are now logged in - {0}", user.UserId); } catch (InvalidOperationException) { message = "You must log in. Login Required"; } var dialog = new MessageDialog(message); dialog.Commands.Add(new UICommand("OK")); await dialog.ShowAsync(); } }
Xamarin.iOS
private MobileServiceUser user; private async Task AuthenticateAsync(UIViewController view) { string authority = "INSERT-AUTHORITY-HERE"; string resourceId = "INSERT-RESOURCE-ID-HERE"; string clientId = "INSERT-CLIENT-ID-HERE"; string redirectUri = "INSERT-REDIRECT-URI-HERE"; try { AuthenticationContext ac = new AuthenticationContext(authority); AuthenticationResult ar = await ac.AcquireTokenAsync(resourceId, clientId, new Uri(redirectUri), new PlatformParameters(view)); JObject payload = new JObject(); payload["access_token"] = ar.AccessToken; user = await client.LoginAsync( MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload); } catch (Exception ex) { Console.Error.WriteLine(@"ERROR - AUTHENTICATION FAILED {0}", ex.Message); } }
Xamarin.Android
private MobileServiceUser user; private async Task AuthenticateAsync() { string authority = "INSERT-AUTHORITY-HERE"; string resourceId = "INSERT-RESOURCE-ID-HERE"; string clientId = "INSERT-CLIENT-ID-HERE"; string redirectUri = "INSERT-REDIRECT-URI-HERE"; try { AuthenticationContext ac = new AuthenticationContext(authority); AuthenticationResult ar = await ac.AcquireTokenAsync(resourceId, clientId, new Uri(redirectUri), new PlatformParameters(this)); JObject payload = new JObject(); payload["access_token"] = ar.AccessToken; user = await client.LoginAsync( MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload); } catch (Exception ex) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.SetMessage(ex.Message); builder.SetTitle("You must log in. Login Required"); builder.Create().Show(); } } protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data); }
En Sign-On med en token från Facebook eller Google
Du kan använda klientflödet som det visas i det här kodfragmentet för Facebook eller Google.
var token = new JObject();
// Replace access_token_value with actual value of your access token obtained
// using the Facebook or Google SDK.
token.Add("access_token", "access_token_value");
private MobileServiceUser user;
private async Task AuthenticateAsync()
{
while (user == null)
{
string message;
try
{
// Change MobileServiceAuthenticationProvider.Facebook
// to MobileServiceAuthenticationProvider.Google if using Google auth.
user = await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token);
message = string.Format("You are now logged in - {0}", user.UserId);
}
catch (InvalidOperationException)
{
message = "You must log in. Login Required";
}
var dialog = new MessageDialog(message);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}
Server-hanterad autentisering
När du har registrerat din identitetsprovider anropar du metoden LoginAsync på [MobileServiceClient] med värdet MobileServiceAuthenticationProvider för din provider. Följande kod initierar till exempel inloggning med ett serverflöde med hjälp av Facebook.
private MobileServiceUser user;
private async System.Threading.Tasks.Task Authenticate()
{
while (user == null)
{
string message;
try
{
user = await client
.LoginAsync(MobileServiceAuthenticationProvider.Facebook);
message =
string.Format("You are now logged in - {0}", user.UserId);
}
catch (InvalidOperationException)
{
message = "You must log in. Login Required";
}
var dialog = new MessageDialog(message);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}
Om du använder en annan identitetsprovider än Facebook ändrar du värdet för MobileServiceAuthenticationProvider till värdet för din leverantör.
I ett serverflöde Azure App Service hanterar OAuth-autentiseringsflödet genom att visa inloggningssidan för den valda providern. När identitetsprovidern returnerar Azure App Service en App Service autentiseringstoken. Metoden LoginAsync returnerar en MobileServiceUser, som tillhandahåller både UserId för den autentiserade användaren och MobileServiceAuthenticationToken som en JSON-webbtoken (JWT). Den här token kan cachelagras och återanvändas tills den upphör att gälla. Mer information finns i Cachelagring autentiseringstoken.
När du använder Xamarin (Android eller iOS) används Xamarin.Essentials WebAuthenticator. Du måste skicka standardkontexten (Android) eller UIViewController (iOS) till LoginAsync
metoden . Dessutom måste du hantera returen från webbutentören. I Android hanteras detta i MainActivity.cs
:
public override void OnResume()
{
base.OnResume();
Xamarin.Essentials.Platform.OnResume();
}
I iOS hanteras detta i AppDelegate.cs:
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
if (client.ResumeWithURL(app, url, options))
return true;
return base.OpenUrl(app, url, options);
}
Cachelagring autentiseringstoken
I vissa fall kan anropet till inloggningsmetoden undvikas efter den första lyckade autentiseringen genom att lagra autentiseringstoken från providern. Microsoft Store- och UWP-appar kan använda PasswordVault för att cachelagra den aktuella autentiseringstoken efter en lyckad inloggning, enligt följande:
await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook);
PasswordVault vault = new PasswordVault();
vault.Add(new PasswordCredential("Facebook", client.currentUser.UserId,
client.currentUser.MobileServiceAuthenticationToken));
UserId-värdet lagras som användarnamnet för autentiseringsnamnet och token lagras som lösenord. Vid efterföljande start kan du kontrollera PasswordVault för cachelagrade autentiseringsuppgifter. I följande exempel används cachelagrade autentiseringsuppgifter när de hittas och försöker på annat sätt autentisera igen med backend:en:
// Try to retrieve stored credentials.
var creds = vault.FindAllByResource("Facebook").FirstOrDefault();
if (creds != null)
{
// Create the current user from the stored credentials.
client.currentUser = new MobileServiceUser(creds.UserName);
client.currentUser.MobileServiceAuthenticationToken =
vault.Retrieve("Facebook", creds.UserName).Password;
}
else
{
// Regular login flow and cache the token as shown above.
}
När du loggar ut en användare måste du även ta bort lagrade autentiseringsuppgifter på följande sätt:
client.Logout();
vault.Remove(vault.Retrieve("Facebook", client.currentUser.UserId));
Xamarin-appar använder API:erna för Xamarin.Auth för att lagra autentiseringsuppgifter i ett kontoobjekt på ett säkert sätt. Ett exempel på hur du använder dessa API:er finns i kodfilen AuthStore.cs i exemplet contosoMoments-fotodelning.
När du använder klientbaserad autentisering kan du även cachelagra den åtkomsttoken som hämtas från din provider, till exempel Facebook eller Twitter. Denna token kan anges för att begära en ny autentiseringstoken från server slutet, enligt följande:
var token = new JObject();
// Replace <your_access_token_value> with actual value of your access token
token.Add("access_token", "<your_access_token_value>");
// Authenticate using the access token.
await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token);
Push-meddelanden
I följande avsnitt går vi igenom push-meddelanden:
- Registrera dig för push-meddelanden
- Hämta ett Microsoft Store-PAKET-SID
- Registrera med plattformsoberoende mallar
Gör så här: Registrera dig för push-meddelanden
Med Mobile Apps-klienten kan du registrera dig för push-meddelanden med Azure Notification Hubs. När du registrerar dig får du en referens som du får från den plattformsspecifika push-meddelandetjänsten (PNS). Sedan anger du det här värdet tillsammans med eventuella taggar när du skapar registreringen. Följande kod registrerar din Windows för push-meddelanden med Windows Notification Service (WNS):
private async void InitNotificationsAsync()
{
// Request a push notification channel.
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
// Register for notifications using the new channel.
await MobileService.GetPush().RegisterNativeAsync(channel.Uri, null);
}
Om du push-pushar till WNS måste du hämta ett Microsoft Store-SID. Mer information om hur Windows appar, inklusive hur du registrerar dig för mallregistreringar, finns i Lägga till push-meddelanden i din app.
Det går inte att begära taggar från klienten. Taggbegäranden tas bort tyst från registreringen.
Om du vill registrera din enhet med taggar skapar du ett anpassat API som använder API:Notification Hubs för att utföra registreringen åt dig. Anropa det anpassade API:et i stället för RegisterNativeAsync()
metoden .
Gör så här: Skaffa ett Microsoft Store-paket-SID
Ett paket-SID krävs för att aktivera push-meddelanden i Microsoft Store appar. Om du vill ta emot ett paket-SID registrerar du ditt program med Microsoft Store.
Så här hämtar du det här värdet:
- I Visual Studio Solution Explorer högerklickar du på Microsoft Store appprojektet och klickar på StoreAssociera>app med Store....
- I guiden klickar du på Nästa, loggar in med Microsoft-konto, skriver ett namn för din app i Reservera ett nytt appnamn och klickar sedan på Reservera.
- När appregistreringen har skapats väljer du appnamnet, klickar på Nästa och klickar sedan på Associera.
- Logga in på Windows Dev Center ditt Microsoft-konto. Under Mina appar klickar du på den appregistrering som du skapade.
- Klicka på ApphanteringAppidentitet> och bläddra sedan ned för att hitta ditt paket-SID.
Många användningsområden för paket-SID behandlar det som en URI, i vilket fall du måste använda ms-app:// som schema. Anteckna versionen av ditt paket-SID som bildas genom att det här värdet sammanfogas som ett prefix.
Xamarin-appar kräver viss ytterligare kod för att kunna registrera en app som körs på iOS- eller Android-plattformar. Mer information finns i avsnittet för din plattform:
Gör så här: Registrera push-mallar för att skicka plattformsoberoende meddelanden
Om du vill registrera mallar använder du RegisterAsync()
metoden med mallarna på följande sätt:
JObject templates = myTemplates();
MobileService.GetPush().RegisterAsync(channel.Uri, templates);
Mallarna ska vara JObject
av olika typer och kan innehålla flera mallar i följande JSON-format:
public JObject myTemplates()
{
// single template for Windows Notification Service toast
var template = "<toast><visual><binding template=\"ToastText01\"><text id=\"1\">$(message)</text></binding></visual></toast>";
var templates = new JObject
{
["generic-message"] = new JObject
{
["body"] = template,
["headers"] = new JObject
{
["X-WNS-Type"] = "wns/toast"
},
["tags"] = new JArray()
},
["more-templates"] = new JObject {...}
};
return templates;
}
Metoden RegisterAsync() accepterar även sekundära paneler:
MobileService.GetPush().RegisterAsync(string channelUri, JObject templates, JObject secondaryTiles);
Alla taggar tas bort under registreringen av säkerhetsskäl. Information om hur du lägger till taggar i installationer eller mallar i installationer finns i [Arbeta med SDK för .NET-serverserver för Azure Mobile Apps].
Information om hur du skickar meddelanden med hjälp av dessa registrerade mallar finns i Notification Hubs API:er.
Diverse ämnen
Gör så här: Hantera fel
När ett fel inträffar i backend-klienten träffar klient-SDK:n en MobileServiceInvalidOperationException
. I följande exempel visas hur du hanterar ett undantag som returneras av backend:en:
private async void InsertTodoItem(TodoItem todoItem)
{
// This code inserts a new TodoItem into the database. When the operation completes
// and App Service has assigned an Id, the item is added to the CollectionView
try
{
await todoTable.InsertAsync(todoItem);
items.Add(todoItem);
}
catch (MobileServiceInvalidOperationException e)
{
// Handle error
}
}
Ett annat exempel på hur du hanterar felvillkor finns i Mobile Apps Files Sample. Exemplet LoggingHandler innehåller en loggningsdelegathanterare för att logga begäranden som görs till backend.
Gör så här: Anpassa begärandehuvuden
För att stödja ditt specifika appscenario kan du behöva anpassa kommunikationen med mobilapps-backend. Du kanske till exempel vill lägga till ett anpassat huvud för varje utgående begäran eller till och med ändra svarsstatuskoder. Du kan använda en anpassad DelegatingHandler, som i följande exempel:
public async Task CallClientWithHandler()
{
MobileServiceClient client = new MobileServiceClient("AppUrl", new MyHandler());
IMobileServiceTable<TodoItem> todoTable = client.GetTable<TodoItem>();
var newItem = new TodoItem { Text = "Hello world", Complete = false };
await todoTable.InsertAsync(newItem);
}
public class MyHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Change the request-side here based on the HttpRequestMessage
request.Headers.Add("x-my-header", "my value");
// Do the request
var response = await base.SendAsync(request, cancellationToken);
// Change the response-side here based on the HttpResponseMessage
// Return the modified response
return response;
}
}