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


1md bot
2cd bot
3dotnet new -t web

Add the following dependencies to your project.json file


1    "Microsoft.AspNet.WebApi.Client": "5.2.3",
2    "System.Runtime.Serialization.Xml": "4.1.1",
3    "Microsoft.Extensions.Caching.Memory": "1.0.0",
4    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
5    "Microsoft.Extensions.DependencyInjection": "1.0.0",
6    "Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0"

And restore the packages

1dotnet restore

Add the following section to your appsettings.json file


Replace the values with those of your registered bot.

1"BotCredentials": {
2    "ClientId": "{Replace with your ClientId}",
3    "ClientSecret": "{Replace with your ClientSecret}"
4  }

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.

 1    // This method gets called by the runtime. Use this method to add services to the container.
 2    public void ConfigureServices(IServiceCollection services)
 3    {
 4        // Adding options so we can inject configurations.
 5        services.AddOptions();
 6
 7        // Register the bot credentials section
 8        services.Configure<BotCredentials>(Configuration.GetSection("BotCredentials"));
 9
10        // we'll be catching tokens, so enable MemoryCache.
11        services.AddMemoryCache();
12
13        services.AddMvc();
14     }

Create a BotCredentials class

This class will hold the bot credentials

 1namespace WebApplication
 2{
 3    /// <summary>
 4    /// Bot Credentials
 5    /// </summary>
 6    public class BotCredentials
 7    {
 8        /// <summary>
 9        /// CLientId
10        /// </summary>
11        public string ClientId { get; set; }
12
13        /// <summary>
14        /// ClientSecret
15        /// </summary>
16        public string ClientSecret { get; set; }
17    }
18}

Create TokenResponse class

 1namespace WebApplication
 2{
 3    /// <summary>
 4    /// Token Response
 5    /// </summary>
 6    public class TokenResponse
 7    {
 8        /// <summary>
 9        /// Property to hold the token
10        /// </summary>
11        public string access_token { get; set; }
12    }
13}

Create a MessagesController class

  1namespace WebApplication.Controllers
  2{
  3    using System;
  4    using System.Collections.Generic;
  5    using System.Dynamic;
  6    using System.Net.Http;
  7    using System.Net.Http.Headers;
  8    using System.Threading.Tasks;
  9    using Microsoft.AspNetCore.Mvc;
 10    using Microsoft.Extensions.Caching.Memory;
 11    using Microsoft.Extensions.Options;
 12
 13    /// <summary>
 14    /// This controller will receive the skype messages and handle them to the EchoBot service. 
 15    /// </summary>
 16    [Route("api/[controller]")]
 17    public class MessagesController : Controller
 18    {
 19        /// <summary>
 20        /// memoryCache
 21        /// </summary>
 22        IMemoryCache memoryCache;
 23
 24        /// <summary>
 25        /// Bot Credentials
 26        /// </summary>
 27        BotCredentials botCredentials;
 28
 29        /// <summary>
 30        /// Constructor
 31        /// </summary>
 32        /// 
 33        /// 
 34        public MessagesController(IMemoryCache memoryCache, IOptions<BotCredentials> botCredentials)
 35        {
 36            this.memoryCache = memoryCache;
 37            this.botCredentials = botCredentials.Value;
 38        }
 39
 40        /// <summary>
 41        /// This method will be called every time the bot receives an activity. This is the messaging endpoint
 42        /// </summary>
 43        /// 
 44        /// <returns>201 Created</returns>
 45        [HttpPost]
 46        public virtual async Task<IActionResult> Post([FromBody] dynamic activity)
 47        {
 48            // Get the conversation id so the bot answers.
 49            var conversationId = activity.from.id.ToString();
 50
 51            // Get a valid token 
 52            string token = await this.GetBotApiToken();
 53
 54            // send the message back
 55            using (var client = new HttpClient())
 56            {
 57                // I'm using dynamic here to make the code simpler
 58                dynamic message = new ExpandoObject();
 59                message.type = "message/text";
 60                message.text = activity.text;
 61
 62                // Set the toekn in the authorization header.
 63                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
 64
 65                // Post the message
 66                await client.PostAsJsonAsync<ExpandoObject>(
 67                    $"https://api.skype.net/v3/conversations/{conversationId}/activities",
 68                    message as ExpandoObject);
 69            }
 70
 71            return Created(Url.Content("~/"), string.Empty);
 72        }
 73
 74        /// <summary>
 75        /// Gets and caches a valid token so the bot can send messages.
 76        /// </summary>
 77        /// <returns>The token</returns>
 78        private async Task<string> GetBotApiToken()
 79        {
 80            // Check to see if we already have a valid token
 81            string token = memoryCache.Get("token")?.ToString();
 82            if (string.IsNullOrEmpty(token))
 83            {
 84                // we need to get a token.
 85                using (var client = new HttpClient())
 86                {
 87                    // Create the encoded content needed to get a token
 88                    var parameters = new Dictionary<string, string>
 89                    {
 90                        {"client_id", this.botCredentials.ClientId },
 91                        {"client_secret", this.botCredentials.ClientSecret },
 92                        {"scope", "https://graph.microsoft.com/.default" },
 93                        {"grant_type", "client_credentials" }
 94                    };
 95                    var content = new FormUrlEncodedContent(parameters);
 96
 97                    // Post
 98                    var response = await client.PostAsync("https://login.microsoftonline.com/common/oauth2/v2.0/token", content);
 99
100                    // Get the token response
101                    var tokenResponse = await response.Content.ReadAsAsync<TokenResponse>();
102
103                    token = tokenResponse.access_token;
104
105                    // Cache the token for 15 minutes.
106                    memoryCache.Set(
107                        "token",
108                        token,
109                        new DateTimeOffset(DateTime.Now.AddMinutes(15)));
110                }
111            }
112
113            return token;
114        }
115    }
116}

Deploy your bot and add it to your skype


  1. Deploy your bot (I deployed it to an Azure Web App)
  2. 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!