1

大家好,我正在尝试将一些数据从登录控制器保存到用户数据存储中。

[HttpGet, Route("api/{channelId}/{userId}/authorize")]
public async System.Threading.Tasks.Task<HttpResponseMessage> Authorize(string channelId, string userId, string code)
{
    string protocalAndDomain = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);

    AuthenticationContext ac = new AuthenticationContext(Constants.AD_AUTH_CONTEXT);
    ClientCredential cc = new ClientCredential(Constants.AD_CLIENT_ID, Constants.AD_CLIENT_SECRET);
    AuthenticationResult ar = await ac.AcquireTokenByAuthorizationCodeAsync(code, new Uri(protocalAndDomain + "/api/" + channelId + "/" + userId + "/authorize"), cc);
    MicrosoftAppCredentials.TrustServiceUrl(protocalAndDomain, DateTime.Now.AddHours(1));

    if (!String.IsNullOrEmpty(ar.AccessToken))
    {
        // Store access token & User Id to bot state
        //var botCred = new MicrosoftAppCredentials(Constants.MS_APP_ID, Constants.MS_APP_PASSWORD);
        //https://state.botframework.com

        using (var sc = new StateClient(new Uri("http://localhost:3979/")))
            if (sc != null)
            {
                var botData = new BotData(data: null, eTag: "*");
                botData.SetProperty("accessToken", ar.AccessToken);
                botData.SetProperty("userEmail", ar.UserInfo.DisplayableId);

                //i get a 401 response here
                await sc.BotState.SetUserDataAsync(channelId, userId, botData);
            }


        var response = Request.CreateResponse(HttpStatusCode.Moved);
        response.Headers.Location = new Uri("/loggedin.html", UriKind.Relative);
        return response;

    }
    else
        return Request.CreateResponse(HttpStatusCode.Unauthorized);
}

我已经看到您可以使用 AppId 和 appPassword 来访问机器人状态的示例,但据我了解,在您的机器人在我目前无法执行的 azuer 应用程序门户中发布/注册之前,这些示例不可用。

或者您可以通过我无法访问的活动访问它。

这实际上只是一个临时解决方案,我的计划是最终将用户数据保存到 Azure 表存储中,但同时我想要一个临时解决方案;我正在考虑将字典序列化和反序列化为本地文本文件,但这似乎有点过头了,而且如果我的应用程序没有在 azure 中注册,我就无法在本地保存到用户数据,这似乎很愚蠢。

非常感谢任何帮助。

4

1 回答 1

0

有了这条线:

var sc = new StateClient(new Uri("http://localhost:3979/"))

您正在指示 BotBuilder 使用状态服务,http://localhost:3979/ 但该端点没有状态服务。

如果您想要一个临时解决方案,在添加 Azure 表存储之前,您可以使用InMemoryDataStore

protected void Application_Start()
{
    Conversation.UpdateContainer(
        builder =>
            {
                builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));

                var store = new InMemoryDataStore(); // volatile in-memory store

                builder.Register(c => store)
                    .Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore)
                    .AsSelf()
                    .SingleInstance();


            });

    GlobalConfiguration.Configure(WebApiConfig.Register);
}

注意:这需要 Azure Extensions nuget 包https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/

注册 InMemoryDataStore 后,您可以使用以下方式访问它:

var message = new Activity()
                {
                    ChannelId = ChannelIds.Directline,
                    From = new ChannelAccount(userId, userName),
                    Recipient = new ChannelAccount(botId, botName),
                    Conversation = new ConversationAccount(id: conversationId),
                    ServiceUrl = serviceUrl
                }.AsMessageActivity();

using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
{
    var botDataStore = scope.Resolve<IBotDataStore<BotData>>();
    var key = new AddressKey()
    {
        BotId = message.Recipient.Id,
        ChannelId = message.ChannelId,
        UserId = message.From.Id,
        ConversationId = message.Conversation.Id,
        ServiceUrl = message.ServiceUrl
    };
    var userData = await botDataStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);

    userData.SetProperty("key 1", "value1");
    userData.SetProperty("key 2", "value2");

    await botDataStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);
    await botDataStore.FlushAsync(key, CancellationToken.None);
}
于 2017-10-02T22:16:59.317 回答