使用 Azure Mobile Services 为 iOS 和 Windows Phone 创建移动 CRM





0/5 (0投票)
Dun and Bradstreet Developer Challenge 的 iOS 应用和 Windows Phone 应用条目
引言
需求是发明之母,Ivan 进军创业世界的新尝试让他面临饥饿和破产的威胁。他需要客户来使用他的新股票分析应用程序,该应用程序的业绩 regularly outperform the market twofold。还有比邓白氏更好的市场细分分析来源吗?但是,他有没有一种简单的方法来获取这些信息并确定潜在客户,以便与他们接触并完成销售?
背景
Honey Badger [潜在客户生成和] CRM 应运而生。该应用程序可用于 iPhone 和 Windows Phone,Android 版本只需进行少量用户界面工作即可推出,它使用邓白氏的数据来为 Ivan 的天才之作寻找潜在客户。但这只是应用程序功能的冰山一角:通过 Honey Badger CRM,一旦 Ivan 识别出潜在客户,他就会在移动设备上记录尝试联系这些客户并进行销售的尝试。该应用程序还具有游戏化元素:每次联系潜在客户时,都会消耗一定数量的积分(代表金钱、时间或两者)。积分供应是有限的;Ivan 必须选择正确的目标并在积分用完饿死之前完成销售。
我们制作了一个简短的视频来展示 Honey Badger CRM
http://www.youtube.com/watch?v=-gZzwrLwFH0
我们还在 GitHub 上提供了源代码
Windows Phone: https://github.com/FabienLavocat/HoneyBadgerCRM
iOS: https://github.com/echuvyrov/HoneyBadgerCRM
您还可以下载 .zip 存档的代码。
本文的其余部分描述了我们解决方案的技术实现细节。我们希望 codeproject.com 的读者通过阅读本文能够学到一些技巧。
技术实现
为了加快移动跨平台开发,该应用程序使用 Azure 移动服务进行所有后端处理。邓白氏数据从 Azure 移动服务访问,而不是从客户端应用程序调用;下图说明了我们构建的应用程序的高级架构。
在实现此应用程序时,我们涉及了三项独立的技术:Azure 移动服务、iOS 开发和 Windows Phone 编程。下面,我们重点介绍我们针对每种技术解决方案中最重要的部分。
Windows Azure 移动服务
Windows Azure 移动服务 (WAMS) 允许您快速设置移动应用程序的后端,无需预置独立的服务器、安装和管理数据库引擎以及担心可伸缩性。为了加快跨平台开发,我们严重依赖 WAMS 提供的功能和工具。
使用自定义 API 访问 D&B 数据
WAMS 上的自定义 API 支持使用 JavaScript 进行服务器端脚本编写(内部运行 node.js)。我们引入了一个自定义 API 层来调用 D&B 开发人员沙盒;移动客户端调用此层而不是直接与 D&B 沙盒数据通信。这样做至少有两个原因
- 我们避免将访问 D&B 数据所需的安全凭据分发给移动设备,因为这些凭据很容易被逆向工程。
- 我们将常见的數據访问和业务逻辑封装到一个入口点中,而不是将其分散到各个设备上。
下面的代码是我们使用的实际自定义 API 端点之一,它根据传入的 DUNS 标识符检索公司详细信息。可以编写类似的代码来访问其他 Azure 数据市场商店(不仅仅是 D&B 沙盒)和其他 OData 提供商。保存后,可以通过以下端点访问自定义 API:http://<您的-wams-app-name>.azure-mobile.net/api/您的apiname。
exports.get = function (req, res) {
var http = require('https');
var username = '<YOUR USERNAME>',
password = '<YOUR PASSWORD>';
var body = '';
var searchParams = '';
if(req.query.DUNSNumber) {
searchParams = "DUNSNumber eq '" + req.query.DUNSNumber + "'";
}
var dnb = {
host: "api.datamarket.azure.com",
path: "/DNB/DeveloperSandbox/v1/Firmographics?$format=JSON&$filter=" + encodeURIComponent(searchParams),
// set up Basic authentication
headers: {
'Authorization': 'Basic ' + new Buffer(username + ':' + password).toString('base64')
}
};
http.request(dnb, function (dnb_response) {
dnb_response.on('data', function(chunk){
console.log("Got chunk: " + chunk);
body += chunk;
});
dnb_response.on("end", function(e){
res.send(200, body);
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
}).end();
}
保存客户数据
将客户数据保存到 WAMS 非常简单,特别是考虑到数据不需要(也许也不应该)采用关系格式。您将在下面的 Windows Phone 和 iOS 部分了解保存操作;WAMS 带来的重要且非常方便的部分是引入了自定义脚本,这些脚本可以在每次读取、插入、更新或删除之前在服务器端执行。例如,以下代码片段说明了如何在插入用户表之前检查用户是否已存在;通过下面的代码,新用户还可以获得 100 分,以开始他们的宣传活动。
function insert(item, user, request) {
var userTable = tables.getTable('user');
userTable.where({ UserId: user.userId })
.read({ success: checkIfUserExists });
function checkIfUserExists(results) {
if (results.length === 0) {
console.log('New User %s.', user.userId);
item.UserId = user.userId;
item.Points = 100;
request.execute();
}
else {
request.respond(statusCodes.OK, results[0]);
}
}
}
Windows Phone 客户端
为 WAMS 访问设置 Windows Phone 需要一些必要的步骤。为了轻松使用 WAMS,我们需要向项目添加以下 NuGet 包
然后,如果尚未完成,请下载并安装Windows Azure 移动服务 SDK。
最后,在 Visual Studio 中创建或打开您的 Windows Phone 8 项目,并将以下代码添加到 App.xaml.cs 中
public static readonly MobileServiceClient MobileService =
new MobileServiceClient("https://[address].azure-mobile.net/", "[code]");
上述 {code] 部分的安全信息可以在您创建的 Azure 移动服务项目的仪表板上找到。
检索潜在客户
如上所述,所有对 D&B 数据的访问都通过 Azure 移动服务上的自定义 API 进行。要检索客户数据,Windows Phone 客户端需要调用该 API,并在查询字符串中传递适当的参数。在通过简单连接构建搜索查询字符串后,以下代码调用自定义 API 以检索潜在客户列表
private static async Task DownloadResultAsync(string url, NetworkCredential credentials)
{
var client = new WebClient { Credentials = credentials };
var result = await client.DownloadStringTaskAsync(new Uri(url));
return JsonConvert.DeserializeObject(result);
}
检索到潜在客户后,我们将其映射到 Windows Phone 设备上。
将数据保存到 Azure 移动服务
将数据保存到 Azure 移动服务也很容易:首先,我们将声明一个包含要保存的数据的对象
[JsonObject]
public class Campaign
{
[JsonProperty]
public int Id { get; set; }
[JsonProperty]
public string User { get; set; }
[JsonProperty]
public string Name { get; set; }
//add additional parameters as needed
}
然后,我们调用 WAMS SDK 中的方法将数据推送到云端
private async Task SaveCampaign()
{
Campaign c = new Campaign
{
User = App.MobileServicesUser.UserId,
Name = campaign.Name,
};
try
{
IMobileServiceTable campaignTable = App.MobileService.GetTable();
await campaignTable.InsertAsync(c);
NavigationService.Navigate(new Uri("/NextPage.xaml", UriKind.RelativeOrAbsolute));
}
catch (Exception)
{
MessageBox.Show("An error happened. Please try again.");
}
}
iOS 客户端
我们还构建了一个功能与 Windows Phone 完全相同的原生 iOS 客户端。由于许多逻辑都封装在 Windows Azure 移动服务中,我们能够相当快地构建应用程序。以下是一些利用 iOS 上的 WAMS 的亮点。
Azure 移动服务提供了一组入门项目,其中包括一个功能齐全的 ToDo 应用程序。如果您正在使用 WAMS 启动一个全新的项目,下载此项目并开始修改它可能是最方便的。但是,如果您有一个想要移植到 WAMS 的现有应用程序,请下载并安装 Windows Azure 移动服务 SDK。然后,将 WindowsAzureMobileServices
框架添加到您的项目中。
与 WAMS 通信最方便的方法是有一个单独的类来处理所有数据操作和 Azure 级别的工作。可下载的入门项目已经包含这个类;要为现有项目创建这个类,请添加一个新的 NSObject
类并将其命名为 honeyBadgerService
。在 honeyBadgerService.h 文件中,请确保您有以下 #include
语句和属性声明
#import <WindowsAzureMobileServices/ WindowsAzureMobileServices.h>
@property (nonatomic, strong) NSArray *companies;
@property (nonatomic, strong) NSArray *campaigns;
@property (nonatomic, strong) MSClient *client;
@property (nonatomic, copy) QSBusyUpdateBlock busyUpdate;
@property (nonatomic, strong) MSTable *table;
为了完成设置并与 WAMS 通信,我们在 honeyBadgerService.m
中添加了以下代码
+ (honeyBadgerService *)defaultService
{
static honeyBadgerService* service;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
service = [[honeyBadgerService alloc] init];
});
return service;
}
-(honeyBadgerService *)init
{
self = [super init];
if (self)
{
// Initialize the Mobile Service client with your URL and key
MSClient *client = [MSClient clientWithApplicationURLString:@"<YOUR WAMS URL>"
applicationKey:@"<YOUR KEY>"];
// Add a Mobile Service filter to enable the busy indicator
self.client = [client clientWithFilter:self];
self.table = [_client tableWithName:@"campaign"];
self.companies = [[NSMutableArray alloc] init];
self.campaigns = [[NSMutableArray alloc] init];
self.busyCount = 0;
}
return self;
}
完成这些设置步骤后,我们就可以检索数据并将其保存到服务器。
检索客户营销活动
我们应用程序的一个屏幕显示了我们试图与给定客户建立的所有联系和营销活动。下面的代码片段说明了如何获取该数据。简而言之,我们创建了一个 NSPredicate
来检索我们感兴趣的数据,并使用 Azure 移动服务 SDK 中的方法从服务器获取数据。
- (void)getCampaignsForDUNSNumber:(NSString*)dunsNumber completion:(QSCompletionBlock)completion
{
// Create a predicate that finds items where complete is false
NSString* searchString = [@"DUNSNumber == " stringByAppendingString:dunsNumber];
NSPredicate * predicate = [NSPredicate predicateWithFormat:searchString];
// Query the TodoItem table and update the items property with the results from the service
[self.table readWithPredicate:predicate completion:^(NSArray *results, NSInteger totalCount, NSError *error)
{
[self logErrorIfNotNil:error];
campaigns = [results mutableCopy];
completion();
}];
}
检索潜在客户的方式与 Windows Phone 完全相同:我们构建查询字符串并调用 Azure 移动服务上的自定义 API,然后处理检索到的结果集
- (NSDictionary *)getTargets
{
NSString* query = [@"http://dnb-crm.azure-mobile.net/api/firmographics?City=" stringByAppendingString:dnbCity];
query = [query stringByAppendingString:@"&State="];
query = [query stringByAppendingString:dnbState];
query = [query stringByAppendingString:@"&IndustryCode="];
query = [query stringByAppendingString:[self getIndustryCode]];
query = [query stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error] : nil;
if (error) NSLog(@"[%@ %@] JSON error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
return results;
}
与 Windows Phone 应用程序类似,我们映射潜在客户以查看他们离我们有多近。
将数据保存到 Azure 移动服务
从 iOS 客户端将数据保存到 Azure 移动服务几乎与从 Windows Phone 一样简单:我们传入一个包含与数据存储中的列/列值对应的键/值对的 NSDictionary
。然后,我们在 WAMS 表上调用插入方法。如果传入的 NSDictionary
中出现新列,表将扩展以包含新列;这种可塑性是使 WAMS 应用程序快速运行的关键之一。
-(void)addItem:(NSDictionary *)item completion: (QSCompletionWithIndexBlock)completion
{
// Insert the item into the TodoItem table and add to the items array on completion
[self.table insert:item completion:^(NSDictionary *result, NSError *error)
{
[self logErrorIfNotNil:error];
NSUInteger index = [campaigns count];
[(NSMutableArray *)campaigns insertObject:result atIndex:index];
// Let the caller know that we finished
completion(index);
}];
}
如果涵盖我们解决方案的每个实现细节,那将是一篇很长的文章。请查看源代码以获取实现澄清,也请随时与我们联系。
现在,这款 Honey Badger (CRM) 已准备好投入战斗!
历史
首次发布(1.0 版)- 2013 年 7 月 30 日。