diff --git a/CSharp/demo-RollerSkill/App_Start/WebApiConfig.cs b/CSharp/demo-RollerSkill/App_Start/WebApiConfig.cs
new file mode 100644
index 0000000000..7ba0c607f6
--- /dev/null
+++ b/CSharp/demo-RollerSkill/App_Start/WebApiConfig.cs
@@ -0,0 +1,33 @@
+namespace RollerSkillBot
+{
+ using System.Web.Http;
+ using Newtonsoft.Json;
+ using Newtonsoft.Json.Serialization;
+
+ public static class WebApiConfig
+ {
+ public static void Register(HttpConfiguration config)
+ {
+ // Json settings
+ config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
+ config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
+ config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
+ JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver(),
+ Formatting = Newtonsoft.Json.Formatting.Indented,
+ NullValueHandling = NullValueHandling.Ignore,
+ };
+
+ // Web API configuration and services
+
+ // Web API routes
+ config.MapHttpAttributeRoutes();
+
+ config.Routes.MapHttpRoute(
+ name: "DefaultApi",
+ routeTemplate: "api/{controller}/{id}",
+ defaults: new { id = RouteParameter.Optional });
+ }
+ }
+}
diff --git a/CSharp/demo-RollerSkill/Controllers/MessagesController.cs b/CSharp/demo-RollerSkill/Controllers/MessagesController.cs
new file mode 100644
index 0000000000..d85ce651e4
--- /dev/null
+++ b/CSharp/demo-RollerSkill/Controllers/MessagesController.cs
@@ -0,0 +1,27 @@
+namespace RollerSkillBot
+{
+ using System.Net;
+ using System.Net.Http;
+ using System.Threading.Tasks;
+ using System.Web.Http;
+ using Microsoft.Bot.Builder.Dialogs;
+ using Microsoft.Bot.Connector;
+ using RollerSkillBot.Dialogs;
+
+ [BotAuthentication]
+ public class MessagesController : ApiController
+ {
+ ///
+ /// POST: api/Messages
+ /// Receive a message from a user and reply to it
+ ///
+ public async Task Post([FromBody]Activity activity)
+ {
+ await Conversation.SendAsync(activity, () => new RootDispatchDialog());
+
+ var response = Request.CreateResponse(HttpStatusCode.OK);
+
+ return response;
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSharp/demo-RollerSkill/Dialogs/CreateGameDialog.cs b/CSharp/demo-RollerSkill/Dialogs/CreateGameDialog.cs
new file mode 100644
index 0000000000..27be538a2d
--- /dev/null
+++ b/CSharp/demo-RollerSkill/Dialogs/CreateGameDialog.cs
@@ -0,0 +1,70 @@
+namespace RollerSkillBot.Dialogs
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using Microsoft.Bot.Builder.Dialogs;
+ using RollerSkillBot.Properties;
+
+ [Serializable]
+ public class CreateGameDialog : IDialog
+ {
+ public async Task StartAsync(IDialogContext context)
+ {
+ context.UserData.SetValue(Utils.GameDataKey, new GameData());
+
+ var descriptions = new List() { "4 Sides", "6 Sides", "8 Sides", "10 Sides", "12 Sides", "20 Sides" };
+ var choices = new Dictionary>()
+ {
+ { "4", new List { "four", "for", "4 sided", "4 sides" } },
+ { "6", new List { "six", "sex", "6 sided", "6 sides" } },
+ { "8", new List { "eight", "8 sided", "8 sides" } },
+ { "10", new List { "ten", "10 sided", "10 sides" } },
+ { "12", new List { "twelve", "12 sided", "12 sides" } },
+ { "20", new List { "twenty", "20 sided", "20 sides" } }
+ };
+
+ var promptOptions = new PromptOptionsWithSynonyms(
+ Resources.ChooseSides,
+ choices: choices,
+ descriptions: descriptions,
+ speak: SSMLHelper.Speak(Utils.RandomPick(Resources.ChooseSidesSSML)));
+
+ PromptDialog.Choice(context, this.DiceChoiceReceivedAsync, promptOptions);
+ }
+
+ private async Task DiceChoiceReceivedAsync(IDialogContext context, IAwaitable result)
+ {
+ GameData game;
+ if (context.UserData.TryGetValue(Utils.GameDataKey, out game))
+ {
+ int sides;
+ if (int.TryParse(await result, out sides))
+ {
+ game.Sides = sides;
+ context.UserData.SetValue(Utils.GameDataKey, game);
+ }
+
+ var promptText = string.Format(Resources.ChooseCount, sides);
+
+ // TODO: When supported, update to pass Min and Max paramters
+ var promptOption = new PromptOptions(promptText, speak: SSMLHelper.Speak(Utils.RandomPick(Resources.ChooseCountSSML)));
+
+ var prompt = new PromptDialog.PromptInt64(promptOption, min: 1, max: 100);
+ context.Call(prompt, this.DiceNumberReceivedAsync);
+ }
+ }
+
+ private async Task DiceNumberReceivedAsync(IDialogContext context, IAwaitable result)
+ {
+ GameData game;
+ if (context.UserData.TryGetValue(Utils.GameDataKey, out game))
+ {
+ game.Count = await result;
+ context.UserData.SetValue(Utils.GameDataKey, game);
+ }
+
+ context.Done(game);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSharp/demo-RollerSkill/Dialogs/HelpDialog.cs b/CSharp/demo-RollerSkill/Dialogs/HelpDialog.cs
new file mode 100644
index 0000000000..54373e2429
--- /dev/null
+++ b/CSharp/demo-RollerSkill/Dialogs/HelpDialog.cs
@@ -0,0 +1,40 @@
+namespace RollerSkillBot.Dialogs
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+ using Microsoft.Bot.Builder.Dialogs;
+ using Microsoft.Bot.Connector;
+ using RollerSkillBot.Properties;
+
+ [Serializable]
+ public class HelpDialog : IDialog
+
+
diff --git a/CSharp/demo-RollerSkill/packages.config b/CSharp/demo-RollerSkill/packages.config
new file mode 100644
index 0000000000..0648596f79
--- /dev/null
+++ b/CSharp/demo-RollerSkill/packages.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file