新型应用程序

Windows Azure 移动服务为新型应用程序提供助力

Rachel Appel

 

Rachel Appel无论你的应用程序发布面向的是哪个平台,Windows Azure 移动服务 (WAMS) 都可作为“一控全局”的后端。它是 Windows Azure 平台的核心组件,为跨平台的新型应用程序和 Web 开发提供后端支持。在本文中,我将介绍如何设置 WAMS,使其能够在 Visual Studio 中工作,概述 WAMS API 并解释使用 WAMS 构建新型应用程序所必需的编码。

WAMS 的跨平台体系结构

可用于管理数据和为应用程序提供后端支持的 Windows Azure 服务有很多,而应用程序使用多个 Windows Azure 服务的情况也并不罕见。下面是一些可用的服务:

  • WAMS: 一套跨平台且功能齐全的后端服务及资源,专门用于快速构建应用程序。
  • SQL Azure: 一款同样流行的 SQL Server,但位于云中,提供了一个易于使用的 Web 管理界面。它是规模较小的初创公司、企业和 ISV 的经济高效之选。
  • Windows Azure 表存储: 以 NoSQL 的方式操作表格及类表格数据。
  • Windows Azure 二进制大型对象 (BLOB) 存储: 以高度可扩展的方式将数据封装为键/值对形式并存储在云中,无结构化数据之忧及限制。
  • Windows Azure 网站: 除网站托管之外,Windows Azure 网站还可以运行 ASP.NET 和 ASP.NET Web API。由于避免了大量的体系结构重构工作,使得其成为基于 HTTP 的旧网站、程序和应用的极佳选择。

应用程序的体系结构取决于需求。如果应用程序需要存储大量(如数十或数百 GB 的数据)的媒体或二进制内容,使用 Windows Azure BLOB 存储可能是更好的选择。对于大多数只读写带有少量配图的文本数据的应用程序来说,WAMS 是一个简洁、易用的解决方案。许多应用程序必须处理旧数据,因此从 SQL Server、SQL Server Compact (SQL CE) 或任一 Microsoft SQL 系列数据库直接迁移到 SQL Azure 可能是最好的方式(如果需要用 DBA 来管理这些数据)。

对大多数应用程序而言,WAMS 非常合适,这是因为它不仅具有数据存储功能,而且还包含一整套基于数据库构建的后端服务,可快速实现常见的应用程序基础结构方案(如推送通知和身份验证)。

WAMS 的核心服务

WAMS 核心服务的功能包括:

  • 数据: 毫无疑问,存储和操作数据是所有应用程序都必不可少的,因而 WAMS 亦为此提供了支持。每一项移动服务的背后都有一个为其提供支持的 SQL Azure 数据库。
  • 消息传送: 用户想要了解最新动态,因而推送通知变得日益重要。随着应用程序变得越来越复杂、直观和用户友好(换句话说,更富现代气息),推送消息和实时通信等功能变得司空见惯。幸运的是,使用 WAMS 中的推送通知就像调用发送 toast(操作系统右上角或右下角的微型弹出消息)通知一样简单:

 

push.wns.sendToastText04(channel, { text1: item.text });
  • 身份验证: 保护数据,尤其是用户数据,与数据本身同等重要。 新型应用程序的一项基本功能是通过流行的 Web 站点(如 Facebook 或 Twitter)进行身份验证,因此,WAMS 允许使用以下任一身份提供程序进行身份验证:
  1. Microsoft Account(之前称作 Windows Live ID 的身份验证提供程序)
  2. Facebook login
  3. Twitter login
  4. Google login

WAMS 提供了若干用于 Windows 系列应用程序开发的库,其中包括用于托管客户端的 Windows 运行时 (WinRT) 库,用于核心服务、身份验证和消息传送等所有操作的 Windows JavaScript 库 (WinJS) 客户端库和 Representational State Transfer (REST) API。 此外,WAMS 甚至还提供了 iOS 和 Android 客户端库,实现用于跨平台同等访问。

在 Windows 应用商店项目或 Windows Phone 项目中使用 WAMS API

无论你构建的是 Windows 应用商店应用程序还是 Windows Phone 应用程序,其代码几乎相同,而 WinJS 端上的 JavaScript 代码更是惊人的相似。 只要拥有适当的开发工具并安装和配置好 WAMS(有关更多相关信息,请参阅 bit.ly/NAAQz8),就很容易写出访问移动服务中对象和数据的代码,但其不同于传统的客户端/服务器或 n 层应用程序开发。 这是由 WAMS 与应用程序的集成方式造成的:应用程序模型中的某些更改可能会导致底层数据结构发生更改。 换句话说,你可以丢弃许多传统的 SQL 数据定义语句而只修改某个类成员,然后重新编译、运行应用程序,并验证数据库级别上的更改。 现如今,用于数据库维护(如验证脚本或设置数据限制)的语法方面,Javascript 已取代了 SQL 的位置。 由于能够通过应用程序、命令提示符和 Web 管理工具轻松编写更改数据库的脚本,使得应用程序的构建过程得以缩短。

Microsoft.WindowsAzure.MobileServices 命名空间提供了对移动服务或其底层 SQL Azure 数据库中对象的标准化访问。 下面的代码示例创建了一个 MobileServiceClient 实例:

public static MobileServiceClient MobileService = new MobileServiceClient(   "https://your-very-own-service-url.azure-mobile.
net/",   "your-very-own-key-that-is-a-gigantic-string-of-characters-and-numbers" );

正如你看到的那样,MobileServiceClient 构造函数的参数为 WAMS 应用程序的 URL 和密钥。 要查找 URL 和密钥,请登录 Windows Azure 门户转至移动服务,然后单击仪表板菜单项左侧的云图标。

在上面的代码示例中,MobileServiceClient 类的行为有点像连接对象,但没有 SqlConnection 对象时代那些烦扰的 open 和 close 方法。 MobileServiceClient 类会代你管理连接。 如果将数据设为公共用途,则无需调用 MobileServiceClient.login 方法,亦可访问表、运行查询和对数据进行排序。 当然,更复杂或安全要求更高的操作可能需要凭据。

拥有有效的 MobileServiceClient 类实例后,即可使用 GetTable<T> 与底层的 WAMS 表进行交互:

private IMobileServiceTable<Person> personsTable =   MobileService.GetTable< Person>();

IMobileServiceTable<T> 中的类型参数 T 会导致编译器检查该参数的相关属性及信息(在本例中,该参数为图 1 中的 Person 类),检查方法是将其映射到数据库级别的底层表。 这使得你能够在开发期间添加或修改属性并于运行时在云中反映相应的架构更改,从而在代码与数据库之间建立一种更紧密的共生关系。 但是,并非代码中的每个更改都会导致数据库级别的架构发生自动更改。 例如,在图 1 的代码中添加一个属性会在表中创建一个新列,但删除已有属性并不会引发删除操作。

图 1 Person 类

// Data model/class code.
public class Person {   public int Id { get; set; }   public string Name { get; set; }   [DataMember(Name = "Birthday")]    public DateTime Date { get; set; }   public string Picture { get; set; }   public string Notes { get; set; } }

GetTable<T> 返回一个 IMobileServiceTable 对象,该对象代表 WAMS 中实际的底层表,并且包含插入、更新、删除和排序服务的方法,如下所示:

// Perform delete asynchronously where item is of type Person, see Figure 1.
await itemsTable.DeleteAsync(item); // Select specific records with LINQ query var people =   personsTable.Select(p => p.Birthday > DateTime.Now.AddDays(14));

你可以通过创建一个与表及成员名称相匹配的自定义类来在代码中构建自己的数据层。 这种技术叫作“惯例优先于配置”,是一种能够缩减臃肿的 XML 配置代码以提高命名中连续性和一致性的方法,它可产生更少的代码,提高可维护性。 例如,图 1 中的类和架构演示了该客户端类代码到 WAMS 表及其成员的映射。

图 1 中的代码会创建图 2 所示的数据库架构。

图 2 惯例优先于配置与类代码和数据库架构名称相匹配

类型
ID SQL Bigint
“名称” 字符串
日期 DateTime
Categories TableAdapter(类别 TableAdapter) 字符串
备注 字符串

WAMS 根据代码中属性的数据类型来推断数据类型。 但是,有些类型,特别是图像和二进制数据,无法以数据属性表示。 这意味着,如需存储图像,则应使用 Windows Azure BLOB 存储,这是因为它的可扩展性更高、代价更低,且性能远远优于其替代方法(即使用 Base64 将图像编码为字符串,然后将其存储在 WAMS 表中)。 Windows Azure BLOB 存储具有 REST API 和托管 API,因此,开发人员可以方便地访问跨平台服务和首选项。

要执行插入、更新或删除操作,只需创建一个自定义对象的实例,然后调用 IMobileServiceTable 对象中的相应方法即可:

Person person = new Person {   Name = "Alan Turing",   Birthday = DateTime dte = new DateTime(1912,6,23),   Picture = base64string, // Image encoding done elsewhere in code.    Notes = "A father of modern computer science.
There is a test " +     "named after him that I fail regularly"}; await personsTable.InsertAsync(person);

对 InsertAsync 的调用显然是异步的,因而该调用不会阻塞 UI 代码的运行,这使得你可以在后台管理数据,而不干扰用户的活动。 Windows 应用商店应用程序和 Windows Phone 应用程序默认以异步方式工作,这是因为你不能总是指望连接非常可靠。

如果操作的是 XAML,则可通过调用 IMobileServiceTable 对象的 ToListAsync 方法来将数据绑定至表。 该方法会将数据预备好,然后将其返回到一个可将 WAMS 表轻松绑定至 XAML ListView 元素的对象中,如下面的代码示例所示:

var results = await todoTable.ToListAsync(); items = new ObservableCollection<TodoItem>(results); ListItems.ItemsSource = items;

上面的代码类似于 Microsoft .NET 框架中传统的数据绑定代码。 如需手动遍历数据而非执行数据绑定,也可调用 IMobileServiceTable 对象的相关方法来返回 IList<T> 或 IEnumerable<T>。

管理 WAMS 的高级功能

毫无疑问,你需要管理和维护移动服务及其数据、安全性和与后端维护相关的所有日常工作,因为这类工作不该全部放在应用程序中完成。 幸运的是,在后端管理任务方面,WAMS 为你提供了一些选择:

  • 命令行工具: 无论采用何种平台进行开发,这都是个非常好的选择;只要下载并安装了命令行库(有关更多信息,请参阅 bit.ly/14Q49bi),即可使用任何命令提示符。    
  • Web 管理: 也称作 Windows Azure 门户,非常适合跨平台后端开发,你可以借助该工具在线完成所有基本工作——创建数据库、运行服务器端脚本、管理服务、管理安全性等等(可通过 Windows Azure 主站 (bit.ly/4yqVhP) 访问该门户)。
  • SQL Server Management Studio: 一款经典的 Microsoft 数据库管理工具,可以用它来连接和管理移动服务的后端数据库(有关更多信息,请参阅 bit.ly/VdqpZH)。

WAMS 包含一个简洁但完整的 WAMS 服务器端脚本参考示例 (bit.ly/XvsVec)。 可通过命令行工具或 Windows Azure 门户在线发送命令。 在命令提示符下,只需输入命令 azure mobile 即可查看所有可用命令的列表,输入 azure mobile list 则可列出所有的移动服务。

与应用程序代码一样,服务器端脚本函数通过命名约定“登记”到一张表中,因此,脚本必须匹配插入、读取、更新和删除操作的方法签名。 下面是 JavaScript 的数据操作脚本签名:

  • 插入函数: insert (item, user, request) { ... }
  • 读取函数: read (query, user, request) { ... }
  • 更新函数: update (item, user, request) { ... }
  • 删除函数: del (id, user, request) { ... }

请注意,所需的一切信息都封装成了方法的参数,即数据行、用户身份和请求本身。 这既可实现行级别的安全性,又可运行任意类型的服务器端规则(如在验证活动发生时进行数据验证)。

例如,你可能需要通过验证来限制传入字符串(用于插入操作)的长度。 可用以下代码实现该功能:

function insert(item, user, request) {   if (item.text.length > 20) {     request.respond(statusCodes.BAD_REQUEST,     'The length of the input text must be less than 20');   } else {     request.execute();     } }

你可在 Windows Azure 门户上修改这些脚本,也可在你喜欢的文本编辑器中进行这些修改并将其保存为带 .js 扩展名的文件(如 person.insert.js)。 然后,通过在命令行上执行采用以下语法和签名的命令上传准备好的脚本:

azure mobile script upload <service-name> table/<table-name>.<operation>.js

下面是用来上传上述示例脚本的命令(其中,Notable 为服务名称,person 为表名):

azure mobile script upload NotablePeople table/person.insert.js

正如你预料的那样,可以使用任意客户端语言中的 try/catch 语句捕捉验证错误的结果。

近来,随着服务器端 JavaScript 趋势的兴起,SQL 开发人员可能会感到落寞,但值得欣慰的是,他们可以在 mssql 脚本对象中使用 SQL,即使与 JavaScript 混用也行:

mssql.query('select * from people', {   success: function(results) {     console.log(results);   } });

如果你所在的企业大量采用 SQL 进行开发,则这一特性尤为有用,因为其与 JavaScript 的动态本质有相当大的不同。

回顾一下,WAMS 是一套完整的用于快速构建跨平台应用程序的后端服务。 除 SQL Azure 外,所有的 Windows Azure 服务都自动实现了 REST 友好的 URL,而 REST 又是跨平台的,因而你没必要为确保应用程序体系结构支持未来的新客户端设备或用户代理而担忧。 此外,WAMS 不仅拥有强大的 Web 管理和命令行工具(使用 WAMS 时无需在客户端上安装大量软件),而且还提供了简单易用的 API,涵盖了从基本的数据存储到批量电子邮件与推送通知的一切内容。

Rachel Appel 是 Microsoft 在纽约市的开发推广人员。 您可以通过 rachelappel.com 网站与她联系,或者通过电子邮件 (rachel.appel@microsoft.com) 与她联系。 您还可以在 Twitter 上(网址为 twitter.com/rachelappel)留意她的最新更新。

衷心感谢以下技术专家对本文的审阅: Paul Batum (Microsoft)
Paul Batum 是 Microsoft 的一名项目经理,负责 Windows Azure 移动服务方面的工作。 他的工作重点是方便移动开发人员在其应用程序中添加云计算功能。 可通过 pbatum@microsoft.com 与他联系。