.NET Core and Microsoft Bot Framework
Categories:
4 minute read
Today I’ll show you how to create a simple Skype bot that will reply with the same text message you send to it.
You’ll be using .Net Core and Microsoft Bot Framework. As you already know not every library has been ported to .Net Core so you’ll have to use the Microsoft Bot Connector API – v3.0 to bring the bot to life.
Let me show you what it takes to create a simple bot:
Register the bot
Head to the Register bot page and fill the required fields.
For the messaging endpoint use something like: https://{url of your bot}/api/messages
Also get your Microsoft App ID and password from the Microsoft Application registration portal, and save them cause you’ll need them to fill the BotCredentials in our sample.
Create a new .NET Core Web the project
md bot
cd bot
dotnet new -t web
Add the following dependencies to your project.json file
"Microsoft.AspNet.WebApi.Client": "5.2.3",
"System.Runtime.Serialization.Xml": "4.1.1",
"Microsoft.Extensions.Caching.Memory": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"Microsoft.Extensions.DependencyInjection": "1.0.0",
"Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0"
And restore the packages
dotnet restore
Add the following section to your appsettings.json file
Replace the values with those of your registered bot.
"BotCredentials": {
"ClientId": "{Replace with your ClientId}",
"ClientSecret": "{Replace with your ClientSecret}"
}
Replace the ConfigureServices in you Startup class
You’ll be using options to inject configurations (BotCredentials) to the controller and in Memory Cache to save tokens to avoid authenticating the bot on every call.
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Adding options so we can inject configurations.
services.AddOptions();
// Register the bot credentials section
services.Configure<BotCredentials>(Configuration.GetSection("BotCredentials"));
// we'll be catching tokens, so enable MemoryCache.
services.AddMemoryCache();
services.AddMvc();
}
Create a BotCredentials class
This class will hold the bot credentials
namespace WebApplication
{
/// <summary>
/// Bot Credentials
/// </summary>
public class BotCredentials
{
/// <summary>
/// CLientId
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// ClientSecret
/// </summary>
public string ClientSecret { get; set; }
}
}
Create TokenResponse class
namespace WebApplication
{
/// <summary>
/// Token Response
/// </summary>
public class TokenResponse
{
/// <summary>
/// Property to hold the token
/// </summary>
public string access_token { get; set; }
}
}
Create a MessagesController class
namespace WebApplication.Controllers
{
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
/// <summary>
/// This controller will receive the skype messages and handle them to the EchoBot service.
/// </summary>
[Route("api/[controller]")]
public class MessagesController : Controller
{
/// <summary>
/// memoryCache
/// </summary>
IMemoryCache memoryCache;
/// <summary>
/// Bot Credentials
/// </summary>
BotCredentials botCredentials;
/// <summary>
/// Constructor
/// </summary>
///
///
public MessagesController(IMemoryCache memoryCache, IOptions<BotCredentials> botCredentials)
{
this.memoryCache = memoryCache;
this.botCredentials = botCredentials.Value;
}
/// <summary>
/// This method will be called every time the bot receives an activity. This is the messaging endpoint
/// </summary>
///
/// <returns>201 Created</returns>
[HttpPost]
public virtual async Task<IActionResult> Post([FromBody] dynamic activity)
{
// Get the conversation id so the bot answers.
var conversationId = activity.from.id.ToString();
// Get a valid token
string token = await this.GetBotApiToken();
// send the message back
using (var client = new HttpClient())
{
// I'm using dynamic here to make the code simpler
dynamic message = new ExpandoObject();
message.type = "message/text";
message.text = activity.text;
// Set the toekn in the authorization header.
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
// Post the message
await client.PostAsJsonAsync<ExpandoObject>(
$"https://api.skype.net/v3/conversations/{conversationId}/activities",
message as ExpandoObject);
}
return Created(Url.Content("~/"), string.Empty);
}
/// <summary>
/// Gets and caches a valid token so the bot can send messages.
/// </summary>
/// <returns>The token</returns>
private async Task<string> GetBotApiToken()
{
// Check to see if we already have a valid token
string token = memoryCache.Get("token")?.ToString();
if (string.IsNullOrEmpty(token))
{
// we need to get a token.
using (var client = new HttpClient())
{
// Create the encoded content needed to get a token
var parameters = new Dictionary<string, string>
{
{"client_id", this.botCredentials.ClientId },
{"client_secret", this.botCredentials.ClientSecret },
{"scope", "https://graph.microsoft.com/.default" },
{"grant_type", "client_credentials" }
};
var content = new FormUrlEncodedContent(parameters);
// Post
var response = await client.PostAsync("https://login.microsoftonline.com/common/oauth2/v2.0/token", content);
// Get the token response
var tokenResponse = await response.Content.ReadAsAsync<TokenResponse>();
token = tokenResponse.access_token;
// Cache the token for 15 minutes.
memoryCache.Set(
"token",
token,
new DateTimeOffset(DateTime.Now.AddMinutes(15)));
}
}
return token;
}
}
}
Deploy your bot and add it to your skype
- Deploy your bot (I deployed it to an Azure Web App)
- Head to the My Bots section of the Microsoft Bot Framework page and add the bot to your skype contacts.
Talk to your bot
No you can talk to your bot!
You can get the code here: https://github.com/cmendible/dotnetcore.samples/tree/main/echobot
Hope it helps!