1

I am trying to authenticate a user before proceeding to the rest of the bots functions and have this code to ensure a user exists

  [Serializable]
public class ModifyLicenceDialog: IDialog<object>
{
    private const string CreateLicence = "Create a new licence";
    private const string ModifyEndDate = "Modify end date";
    private const string CancelLicence = "Cancel a licence";

    public async Task StartAsync(IDialogContext context)
    {
        if (!CommonConversation.User.IsAuthorized)
        {
            context.Call(new AuthDialog(), ResumeAfterAuth);
        }
    }

    private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<object> result)
    {
        await result;
        PromptDialog.Choice(context, ResumeAfterChoice, new[] { CreateLicence, ModifyEndDate, CancelLicence },
           "What licence function would you like?",
           "I am sorry i did not understand that, please select one of the below options");
    }

    private async Task ResumeAfterChoice(IDialogContext context, IAwaitable<string> result)
    {
        string selected = await result;

        switch (selected)
        {
            case CreateLicence:
                context.Call(new CreateLicenseDialog(), AfterLicenseDialog(CreateLicence));
                break;
            case ModifyEndDate:
                break;
            case CancelLicence:
                break;

        }
    }

    private ResumeAfter<object> AfterLicenseDialog(IDialogContext context, string licenseEvent)
    {
        switch (licenseEvent)
        {
            case CancelLicence:
                await context.PostAsync("Auth done");
                context.Done(licenseEvent);
                break;

        }
    }

However when my code goes into the AuthDialog when it tries to call the api to get if the user with the provided email exists (specifically at res = await client.GetAsync(uri)) once the api returns a result the bot returns to the parent dialog (ModifyLicenceDialog) and executes ResumeAfterAuth

   [Serializable]
    public class AuthDialog: IDialog<object>
    {
        private const string InputEmail = "Please input your email address to continue.";
        private int _attempts = 3;

        public async Task StartAsync(IDialogContext context)
        {
            await context.PostAsync(InputEmail);
            context.Wait(MessageReceivedAsync);
        }  

        private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
        {
            IMessageActivity activity = await result;
            string email = activity.Text;

            await context.PostAsync("Please wait while we verify this...");

            HttpResponseMessage res = new HttpResponseMessage();
            HttpClient client = AuthFunctions.Client;

            string uri = $"api/v1/auth/licenses/{email}";

            res = await client.GetAsync(uri);

            if (res.IsSuccessStatusCode)
            {
                CommonConversation.User = JsonConvert.DeserializeObject<CustomerUser>(await res.Content.ReadAsStringAsync());
                await context.PostAsync($"Welcome {CommonConversation.User.FirstName}!");
                context.Done(email);
            }
            else if (_attempts > 0)
            {
                _attempts--;

                await context.PostAsync("I am sorry we do not recognize that email address, lets try again. Please input your email address");
                context.Wait(MessageReceivedAsync);
            }
            else
            {
                context.Fail(new Exception("I am afraid you are not an authorized user"));
            }
        }



    }
}

Update after some guidance from Nicolas R it turns out that at that point an exception is thrown the exception is as follows

{"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."}
"   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at SupportHelpdeskBot.Dialogs.AuthDialog.<MessageReceivedAsync>d__3.MoveNext() in C:\\Workspace\\SupportBot\\SupportHelpdeskBot\\SupportHelpdeskBot\\Dialogs\\AuthDialog.cs:line 41"

I have tried System.Net.ServicePointManager.Expect100Continue = false; to stop this from happening but this hasnt work any suggesitons?

Harry
  • 3,333
  • 3
  • 18
  • 28

1 Answers1

1

There is no error in your implementation: you are completing your AuthDialog here with your context.Done(email):

if (res.IsSuccessStatusCode)
{
    CommonConversation.User = JsonConvert.DeserializeObject<CustomerUser>(await res.Content.ReadAsStringAsync());
     await context.PostAsync($"Welcome {CommonConversation.User.FirstName}!");
     context.Done(email);
}

That's the normal behaviour. What do you want to implement? I think your question is incomplete

Nicolas R
  • 13,812
  • 2
  • 28
  • 57
  • No, am sorry if its not clear from my question but the issue is it never reaches any of the code after res = await client.GetAsync(uri); once the request is completed instead of continuing like you point out to the if statement it returns to the parent dialog. – Harry Jul 10 '17 at 23:38
  • Did you add a look into 'res' while debugging? Can you also put all the code of your 'ModifyLicenceDialog' please? – Nicolas R Jul 10 '17 at 23:41
  • Yes, res returns a 200 response with the expected json object, give me one sec while i update the rest of ModifyLicenceDialog as well – Harry Jul 10 '17 at 23:44
  • As we can't test the web call I can only give some tips. Can you try/catch the content of MessageReceived also? – Nicolas R Jul 10 '17 at 23:50
  • Ah sorry thats what you meant yes i have a breakpoint in the web api call as well and it executed fine reached return Ok(JsonObject) i can provide the code for that as well. Unfortunately i can't test anything at the moment as i am from my home machine and can access only a read-only version of my code. I will be back in the office in 8 hours. I have updated ModifyLicenceDialog with he full code as well – Harry Jul 10 '17 at 23:54
  • Thanks for your suggestion last night i dont know why i didnt though of surounding it with a try catch before it turns out that my code throws the following exception i will update the question – Harry Jul 11 '17 at 08:52
  • I saw your update, have a look to this SO answer: https://stackoverflow.com/questions/5420656/unable-to-read-data-from-the-transport-connection-an-existing-connection-was-f – Nicolas R Jul 11 '17 at 09:08
  • Hi thanks for guiding me to this, i will contact the IT team responsible for the firewall to ask them if they can disable it for a bit and test this out – Harry Jul 11 '17 at 09:14
  • Hi Thanks for all your help and support for this. I am marking this as correct as the issue as you suspected initially did not occured in the Bot code but from the API the reason it was failing is due to the request not receiving a Content-Length for the request thus ending it before it had finished reading it. This was solved by adding the header Content-Length on the request. once again thanks. – Harry Jul 11 '17 at 10:26
  • Thanks for your feedback – Nicolas R Jul 11 '17 at 10:27