Using FormFlow in Microsoft Bot Framework (Creating lead in CRM)


Let us continue with our previous posts on using Microsoft Bot Framework

Getting Started with Microsoft Bot Framework.

Using Dialogs in Microsoft Bot Framework

To better understand the FormFlow refer to the below article.

https://docs.botframework.com/en-us/csharp/builder/sdkreference/forms.html

Here we will update our Bot Application to use the FormFlow instead of Dialog.

As FormFlow are bound to a model, we will create a model class first.

Create a new folder named Model and a new class named LeadModel in it.

The class has an enum for selecting Product Type. It defines property for capturing Name and Description.

Here we define a static method named BuildForm that returns the IForm of type LeadModel.

The message defines the initial message that will be shown to the user and oncompletion we are defining a callback method that will be called on completion which we will be using to create lead record in CRM.

Next update the MessageController.cs to call this Lead Model instead of dialog which we did in our previous post.

The conversation between the Bot and the User.

The lead record created in CRM.

Source Code –


using Microsoft.Bot.Builder.FormFlow;
using System;
using Microsoft.Bot.Builder.Dialogs;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk;

namespace Bot_Application1.Models
{

public enum InterestOptions { Product1 = 1, Product2 = 2, Product3 = 3};

[Serializable]
public class LeadModel
{
public InterestOptions Product;
public string Name;
public string Description;
public static IForm<LeadModel> BuildForm()
{
return new FormBuilder<LeadModel>()
.Message("Welcome to the CRM bot !")
.OnCompletion(CreateLeadInCRM)
.Build();
}
private static async Task CreateLeadInCRM(IDialogContext context, LeadModel state)
{
await context.PostAsync("Thanks for showing your interest we will contact you shortly.");
Entity lead = new Entity("lead");
lead.Attributes["subject"] = "Interested in product " + state.Product.ToString();
lead.Attributes["lastname"] = state.Name;
lead.Attributes["description"] = state.Description;
GetOrganizationService().Create(lead);
}

public static OrganizationServiceProxy GetOrganizationService()
{
IServiceManagement<IOrganizationService> orgServiceManagement =
ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri("https://nishantcrm365.crm.dynamics.com/XRMServices/2011/Organization.svc"));
AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = "nishant@nishantcrm365.onmicrosoft.com";
authCredentials.ClientCredentials.UserName.Password = *****";
AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);
return new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);
}
}
}


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 Microsoft.Bot.Builder.FormFlow;
using Bot_Application1.Models;

namespace Bot_Application1
{
[BotAuthentication]
public class MessagesController : ApiController
{
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
// call MyDialog
// await Conversation.SendAsync(activity, () => new Dialogs.MyDialog());

// Call our FormFlow by calling MakeRootDialog
await Conversation.SendAsync(activity, MakeRootDialog);

}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}

internal static IDialog<LeadModel> MakeRootDialog()
{
return Chain.From(() => FormDialog.FromForm(LeadModel.BuildForm));
}

private Activity HandleSystemMessage(Activity message)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
else if (message.Type == ActivityTypes.Ping)
{
}

return null;
}
}
}

The next posts in this series

Hope it helps

Using Dialogs in Microsoft Bot Framework (Creating lead in CRM)


Let us continue with our previous post on Bot Framework

https://nishantrana.me/2017/04/18/getting-started-with-microsoft-bot-framework/

Here we will implement our own dialog.

Dialogs are basically a class which implements IDialog interface. Dialog sends a message to the user and is in suspended state till it waits for the response from the user. The state is saved in State Service provided by Bot Connector Service.

Here MyDialog is our dialog class which implements the IDialog Interface i.e. implement StartAsync method which would be the first method called. We also need to mark our class as Serializable.

Next we need to update our controller class to point it to our new MyDialog class.

Here we will ask the user about the product in which he is interested, then get the name and description and finally using this information we will create a Lead record inside CRM.

The lead record created in CRM.

Here we are making use of PromptDialog type for managing interactions with the user. Using PromptDialog we can easily prompt user for text, choice, attachment, confirmation etc.

The context here is the IDialogContext. In resume parameter, we can specify which dialog methods to be called next after the user has responded. The response from the user is passed to the subsequent dialog methods.


using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Bot_Application1.Dialogs
{

public enum InterestOptions
{
Product1,
Product2,
Product3
}

// Decorate the class with Serializable attribute
[Serializable]
// Implement IDialog Interface
public class MyDialog : IDialog
{
InterestOptions interestOptions;
string name;
string description;

// Start Sysnc is the first method which is called
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Hi how may i help you?");
// wait for the user's response
context.Wait(MessageRecieveAsync);
}

public virtual async Task MessageRecieveAsync(IDialogContext context, IAwaitable argument)
{
// get the message
var message = await argument;

if (message.Text.Contains("interested"))
{
PromptDialog.Choice(
context: context,
resume: ResumeGetInterest,
options: (IEnumerable<InterestOptions>)Enum.GetValues(typeof(InterestOptions)),
prompt: "Which product are your interested in :",
retry: "I didn't understand. Please try again.");
}

}

public async Task ResumeGetInterest(IDialogContext context, IAwaitable result)
{
interestOptions = await result;

PromptDialog.Text(
context: context,
resume: ResumeGetName,
prompt: "Please provide your name",
retry: "I didn't understand. Please try again.");
}

public async Task ResumeGetName(IDialogContext context, IAwaitable result)
{
name = await result;

PromptDialog.Text(
context: context,
resume: ResumeGetDescription,
prompt: "Please provide a detailed description",
retry: "I didn't understand. Please try again.");
}

public async Task ResumeGetDescription(IDialogContext context, IAwaitable result)
{
description = await result;
PromptDialog.Confirm(
context: context,
resume: ResumeAndConfirm,
prompt: $"You entered Product :- '{interestOptions}', Your Name - '{name}', and Description - '{description}'. Is that correct?",
retry: "I didn't understand. Please try again.");
}

public async Task ResumeAndConfirm(IDialogContext context, IAwaitable result)
{
bool confirm = await result;

if (confirm)
await context.PostAsync("Thanks for showing your interest we will contact you shortly.");

// Create a lead record in CRM
CreateLeadinCRM();

}

private void CreateLeadinCRM()
{
Microsoft.Xrm.Sdk.Entity lead = new Microsoft.Xrm.Sdk.Entity("lead");
lead.Attributes["subject"] = "Interested in product " + interestOptions;
lead.Attributes["lastname"] = name;
lead.Attributes["description"] = description;
GetOrganizationService().Create(lead);
}

public static OrganizationServiceProxy GetOrganizationService()
{
IServiceManagement<IOrganizationService> orgServiceManagement =
ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri("https://nishantcrm365.crm.dynamics.com/XRMServices/2011/Organization.svc"));

AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = "nishant@nishantcrm365.onmicrosoft.com";
authCredentials.ClientCredentials.UserName.Password = "*****";
AuthenticationCredentials tokenCredentials = orgServiceManagement.Authenticate(authCredentials);
return new OrganizationServiceProxy(orgServiceManagement, tokenCredentials.SecurityTokenResponse);
}
}

}

The next posts in this series

Hope it helps..

Getting started with Microsoft Bot Framework


To get started with Bot Framework, download the visual studio template for Bot Application from the following location

http://aka.ms/bf-bc-vstemplate

Extract it and put the content at the following location. (Visual Studio 2017 in my case)

C:\Users\<<ComputerName>>\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual C#

Open Visual Studio and select Bot Application template to create a new project

This is how the basic structure of the bot application looks like

The most important part here being the MessageController class.

The class has the Post method which handles the message sent by the user/client termed as Activity. The Post method handles the Activity of type Message.

Below is the list of different type of Activities

DeleteUserData is when the client\user requests for Deletion of all the user data, ConversationUpdate is when a new member is added or removed from the conversation, Typing is when user is typing the message etc.

Now to test this sample application, we need to first download the Bot Emulator.

https://emulator.botframework.com/

Now run the bot application.

And next start the emulator

Enter the URL and click on Connect. We will leave App ID and Password as blank as we are testing it locally.

Just type in the message and we’d get the response back.

Details section shows the JSON message which could be useful for debugging and testing purpose.

Apart from sending message we can simulate other Activity Type from within the emulator

The next post in this series

Hope it helps..

Solved – You do not have permission to open this Web site in SharePoint Designer 2013


Recently we had installed SharePoint designer 2013, and while trying to open a SharePoint online web site.

However we were getting the below error.

“403 FORBIDDEN403 FORBIDDEN403 FORBIDDEN403 FORBIDDEN403 FORBIDDEN”

Installing the SharePoint designer SP 1 (64 bit in our case) https://www.microsoft.com/en-in/download/details.aspx?id=42009 fixed the issue.

Hope it helps..

Step by step – Upload files to Azure Blob storage


Here we will be creating a storage account of type blob storage and a container inside it. Then we will create a console application, add required nuget packages and upload a file to the container.

Log in to Azure Portal

https://portal.azure.com

Click on Add to add a new storage account.

Create a new container in it to store the blob files

Now we’d write a console app to connect to this container and upload a file.

Create a new console application and add references to below Nuget Packages.

  • Windows.Azure.Storage
  • Windows.Azure.ConfigurationManager

In Azure Portal – Storage Account, go to Access Keys and copy the connection strings for the storage account.

Inside console application add an appSettings section and add a key and paste the above copied connection string there.

The source code to upload the Blob file

// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));

// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("myblogcontainer");

// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("WeekendChamps.jpg");

// Create or overwrite the "myblob" blob with contents from a local file.
using (var fileStream = System.IO.File.OpenRead(@"C:\Users\Bliss\Downloads\WeekendChamps.jpg"))
{
blockBlob.UploadFromStream(fileStream);
}

The file uploaded in the container

Hope it helps..

Plugin Registration Tool and screen resolution issue


Plugin Registration Tool Resolution Issue

nirman1983's avatarNirman Doshi and his Dynamics Lab

If you are a CRM developer or consultant, you can’t live without Plugin Registration Tool. The tool provided with CRM SDK is MUST in order to register/ uninstall any plugin to a CRM instance, be it online or on-premises.

However, there is one weird issue with the tool (atleast the one provided in SDK 2013, and SDK 2016). That is, except for a few specific screen resolutions, the tool doesn’t show buttons to allow users to complete the actions.

Notice the screenshot below, where are the buttons to “Update Selected Plugins”? There is no scrollbar either.

PluginRegTool-Issue

There are few workarounds to get rid of this issue. For example, hitting TAB key for 2 times from the Step 2 control. Or hitting a shortcut key. But, for me the preferred method is to rotate the screen to left or right, this is because at least you can see what button you are hitting.

How…

View original post 73 more words

Nishant Rana's Weblog

Everything related to Microsoft .NET Technology

Skip to content ↓