.net 以1对1聊天方式向租户中的用户发送通知

.net 以1对1聊天方式向租户中的用户发送通知,.net,botframework,microsoft-teams,microsoft-graph-sdks,microsoft-graph-teams,.net,Botframework,Microsoft Teams,Microsoft Graph Sdks,Microsoft Graph Teams,我正在使用ASP.NET核心Graph SDK(来自Microsoft.Identity.Web.MicrosoftGraphBeta)为Microsoft团队中的组织开发一个通知机器人。 我很难为租户中的特定用户开发一个简单的通知系统。这些用户由电子邮件地址标识。 我已经通过以下方式为用户和团队实施了应用程序的主动安装: 接收消息以在MS团队中发送给特定用户的控制器 [HttpPost] [Route("notify-approver")] public async Tas

我正在使用ASP.NET核心Graph SDK(来自Microsoft.Identity.Web.MicrosoftGraphBeta)为Microsoft团队中的组织开发一个通知机器人。 我很难为租户中的特定用户开发一个简单的通知系统。这些用户由电子邮件地址标识。 我已经通过以下方式为用户和团队实施了应用程序的主动安装:

接收消息以在MS团队中发送给特定用户的控制器

[HttpPost]
[Route("notify-approver")]
public async Task<List<string>> NotifyApprover([FromBody] ApproverMessage approverMessage)
{
            var approvers = await _graphServiceClient.Users.Request().Filter($"mail eq '{approverMessage.Email}'").GetAsync();

            var targetApprover = approvers.CurrentPage.ToList().FirstOrDefault();

            var appInstallation= await _graphServiceClient.InstallIfNotAlreadyForUser(targetApprover.Id, _configuration.GetTeamsAppId());


            // PER IL MOMENTO SEMBRA BUG
            var chatId = await _graphServiceClient.GetChatThreadId(targetApprover.Id, appInstallation.Id)

        }
[HttpPost]
[路线(“通知批准人”)]
公共异步任务NotifyApprover([FromBody]ApproverMessage ApproverMessage)
{
var approvers=await _graphServiceClient.Users.Request().Filter($“mail eq'{approverMessage.Email}')).GetAsync();
var targetApprover=approvers.CurrentPage.ToList().FirstOrDefault();
var appInstallation=await _graphServiceClient.InstallIfNotAlreadyForUser(targetApprover.Id,_configuration.GetTeamsAppId());
//每分钟一次
var chatId=await_graphServiceClient.GetChatThreadId(targetAppOver.Id,appInstallation.Id)
}
安装工作正常,并返回UserScopeTeamSAPP安装。 这是我为主动安装而构建的功能:

public static async Task<UserScopeTeamsAppInstallation> InstallIfNotAlreadyForUser(this IGraphServiceClient graphServiceClient, string userId, string teamsAppId)
        {
            var appsCollectionPage = await graphServiceClient.Users[userId].Teamwork.InstalledApps.Request().Expand("teamsAppDefinition")
                .GetAsync();
            var appInstallation = appsCollectionPage.CurrentPage.ToList()
                .Find(a => a.TeamsAppDefinition.TeamsAppId.Equals(teamsAppId));

            if (appInstallation != null) return appInstallation;
            var userScopeTeamsAppInstallation = new UserScopeTeamsAppInstallation()
            {
                AdditionalData = new Dictionary<string, object>
                {
                    {"teamsApp@odata.bind", $"https://graph.microsoft.com/beta/appCatalogs/teamsApps/{teamsAppId}"}
                }
            };
            var freshInstallation = await graphServiceClient.Users[userId].Teamwork.InstalledApps.Request().AddAsync(userScopeTeamsAppInstallation);
            return freshInstallation;

        }
public static async Task InstallIfNotAlreadyForUser(此IGraphServiceClient graphServiceClient、string userId、string teamsAppId)
{
var-appsCollectionPage=await graphServiceClient.Users[userId].Team.InstalledApps.Request().Expand(“teamsAppDefinition”)
.GetAsync();
var appInstallation=appsCollectionPage.CurrentPage.ToList()
.Find(a=>a.TeamsAppDefinition.TeamsAppId.Equals(TeamsAppId));
如果(appInstallation!=null)返回appInstallation;
var userScopeTeamsAppInstallation=new userScopeTeamsAppInstallation()
{
AdditionalData=新字典
{
{"teamsApp@odata.bind", $"https://graph.microsoft.com/beta/appCatalogs/teamsApps/{teamsapid}}
}
};
var freshInstallation=await graphServiceClient.Users[userId].teamworking.InstalledApps.Request().AddAsync(userScopeTeamsAppInstallation);
返回安装;
}
到目前为止还可以,但不好的部分是尝试主动发送消息;正如在文章中所建议的,我继续获得这个应该有用的chatId。有趣的是,如果我使用Graph Client v1.0,在检索下面的聊天对象时会出现一个内部服务器错误,然后我切换到Beta客户端,它。。。有点管用

public static async Task<string> GetChatThreadId(this IGraphServiceClient graphServiceClient, string userId, string teamsAppIdInstallation)
        {
            // forse ci vuole AppInstallationId anziché il semplice teamsAppId della app

            //var chat = await graphServiceClient.Users[userId].Teamwork.InstalledApps[teamsAppIdInstallation].Chat.Request().GetAsync();

            /*
             * Perché dá internal server error?? Possibile bug della API di graph
             * perché viceversa da graph explorer funziona e restituisce l'id della chat
             *
             * Per adesso sono costretto a salvarmi in un database tutte le conversation references.
             */

            var chat =  graphServiceClient.Users[userId].Teamwork.InstalledApps[teamsAppIdInstallation].Chat.Request().GetAsync();


            return chat.Id.ToString();
            //return "CIAONE";
        }
公共静态异步任务GetChatThreadId(此IGraphServiceClient graphServiceClient、string userId、string teamsAppIdInstallation)
{
//对于ci vuole应用程序安装ID anzichéil semplice团队ID della应用程序
//var chat=await graphServiceClient.Users[userId]。teamworking.InstalledApps[teamsAppIdInstallation]。chat.Request().GetAsync();
/*
*Perchédá内部服务器错误??可能的错误della API di图
*图形探索者的乐趣和休息
*
*根据adesso sono costretto在联合国数据库tutte le对话参考中提到的salvarmi。
*/
var chat=graphServiceClient.Users[userId].团队合作.InstalledApps[teamsAppIdInstallation].chat.Request().GetAsync();
return chat.Id.ToString();
//返回“CIAONE”;
}
从现在起,我越来越被大量分散的信息弄糊涂了。 我看到的是,通常情况下,事情应该是:

  • 在bot回调OnConversationUpdateActivityAsync上,应保存ConversationReference,因为它是在安装bot时激发的。但该对象存储在ConcurrentDictionary中,其生命周期仅限于运行时。在我的例子中,我应该将其持久化,但我找不到要存储的属性以及如何重新创建ConversationReference对象,在示例中,该对象始终按原样存储,但没有具有持久性的示例
  • 鉴于上述问题,我无法在bot适配器上使用ContinueConversationAsync方法
  • 在任何情况下,如果我们查看,即使它明确表示要检索这个ChatId,它也会使用缓存的ConversationReference对象执行操作

我该如何做这样一件“简单”的事情,比如向一个人发送一条简单的消息,而它看起来非常混乱?

要保留对话引用属性,请检查中的存储层概念

您可以继续并尝试将此代码示例放置在startup.cs文件中:

services.AddSingleton<IStorage>(new AzureBlobStorage(Configuration["_connectionstring"], Configuration["BlobName"]));
services.AddSingleton<UserState>();
services.AddSingleton<ConversationState>();
services.AddSingleton<BotStateService>(); 
services.AddSingleton(新的AzureBlobStorage(配置[“\u connectionstring]”,配置[“BlobName]”);
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();

另外,请看一看示例代码。

我发现的一个简单解决方案是,当为用户安装Bot时,用json序列化ConversationReference对象并将其保存到Sqlite数据库中,从而将其保存在OnTeamsMembersAddedAsync回调中。为了检索它,我将其反序列化并使用

谢谢您的回复。最后,通过将每个ConversationReference对象保存在本地Sqlite db中,我找到了一个“简单”的解决方案:我用JSON序列化它,然后将它保存为JSON字符串,当我检索它时,我从JSON字符串反序列化它,并按照主动消息传递文档中的说明使用它