背景
我在C#中创建了一个工作机器人,但我没有将它扩展为多租户机器人。我在Microsoft门户using this technique中创建了多个机器人,以便从消息传递端点识别自己:
我可以在MessagesController中从URL中获取LastSegment并将其存储在PrivateConversationData中,这样我就知道哪个机器人在当前对话中正在讲话。我打算使用这个存储的'bot id'来检索Microsoft AppId&来自web.config的密码(机器人的凭据存储为一系列自定义条目,而不是标准的appSettings,因为它只适用于单个机器人。)
凭据问题
身份验证(几乎)作为described here运行良好,除非在.ConfigureAwait(false)中使用异步代码时我无法获取HttpContext.Current,因为它在另一个线程上运行时变为null。这意味着我无法通过在web.config中查找它们或通过调用GetCredentialsFromClaims()来获取经过身份验证的用户的凭据,因为我已经丢失了经过身份验证的用户。如果我使用.ConfigureAwait(true)我只会在整个地方遇到死锁。
我在web.config中有凭据,但它们是按机器人存储的,我需要上面URL中的'bot id'才能获得凭据。
问题
问题的症结在于:我需要URL来获取'bot id',我需要'bot id'来从web.config获取凭据,但是我永远无法可靠地访问URL在代码中传递了.ConfigureAwait(false)。另一方面,我无法从PrivateConversationData获取'bot id',因为我需要机器人的凭据才能加载它。有点鸡肉和鸡蛋: - (
如果有人对我可能做错了什么有任何想法,或者有另一种方法知道哪个'bot id'正在执行,我会非常感激。
由于
答案 0 :(得分:0)
请在下面给出示例代码。
public class StartUp {
public void Configuration(IAppBuilder app) {
var builder = new ContainerBuilder();
//Note: Initialize / register the Metadata Service that can bring the tenant details from the corresponding store
builder.RegisterType<TenantMetadataService>().As<ITenantMetadataService>();
//Note: This helps you in accessing the TenantMetadata from any constructor going forward after the below registry
builder.Register(ti => TenantMetadata.GetTenantMetadataFromRequest()).InstancePerRequest();
//TODO: Register the various services / controllers etc which may require the tenant details here
}
}
public class TenantMetadata {
public Guid TenantId { get;set; }
public Uri TenantUrl { get;set; }
public string TenantName { get;set; }
public static TenantMetadata GetTenantMetadataFromRequest() {
var context = HttpContext.Current;
//TODO: If you have any header like TenantId coming from the request, you can read and use it
var tenantIdFromRequestHeader = "";
//TODO: There will be a lazy cache that keeps building the data as new tenant's login or use the application
if(TenantCache.Contains(...))return TenantCache[Key];
//TODO: Do a look-up from the above step and then construct the metadata
var tenantMetadata = metadataSvc.GetTenantMetadata(...);
//TODO: If the data match does not happen from the Step2, build the cache and then return the value.
TenantCache.Add(key,tenantMetadata);
return tenantMetadata;
}
}
注意强> 上面的代码片段使用各种服务占位符,缓存和其他需要根据设计的应用程序服务使用的方法。如果您不希望缓存租户元数据,如果它可能包含一些敏感数据,则可以删除缓存实现部分。
此实现可以分布在您的所有面向Web的门户网站上,例如Web UI,Web Api和WebJobs等,以便它在所有应用程序中都相同,并且易于测试和使用。
HTH。