1
votes

STEP 1: I have cloned the BotFramework CORE BOT SAMPLE: https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/13.core-bot

STEP 2: I have cloned the BotFramework WEB CHAT SAMPLE 'Customize Web Chat by Making the Component Minimizable' https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/12.customization-minimizable-web-chat

STEP 3: Now I want to connect the Web Chat sample with the Core Bot sample what basically means that I put my bot URL into the following line of code in the MinimizableWebChat.js web chat file: const res = await fetch('https://my_own_bot.azurewebsites.net/directline/token', { method: 'POST' });

But step 3 does not work. Web chat does not connect to my bot. It seems that the Core Bot sample has not implemented a token server so the web chat sample and the core bot sample can not connect. Is this interpretation correct? If yes, can you please help me how to add a token server to the Core Bot sample in C#?

PS: Can it really be that the Core Bot sample is missing a token server? The sample is called CORE BOT and I guess every bot needs a token server?!

Thanks a lot!

1

1 Answers

2
votes

Can it really be that the Core Bot sample is missing a token server? The sample is called CORE BOT and I guess every bot needs a token server?!

No, not really. If you're building your own webchat client, like in the webchat samples, you can have a token server to exchange secret for token. But if you're not building your own webchat, or you don't care about exchanging a secret for a token, or you want to use literally any other channel, you don't need one.

That being said, I have a working secret->token exchange in C# here. Like the node versions in the webchat repo. These are the changes I made to translate that sample from node to C#:

in my html file:

<body>
    <h2>Index??</h2>
    <div id="webchat" role="main" />
    <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
    <script>
        (async function () {
            const res = await fetch('/directline/token', { method: 'POST' });
            const { token } = await res.json();
            window.WebChat.renderWebChat({
                directLine: window.WebChat.createDirectLine({ token }),
            }, document.getElementById('webchat'));
        })();
    </script>
</body>

To catch that POST request, I had to add a couple things to the bot. In the startup class, I needed to make sure my token model was seen:

services.Configure<DLSModel>(Configuration.GetSection("DirectLine"));

Then, I added the DSLModel to my models

image of mvc model folder structure

The model itself is pretty simple:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace JJDirectLineBot.Models
{
    public class DLSModel
    {
        public string DirectLineSecret { get; set; }
    }
}

Basically, all that say 'go looking for her directline secret in her app settings.' I'm sure there's an easier way to get there, but that's the one I did.

Then, you need a controller to actually make the request:

namespace JJDirectLineBot.Controllers
{

    public class TokenController : ControllerBase
    {
        private readonly IOptions<DLSModel> dlSecret;

        public TokenController(IOptions<DLSModel> dls)
        {
            dlSecret = dls;
        }

        [Route("/directline/token")]
        [HttpPost]
        public async Task<string> TokenRequest()
        {
            var secret = dlSecret.Value.DirectLineSecret;
            HttpClient client = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(
                HttpMethod.Post,
                $"https://directline.botframework.com/v3/directline/tokens/generate");
            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", secret);
            var userId = $"dl_{Guid.NewGuid()}";
            request.Content = new StringContent(
                JsonConvert.SerializeObject(
                    new { User = new { Id = userId } }),
                Encoding.UTF8,
                "application/json");
            var response = await client.SendAsync(request);
            string token = string.Empty;

            if (response.IsSuccessStatusCode)
            {
                var body = await response.Content.ReadAsStringAsync();

                return body;
            }
            else
            {
                //Error();
                return token;
            }

        }
    }
}