Cnam Azure
ZeCloud
17/01/2014
Windows Azure Mobile Services
Multi-Platform Apps
You don’t need a different Mobile Service
for each platform!
Connect them all!
Cross-Platform Support
Cross-Platform Support
Multi-Device Push
Windows Store

Single Platform Push Notifications
push.wns.sendToastText04(item.channel, {text1: text}, … );
Windows Phone...
Multi-Platform Push Notifications

function sendNotifications() {

var deviceInfoTable = tables.getTable('DeviceInfo');

d...
Don’t forget to check the response on error
(or getFeedback for APNS)
Also, check out
Delivering Push Notifications to Mil...
Virtual Tables
Create a table
Use it’s endpoint
Don’t call request.Execute
Custom API
•
•
•
•
•
•
•

•
Custom API Demo
Talking to Azure Storage
It’s doable
It’s not perfect

Scripts
and the Azure module
Reading Tables
var azure = require('azure');
function read(query, user, request) {
var accountName = 'accountname';
var ac...
var azure = require('azure');

Reading Table Rows

function read(query, user, request) {
var accountName = 'accountname';
...
var azure = require('azure');
function insert(item, user, request) {

Creating Containers

var accountName = 'accountname'...
Reading and “Creating” Blobs

var azure = require('azure'), qs = require('querystring');
function insert(item, user, reque...
Storage Demo
Talking REST
http://Mobileservice.azure-mobile.net/tables/*

Action

HTTP Verb

URL Suffix

Create

POST

/TodoItem

Retrieve

GET

/To...
JSON Value

T-SQL Type

Numeric values (integer,
decimal, floating point)

Float

Boolean

Bit

DateTime

DateTimeOffset(3...
Postman
&
Runscope Demo
Sending Emails
//var crypto = require('crypto');
//item.tempId = new Buffer(crypto.randomBytes(16)).toString('hex');

Sending an Email

f...
Setting up SendGrid Demo
The CLI
SOME

It’s awe
CLI Demo
Service Filters and DelegatingHandlers
Client side
Intercepts requests
Intercepts responses
Sending Version Info with Each Request
- (void)handleRequest:(NSURLRequest *)request next:(MSFilterNextBlock)next response...
DelegatingHandlers are Service Filters

public static MobileServiceClient MobileService = new MobileServiceClient(
"https:...
Script Versioning
Checking the Version in Scripts

function insert(item, user, request) {

if (request.parameters.build < 2.0) {
item.descri...
For more on versioning, check out
Going Live and Beyond with Windows
Azure Mobile Services
Friday @ 10:30 am
Talking Twitter
v1 is dead
v1.1 is hard
function generateOAuthSignature(method, url, data){
var index = url.indexOf('?');
if (index > 0)
url = url.substring(0, ur...
var crypto = require('crypto');

var querystring = require('querystring');

function read(query, user, request) {

var res...
var sig = generateOAuthSignature('GET', url, sigData);

oauthData.oauth_signature = sig;

var oauthHeader = "";

for (k in...
That was terrible
Do this
The Easy Way
exports.post = function(request, response) {
var twitter = require(‘ctwitter.js’);
twitter.init(’consumer key...
Script Source Control
Enable on dashboard
Creates Git repo
Changes push from client
Shared Scripts
require(‘jsfile.js');
*Need a config change on update (for now)
Auth Part 1: Custom
Pass creds in
Validate
Hash your salt
Create a JWT
Part 1: The Helpers
Part 2: The Work
Part 3: Signing In
…or just use Auth0
http://aka.ms/authZeroZumo
Check out
Who’s that User? – Friday @ 2pm
Auth Part 2: Identity Caching
Storing Credentials in .NET
Getting and Setting Credentials
Auth Part 3: Expired Tokens
Expiration Flow
DelegationHandlers (again)
ServiceFilter (iOS)
Auth Demo
One-to-Many
Client
Server
Client
Server 1
Server 2
Remember API call #s when
considering client side one-to-many
Paging Data
Client
Server
Client
Server Scripts
On-Prem
On-Prem Solutions in Windows Azure
Data
Synchronization
SQL Data Sync

Application-Layer
Connectivity & Messaging
Service ...
Windows Azure

Point-to-Site VPNs

<subnet 1>

<subnet 2>

<subnet 3>
DNS
Server

On-premises

VPN
Gateway

Route-based
VP...
Site-to-Site Connectivity
•
•

On-ramp for migrating services to the cloud

•

Windows Azure

Extend your premises to the ...
Cnam azure 2014   mobile services
Cnam azure 2014   mobile services
Cnam azure 2014   mobile services
Cnam azure 2014   mobile services
Cnam azure 2014   mobile services
Upcoming SlideShare
Loading in...5
×

Cnam azure 2014 mobile services

2,364

Published on

Support de cours sur Azure au Cnam d'Aymeric Weinbach
mobile services

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
2,364
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
22
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Cnam azure 2014 mobile services"

  1. 1. Cnam Azure ZeCloud 17/01/2014
  2. 2. Windows Azure Mobile Services
  3. 3. Multi-Platform Apps
  4. 4. You don’t need a different Mobile Service for each platform!
  5. 5. Connect them all!
  6. 6. Cross-Platform Support
  7. 7. Cross-Platform Support
  8. 8. Multi-Device Push
  9. 9. Windows Store Single Platform Push Notifications push.wns.sendToastText04(item.channel, {text1: text}, … ); Windows Phone push.mpns.sendFlipTile(item.channel, {title: text}, …); iOS push.apns.send(item.token, { alert: text, payload: inAppMessage: Details }}, …); Android push.gcm.send(item.registrationId, item.text, …); {
  10. 10. Multi-Platform Push Notifications function sendNotifications() { var deviceInfoTable = tables.getTable('DeviceInfo'); deviceInfoTable.where({ userId : user.userId }).read({ success: function(deviceInfos){ deviceInfos.forEach(function(deviceInfo){ if (deviceInfo.uuid != request.parameters.uuid) { if (deviceInfo.pushToken != null && deviceInfo.pushToken != 'SimulatorToken') { if (deviceInfo.platform == 'iOS') { push.apns.send(deviceInfo.pushToken, { alert: "New something created" } , { //success / error block}); } else if (deviceInfo.platform == 'Android') { push.gcm.send(deviceInfo.pushToken, "New something created", { success / error block}); } } } }); } }); }
  11. 11. Don’t forget to check the response on error (or getFeedback for APNS) Also, check out Delivering Push Notifications to Millions of Devices – Friday @12pm
  12. 12. Virtual Tables
  13. 13. Create a table Use it’s endpoint Don’t call request.Execute
  14. 14. Custom API
  15. 15. • • • • • • • •
  16. 16. Custom API Demo
  17. 17. Talking to Azure Storage
  18. 18. It’s doable It’s not perfect Scripts and the Azure module
  19. 19. Reading Tables var azure = require('azure'); function read(query, user, request) { var accountName = 'accountname'; var accountKey = 'Accountkey------------nKHDsW2/0Jzg=='; var host = accountName + '.table.core.windows.net'; var tableService = azure.createTableService(accountName, accountKey, host); tableService.queryTables(function (error, tables) { if (error) { request.respond(500, error); } else { request.respond(200, tables); } }); }
  20. 20. var azure = require('azure'); Reading Table Rows function read(query, user, request) { var accountName = 'accountname'; var accountKey = 'Accountkey------------nKHDsW2/0Jzg=='; var host = accountName + '.table.core.windows.net'; var tableService = azure.createTableService(accountName, accountKey, host); var tq = azure.TableQuery .select() .from(request.parameters.table); tableService.queryEntities(tq, function (error, rows) { if (error) { request.respond(500, error); } else { request.respond(200, rows) } }); }
  21. 21. var azure = require('azure'); function insert(item, user, request) { Creating Containers var accountName = 'accountname'; var accountKey = 'Accountkey------------nKHDsW2/0Jzg=='; var host = accountName + '.blob.core.windows.net'; var blobService = azure.createBlobService(accountName, accountKey, host); if (request.parameters.isPublic == 1) { blobService.createContainerIfNotExists(item.containerName ,{publicAccessLevel : 'blob'} , function (error) { if (!error) { request.respond(200, item); } else { /* error */ request.respond(500);} }); } else { blobService.createContainerIfNotExists(item.containerName, function (error) { if (!error) { request.respond(200, item); } else { /*error */ request.respond(500); } }); } }
  22. 22. Reading and “Creating” Blobs var azure = require('azure'), qs = require('querystring'); function insert(item, user, request) { var accountName = 'accountname'; var accountKey = 'Accountkey------------nKHDsW2/0Jzg=='; var host = accountName + '.blob.core.windows.net'; var blobService = azure.createBlobService(accountName, accountKey, host); var sharedAccessPolicy = { AccessPolicy: { Permissions: 'rw', //Read and Write permissions Expiry: minutesFromNow(5) } }; var sasUrl = blobService.generateSharedAccessSignature(request.parameters.containerName, request.parameters.blobName, sharedAccessPolicy); var sasQueryString = { 'sasUrl' : sasUrl.baseUrl + sasUrl.path + '?' + qs.stringify(sasUrl.queryString) }; request.respond(200, sasQueryString); } function minutesFromNow(minutes) { var date = new Date() date.setMinutes(date.getMinutes() + minutes); return date; }
  23. 23. Storage Demo
  24. 24. Talking REST
  25. 25. http://Mobileservice.azure-mobile.net/tables/* Action HTTP Verb URL Suffix Create POST /TodoItem Retrieve GET /TodoItem?$filter=id%3D42 Update PATCH /TodoItem/id Delete DELETE /TodoItem/id
  26. 26. JSON Value T-SQL Type Numeric values (integer, decimal, floating point) Float Boolean Bit DateTime DateTimeOffset(3) String Nvarchar(max)
  27. 27. Postman & Runscope Demo
  28. 28. Sending Emails
  29. 29. //var crypto = require('crypto'); //item.tempId = new Buffer(crypto.randomBytes(16)).toString('hex'); Sending an Email function sendEmail(item) { var sendgrid = new SendGrid('myaccount@azure.com', 'mypassword'); var email = { to : item.email, from : 'from-me@chrisrisner.com', subject : 'Welcome to MyApp', text: 'Thanks for installing My App! Click this link to verify:nn' + 'http://myapp.azurewebsites.net/activate.html?id=' + item.id + '&tid=' + item.tempId, createDate : new Date() }; sendgrid.send({ to: item.email, from: email.from, subject: email.subject, text: email.text }, function(success, message) { // If the email failed to send, log it as an error so we can investigate if (!success) { console.error(message); } else { saveSentEmail(email); } }); }
  30. 30. Setting up SendGrid Demo
  31. 31. The CLI
  32. 32. SOME It’s awe
  33. 33. CLI Demo
  34. 34. Service Filters and DelegatingHandlers
  35. 35. Client side Intercepts requests Intercepts responses
  36. 36. Sending Version Info with Each Request - (void)handleRequest:(NSURLRequest *)request next:(MSFilterNextBlock)next response:(MSFilterResponseBlock)response { MSFilterResponseBlock wrappedResponse = ^(NSHTTPURLResponse *innerResponse, NSData *data, NSError *error) { response(innerResponse, data, error); }; // add additional versioning information to the querystring for versioning purposes NSString *append = [NSString stringWithFormat:@"build=%@&version=%@", self.build, self.version]; NSURL *url = nil; NSRange range = [request.URL.absoluteString rangeOfString:@"?"]; if (range.length > 0) { url = [NSURL URLWithString:[NSString stringWithFormat:@"%@&%@&p=iOS", request.URL.absoluteString, append]]; } else { url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?%@&p=iOS", request.URL.absoluteString, append]]; } NSMutableURLRequest *newRequest = [request mutableCopy]; newRequest.URL = url; next(newRequest, wrappedResponse); }
  37. 37. DelegatingHandlers are Service Filters public static MobileServiceClient MobileService = new MobileServiceClient( "https://<your subdomain>.azure-mobile.net/", "<your app key>", new VersionHandler() ); using System; using System.Net.Http; using System.Threading.Tasks; namespace WindowsStore { public class VersionHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { request.RequestUri = new Uri(request.RequestUri.AbsoluteUri.ToString() + "?version=v2"); return base.SendAsync(request, cancellationToken); } } }
  38. 38. Script Versioning
  39. 39. Checking the Version in Scripts function insert(item, user, request) { if (request.parameters.build < 2.0) { item.description = 'Not entered'; } request.execute({ success : function() { if (request.parameters.build < 2.0) { delete item.description; } request.respond(); } }); }
  40. 40. For more on versioning, check out Going Live and Beyond with Windows Azure Mobile Services Friday @ 10:30 am
  41. 41. Talking Twitter
  42. 42. v1 is dead v1.1 is hard
  43. 43. function generateOAuthSignature(method, url, data){ var index = url.indexOf('?'); if (index > 0) url = url.substring(0, url.indexOf('?')); var signingToken = encodeURIComponent('Your Consumer Secret') + "&" + encodeURIComponent('Your Access Token Secret'); var keys = []; for (var d in data){ if (d != 'oauth_signature') { console.log('data: ' , d); keys.push(d); } } keys.sort(); var output = "GET&" + encodeURIComponent(url) + "&"; var params = ""; keys.forEach(function(k){ params += "&" + encodeURIComponent(k) + "=" + encodeURIComponent(data[k]); }); params = encodeURIComponent(params.substring(1)); return hashString(signingToken, output+params, "base64"); } function hashString(key, str, encoding){ var hmac = crypto.createHmac("sha1", key); hmac.update(str); return hmac.digest(encoding); } function generateNonce() { var code = ""; for (var i = 0; i < 20; i++) { code += Math.floor(Math.random() * 9).toString(); } return code; } Part 1: The Helpers
  44. 44. var crypto = require('crypto'); var querystring = require('querystring'); function read(query, user, request) { var result = { id: query.id, identities: user.getIdentities(), userName: '' }; var identities = user.getIdentities(); var userId = user.userId; var twitterId = userId.substring(userId.indexOf(':') + 1); //API 1.0 //url = 'https://api.twitter.com/1/users/show/' + twitterId + '.json'; //API 1.1 var url = 'https://api.twitter.com/1.1/users/show.json?user_id=' + twitterId; var key = 'This is your consumer key'; var nonce = generateNonce(); var sigmethod = 'HMAC-SHA1'; var version = '1.0'; var twitterAccessToken = identities.twitter.accessToken; var oauth_token = 'The Access Token'; var seconds = new Date() / 1000; seconds = Math.round(seconds); var requestType = 'GET'; var oauthData = { oauth_consumer_key: key, oauth_nonce: nonce, oauth_signature:null, oauth_signature_method: sigmethod, oauth_timestamp: seconds, oauth_token: oauth_token, oauth_version: version }; var sigData = {}; for (var k in oauthData){ sigData[k] = oauthData[k]; } sigData['user_id'] = twitterId; Part 2: The Work (part 1)
  45. 45. var sig = generateOAuthSignature('GET', url, sigData); oauthData.oauth_signature = sig; var oauthHeader = ""; for (k in oauthData){ oauthHeader += ", " + encodeURIComponent(k) + "="" + encodeURIComponent(oauthData[k]) + """; } oauthHeader = oauthHeader.substring(1); var authHeader = 'OAuth' + oauthHeader; //Generate callback for response from Twitter API var requestCallback = function (err, resp, body) { if (err || resp.statusCode !== 200) { console.error('Error sending data to the provider: ', err); request.respond(statusCodes.INTERNAL_SERVER_ERROR, body); } else { try { var userData = JSON.parse(body); if (userData.name != null) result.UserName = userData.name; else result.UserName = "can't get username"; request.respond(200, [result]); } catch (ex) { console.error('Error parsing response from the provider API: ', ex); request.respond(statusCodes.INTERNAL_SERVER_ERROR, ex); } } } //Create the request and execute it var req = require('request'); var reqOptions = { uri: url, headers: { Accept: "application/json" } }; if (authHeader != null) reqOptions.headers['Authorization'] = authHeader; req(reqOptions, requestCallback); } Part 2.2: The Work
  46. 46. That was terrible Do this
  47. 47. The Easy Way exports.post = function(request, response) { var twitter = require(‘ctwitter.js’); twitter.init(’consumer key',’consumer secret'); twitter.tweet(request.body.tweettext, request.user, request); } Get the script here: http://bit.ly/14b73Gg
  48. 48. Script Source Control
  49. 49. Enable on dashboard Creates Git repo Changes push from client
  50. 50. Shared Scripts
  51. 51. require(‘jsfile.js'); *Need a config change on update (for now)
  52. 52. Auth Part 1: Custom
  53. 53. Pass creds in Validate Hash your salt Create a JWT
  54. 54. Part 1: The Helpers
  55. 55. Part 2: The Work
  56. 56. Part 3: Signing In
  57. 57. …or just use Auth0 http://aka.ms/authZeroZumo Check out Who’s that User? – Friday @ 2pm
  58. 58. Auth Part 2: Identity Caching
  59. 59. Storing Credentials in .NET
  60. 60. Getting and Setting Credentials
  61. 61. Auth Part 3: Expired Tokens
  62. 62. Expiration Flow
  63. 63. DelegationHandlers (again)
  64. 64. ServiceFilter (iOS)
  65. 65. Auth Demo
  66. 66. One-to-Many
  67. 67. Client Server
  68. 68. Client
  69. 69. Server 1
  70. 70. Server 2
  71. 71. Remember API call #s when considering client side one-to-many
  72. 72. Paging Data
  73. 73. Client Server
  74. 74. Client
  75. 75. Server Scripts
  76. 76. On-Prem
  77. 77. On-Prem Solutions in Windows Azure Data Synchronization SQL Data Sync Application-Layer Connectivity & Messaging Service Bus Secure Point-to-Site Network Connectivity Windows Azure Virtual Network Secure Site-to-Site Network Connectivity Windows Azure Virtual Network
  78. 78. Windows Azure Point-to-Site VPNs <subnet 1> <subnet 2> <subnet 3> DNS Server On-premises VPN Gateway Route-based VPN Your datacenter Individual computers behind corporate firewall Virtual Network
  79. 79. Site-to-Site Connectivity • • On-ramp for migrating services to the cloud • Windows Azure Extend your premises to the cloud securely Use your on-prem resources in Azure (monitoring, AD, …) On-premises <subnet 2> <subnet 3> DNS Server VPN Gateway Hardware VPN or Windows RRAS Your datacenter <subnet 1> Virtual Network

×