Reputation: 131
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!
Upvotes: 1
Views: 208
Reputation: 2227
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
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;
}
}
}
}
Upvotes: 2