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;
}
}
}
}