LUIS Bot rammeverk vil ikke kalle Intent fra ekstern samtale

stemmer
3

Jeg implementert en ekstern pålogging for min BOT. Når ekstern side kaller Bot TbkRing metoden jeg må sette token og brukernavn i PrivateConversationDataog deretter fortsette å chatte med en melding som Welcome back [username]!.

For å vise denne meldingen jeg sender en MessageActivity, men denne aktiviteten aldri kobles til mitt chat og vil ikke fyre riktig [LuisIntent(UserIsAuthenticated)].

Andre hensikter, av login-flow, fungerer som forventet.

Dette er tilbakeringing metoden:

public class OAuthCallbackController : ApiController
{
    [HttpGet]
    [Route(api/OAuthCallback)]
    public async Task OAuthCallback([FromUri] string userId, [FromUri] string botId, [FromUri] string conversationId,
        [FromUri] string channelId, [FromUri] string serviceUrl, [FromUri] string locale,
        [FromUri] CancellationToken cancellationToken, [FromUri] string accessToken, [FromUri] string username)
    {
        var resumptionCookie = new ResumptionCookie(TokenDecoder(userId), TokenDecoder(botId),
            TokenDecoder(conversationId), channelId, TokenDecoder(serviceUrl), locale);

            var container = WebApiApplication.FindContainer();

            var message = resumptionCookie.GetMessage();
            message.Text = UserIsAuthenticated;

            using (var scope = DialogModule.BeginLifetimeScope(container, message))
            {
                var botData = scope.Resolve<IBotData>();
                await botData.LoadAsync(cancellationToken);

                botData.PrivateConversationData.SetValue(accessToken, accessToken);
                botData.PrivateConversationData.SetValue(username, username);

                ResumptionCookie pending;
                if (botData.PrivateConversationData.TryGetValue(persistedCookie, out pending))
                {
                    botData.PrivateConversationData.RemoveValue(persistedCookie);
                    await botData.FlushAsync(cancellationToken);
                }

                var stack = scope.Resolve<IDialogStack>();
                var child = scope.Resolve<MainDialog>(TypedParameter.From(message));
                var interruption = child.Void<object, IMessageActivity>();

                try
                {
                    stack.Call(interruption, null);

                    await stack.PollAsync(cancellationToken);
                }
                finally
                {
                    await botData.FlushAsync(cancellationToken);
                }
            }
        }
    }   

    public static string TokenDecoder(string token)
    {
        return Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(token));
    }
}

Dette er kontrolleren:

public class MessagesController : ApiController
{
    private readonly ILifetimeScope scope;

    public MessagesController(ILifetimeScope scope)
    {
        SetField.NotNull(out this.scope, nameof(scope), scope);
    }

    public async Task<HttpResponseMessage> Post([FromBody] Activity activity, CancellationToken token)
    {
        if (activity != null)
        {
            switch (activity.GetActivityType())
            {
                case ActivityTypes.Message:
                    using (var scope = DialogModule.BeginLifetimeScope(this.scope, activity))
                    {
                        var postToBot = scope.Resolve<IPostToBot>();
                        await postToBot.PostAsync(activity, token);
                    }
                    break;
            }
        }

        return new HttpResponseMessage(HttpStatusCode.Accepted);
    }
}

Dette er hvordan jeg registrert komponenter:

protected override void Load(ContainerBuilder builder)
    {
        base.Load(builder);

        builder.Register(
            c => new LuisModelAttribute(myId, SubscriptionKey))
            .AsSelf()
            .AsImplementedInterfaces()
            .SingleInstance();

        builder.RegisterType<MainDialog>().AsSelf().As<IDialog<object>>().InstancePerDependency();

        builder.RegisterType<LuisService>()
            .Keyed<ILuisService>(FiberModule.Key_DoNotSerialize)
            .AsImplementedInterfaces()
            .SingleInstance();
    }

Dette er dialogen:

[Serializable]
public sealed class MainDialog : LuisDialog<object>
{
    public static readonly string AuthTokenKey = TestToken;
    public readonly ResumptionCookie ResumptionCookie;
    public static readonly Uri CloudocOauthCallback = new Uri(http://localhost:3980/api/OAuthCallback);

    public MainDialog(IMessageActivity activity, ILuisService luis)
        : base(luis)
    {
        ResumptionCookie = new ResumptionCookie(activity);
    }

    [LuisIntent()]
    public async Task None(IDialogContext context, LuisResult result)
    {
        await context.PostAsync(Sorry cannot understand!);
        context.Wait(MessageReceived);
    }

    [LuisIntent(UserAuthenticated)]
    public async Task UserAuthenticated(IDialogContext context, LuisResult result)
    {
        string username;
        context.PrivateConversationData.TryGetValue(username, out username);

        await context.PostAsync($Welcome back {username}!);
        context.Wait(MessageReceived);
    }

    [LuisIntent(Login)]
    private async Task LogIn(IDialogContext context, LuisResult result)
    {
        string token;
        if (!context.PrivateConversationData.TryGetValue(AuthTokenKey, out token))
        {
            context.PrivateConversationData.SetValue(persistedCookie, ResumptionCookie);

            var loginUrl = CloudocHelpers.GetLoginURL(ResumptionCookie, OauthCallback.ToString());

            var reply = context.MakeMessage();

            var cardButtons = new List<CardAction>();
            var plButton = new CardAction
            {
                Value = loginUrl,
                Type = ActionTypes.Signin,
                Title = Connetti a Cloudoc
            };
            cardButtons.Add(plButton);
            var plCard = new SigninCard(Connect, cardButtons);

            reply.Attachments = new List<Attachment>
            {
                plCard.ToAttachment()
            };

            await context.PostAsync(reply);
            context.Wait(MessageReceived);
        }
        else
        {
            context.Done(token);
        }
    }
}

Hva jeg savner?

Oppdater

Også forsøkt med ResumeAsynci tilbakeringing metode:

var container = WebApiApplication.FindContainer();

var message = resumptionCookie.GetMessage();
message.Text = UserIsAuthenticated;

using (var scope = DialogModule.BeginLifetimeScope(container, message))
{
     var botData = scope.Resolve<IBotData>();
     await botData.LoadAsync(cancellationToken);

     botData.PrivateConversationData.SetValue(accessToken, accessToken);
     botData.PrivateConversationData.SetValue(username, username);

     ResumptionCookie pending;
     if (botData.PrivateConversationData.TryGetValue(persistedCookie, out pending))
     {
         botData.PrivateConversationData.RemoveValue(persistedCookie);
         await botData.FlushAsync(cancellationToken);
     }

     await Conversation.ResumeAsync(resumptionCookie, message, cancellationToken);
 }

men det gir meg feil Operation is not valid due to the current state of the object.

Update 2

Etter Ezequiel idé jeg endret min kode på denne måten:

    [HttpGet]
    [Route(api/OAuthCallback)]
    public async Task OAuthCallback(string state, [FromUri] string accessToken, [FromUri] string username)
    {
        var resumptionCookie = ResumptionCookie.GZipDeserialize(state);
        var message = resumptionCookie.GetMessage();
        message.Text = UserIsAuthenticated;

        await Conversation.ResumeAsync(resumptionCookie, message);
    }

resumptionCookie synes å være ok:

skriv

men await Conversation.ResumeAsync(resumptionCookie, message);fortsetter å gi meg feilOperation is not valid due to the current state of the object.

Publisert på 08/11/2016 klokken 10:33
kilden bruker
På andre språk...                            


2 svar

stemmer
0

Jeg fant hvordan å gjøre det fungerer.

Controller:

public class MessagesController : ApiController
{
    public async Task<HttpResponseMessage> Post([FromBody] Activity activity, CancellationToken token)
    {
        if (activity != null)
        {
            switch (activity.GetActivityType())
            {
                case ActivityTypes.Message:

                    var container = WebApiApplication.FindContainer();

                    using (var scope = DialogModule.BeginLifetimeScope(container, activity))
                    {
                        await Conversation.SendAsync(activity, () => scope.Resolve<IDialog<object>>(), token);
                    }
                    break;
            }
        }
        return new HttpResponseMessage(HttpStatusCode.Accepted);
    }
}

Global.asax

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);

        var builder = new ContainerBuilder();

        builder.RegisterModule(new DialogModule());

        builder.RegisterModule(new MyModule());

        var config = GlobalConfiguration.Configuration;

        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        builder.RegisterWebApiFilterProvider(config);

        var container = builder.Build();
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    }

    public static ILifetimeScope FindContainer()
    {
        var config = GlobalConfiguration.Configuration;
        var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;
        return resolver.Container;
    }
}

MyModule:

public sealed class MyModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        base.Load(builder);

        builder.Register(
            c => new LuisModelAttribute("MyId", "SubId"))
            .AsSelf()
            .AsImplementedInterfaces()
            .SingleInstance();

        builder.RegisterType<MainDialog>().AsSelf().As<IDialog<object>>().InstancePerDependency();

        builder.RegisterType<LuisService>()
            .Keyed<ILuisService>(FiberModule.Key_DoNotSerialize)
            .AsImplementedInterfaces()
            .SingleInstance();
    }
}

Tilbakeringing metoden:

public class OAuthCallbackController : ApiController
{

    [HttpGet]
    [Route("api/OAuthCallback")]
    public async Task OAuthCallback(string state, [FromUri] CancellationToken cancellationToken, [FromUri] string accessToken, [FromUri] string username)
    {
        var resumptionCookie = ResumptionCookie.GZipDeserialize(state);
        var message = resumptionCookie.GetMessage();
        message.Text = "UserIsAuthenticated";

        using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
        {
            var dataBag = scope.Resolve<IBotData>();
            await dataBag.LoadAsync(cancellationToken);

            dataBag.PrivateConversationData.SetValue("accessToken", accessToken);
            dataBag.PrivateConversationData.SetValue("username", username);

            ResumptionCookie pending;
            if (dataBag.PrivateConversationData.TryGetValue("persistedCookie", out pending))
            {
                dataBag.PrivateConversationData.RemoveValue("persistedCookie");
                await dataBag.FlushAsync(cancellationToken);
            }
        }

        await Conversation.ResumeAsync(resumptionCookie, message, cancellationToken);
    }
Svarte 09/11/2016 kl. 11:48
kilden bruker

stemmer
0

Du må gjenoppta samtalen med bot som er grunnen til at meldingen er sannsynligvis ikke kommer.

I stedet for å bruke dialogen stabelen, prøv å bruke

await Conversation.ResumeAsync(resumptionCookie, message);

Avhengig av dine auth behov, vil du kanskje vurdere AuthBot . Du kan også ta en titt på logikken på OAuthCallback kontrolleren av biblioteket for å få et inntrykk av hvordan de er å gjenoppta samtalen med Bot etter auth.

Den ContosoFlowers eksempel er også ved hjelp av CV samtalen mekanisme . Ikke for auth formål, men for å vise hvordan man skal håndtere en hypotethical kredittkortbetaling.

Svarte 08/11/2016 kl. 14:29
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more