cowinr
8/3/2019 - 9:34 AM

App Service

# Set up deployment user
az webapp deployment user set --user-name ric01 --password Qovtpdpgy9!

# Resource group for app
az group create --name apiapp --location "North Europe"

# and the app service plan
az appservice plan create --name api-plan --resource-group apiapp --sku FREE

# webapp with local git deployment
az webapp create --resource-group apiapp --plan api-plan --name ric-api-app --deployment-local-git
# returns json with:
# "deploymentLocalGitUrl": "https://ric01@ric-api-app.scm.azurewebsites.net/ric-api-app.git"

# Add an Azure remote to your local Git repository
git remote add azure https://ric01@ric-api-app.scm.azurewebsites.net/ric-api-app.git

# Go to http://ric-api-app.azurewebsites.net/swagger

# enable CORS to your client's URL
az resource update --name web --resource-group apiapp --namespace Microsoft.Web --resource-type config --parent sites/ric-api-app --set properties.cors.allowedOrigins="['http://localhost:64619']" --api-version 2015-06-01
# You can set more than one client URL in properties.cors.allowedOrigins ("['URL1','URL2',...]")
--set properties.cors.allowedOrigins="['http://localhost:64619', 'URL2']"
# You can also enable all client URLs with "['*']"
--set properties.cors.allowedOrigins="['*']"

Authentication flow

  • Without provider SDK: Application delegates federated sign-in to App Service.
  • With provider SDK: Application signs users in to the provider manually and then submits the authentication token to App Service for validation.

Without provider SDK:

  1. Sign user in: Redirects client to /.auth/login/<provider>
  2. Post-authentication: Provider redirects client to /.auth/login/<provider>/callback
  3. Establish authenticated session: App Service adds authenticated cookie to response.
  4. Serve authenticated content: Client includes authentication cookie in subsequent requests
// Process queue messages
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;

namespace WebJobsSDKSample
{
    public class Functions
    {
        // queue message will be a blob name
        // use the blob name to find and read a blob
        // write a copy of the blob
        public static void ProcessQueueMessage(
            [QueueTrigger("queue")] string message,
            [Blob("container/{queueTrigger}", FileAccess.Read)] Stream myBlob,
            [Blob("container/copy-{queueTrigger}", FileAccess.Write)] Stream outputBlob,
            ILogger logger)
        {
            logger.LogInformation($"Blob name:{message} \n Size: {myBlob.Length} bytes");
            myBlob.CopyTo(outputBlob);
        }
    }
}

To use these features in your app, you initialize a SyncContext to a local store. Then reference your table through the IMobileServiceSyncTable interface. SQLite is used as the local store on the device.

Key Operations

// Set up store
var store = new MobileServiceSQLiteStore(path);
store.DefineTable<ToDoItem>();
await client.SyncContext.InitializeAsync(store);

// Push, Pull, Purge
await client.SyncContext.PushAsync() | PullAsync("allTodoItems", toDoTable.CreateQuery()) | PurgeAsync(...)

The DefineTable method creates a table in the local store that matches the fields in the provided type, ToDoItem:

// ToDoActivity.cs
private async Task InitLocalStoreAsync("blobby")
{
    // Note client reference is
    // MobileServiceClient client;

    // new code to initialize the SQLite store
    string path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), localDbFilename);
    var store = new MobileServiceSQLiteStore(path);
    store.DefineTable<ToDoItem>();

    // Uses the default conflict handler, which fails on conflict
    await client.SyncContext.InitializeAsync(store);
}

The toDoTable member is a IMobileServiceSyncTable (instead of IMobileServiceTable). The IMobileServiceSyncTable directs all create, read, update, and delete (CRUD) table operations to the local store database.

Changes are pushed to the backend by calling IMobileServiceSyncContext.PushAsync():

await client.SyncContext.PushAsync();

// query ID (allTodoItems) is used for incremental sync
await toDoTable.PullAsync("allTodoItems", toDoTable.CreateQuery());

// just sync some records
await todoTable.PullAsync("todoItems" + userid, syncTable.Where(u => u.UserId == userid));

Purge with IMobileServiceSyncTable.PurgeAsync(...).