【发布时间】:2015-10-01 08:58:48
【问题描述】:
我将我的项目构建为多个移动服务,按应用类型分组,例如:
my-core.azure-mobile.net(用户、设备) my-app-A.azure-mobile.net(销售、订单、发票) my-app-B.azure-mobile.net(库存和零件) 我对我的所有服务都使用自定义身份验证,并通过为所有 3 个服务设置相同的主密钥来实现自己的 SSO。
当我使用 REST 客户端进行测试时,事情进展顺利,例如。通过 my-core.azure-mobile.net 上的自定义 API“登录”的用户能够使用返回的 JWT 令牌访问其他移动服务的受限 API。
但是,在我的 xamarin 项目中,只有第一个(注意,按创建顺序)MobileServiceClient 对象正常工作(例如,从给定表返回结果)。客户端对象分别使用自己的 url 和 key 创建,并存储在字典中。
如果我为 app-A 创建了客户端对象,然后只为 app-B 创建,我将能够对销售/订单/发票实体执行 CRUD+Sync,而对库存/零件实体执行 CRUD+Sync 操作只会挂起那里。如果我交换客户端对象的创建顺序,情况则相反。
我想知道 MobileServiceClient 中是否使用了任何内部静态变量导致了这种行为,或者它是一个有效的错误?
=== 代码 sn-p ===
public class AzureService
{
IDictionary<String, MobileServiceClient> services = new Dictionary<String, MobileServiceClient>();
public MobileServiceClient Init (String key, String applicationURL, String applicationKey)
{
return services[key] = new MobileServiceClient (applicationURL, applicationKey);
}
public MobileServiceClient Get(String key)
{
return services [key];
}
public void InitSyncContext(MobileServiceSQLiteStore offlineStore)
{
// Uses the default conflict handler, which fails on conflict
// To use a different conflict handler, pass a parameter to InitializeAsync.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=521416
var syncHandler = new MobileServiceSyncHandler ();
foreach(var client in services) {
client.Value.SyncContext.InitializeAsync (offlineStore, syncHandler);
}
}
public void SetAuthenticationToken(String uid, String token)
{
var user = new MobileServiceUser(uid);
foreach(var client in services) {
client.Value.CurrentUser = user;
client.Value.CurrentUser.MobileServiceAuthenticationToken = token;
}
}
public void ClearAuthenticationToken()
{
foreach(var client in services) {
client.Value.CurrentUser = null;
}
}
}
=== 更多代码 ===
public class DatabaseService
{
public static MobileServiceSQLiteStore LocalStore = null;
public static string Path { get; set; }
public static ISet<IEntityMappingProvider> Providers = new HashSet<IEntityMappingProvider> ();
public static void Init (String dbPath)
{
LocalStore = new MobileServiceSQLiteStore(dbPath);
foreach(var provider in Providers) {
var types = provider.GetSupportedTypes ();
foreach(var t in types) {
JObject item = null;
// omitted detail to create JObject using reflection on given type
LocalStore.DefineTable(tableName, item);
}
}
}
}
=== 仍然是代码 ===
public class AzureDataSyncService<T> : IAzureDataSyncService<T>
{
public MobileServiceClient ServiceClient { get; set; }
public virtual Task<List<T>> GetAll()
{
try
{
var theTable = ServiceClient.GetSyncTable<T>();
return theTable.ToListAsync();
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine("GetAll<{0}> EXCEPTION TYPE: {1}, EXCEPTION:{2}", typeof(T).ToString(), msioe.GetType().ToString(), msioe.ToString());
}
catch (Exception e)
{
Debug.WriteLine("GetAll<{0}> EXCEPTION TYPE: {1}, EXCEPTION:{2}", typeof(T).ToString(), e.GetType().ToString(), e.ToString());
}
List<T> theCollection = Enumerable.Empty<T>().ToList();
return Task.FromResult(theCollection);
}
}
=== 代码 ===
public class UserService : AzureDataSyncService<User>
{
}
public class PartService : AzureDataSyncService<Part>
{
}
const string coreApiURL = @"https://my-core.azure-mobile.net/";
const string coreApiKey = @"XXXXX";
const string invApiURL = @"https://my-inventory.azure-mobile.net/";
const string invApiKey = @"YYYYY";
public async void Foo ()
{
DatabaseService.Providers.Add (new CoreDataMapper());
DatabaseService.Providers.Add (new InvDataMapper ());
DatabaseService.Init (DatabaseService.Path);
var coreSvc = AzureService.Instance.Init ("Core", coreApiURL, coreApiKey);
var invSvc = AzureService.Instance.Init ("Inv", invApiURL, invApiKey);
AzureService.Instance.InitSyncContext (DatabaseService.LocalStore);
AzureService.Instance.SetAuthenticationToken("AAA", "BBB");
UserService.Instance.ServiceClient = coreSvc;
PartService.Instance.ServiceClient = invSvc;
var x = await UserService.GetAll(); // this will work
var y = await PartService.GetAll(); // but not this
}
【问题讨论】:
标签: azure xamarin azure-mobile-services