TechBash 2018 will be better than ever. Here’s some exciting information about our next conference…


TechBash | Oct 2-5, 2018 | Kalahari Resort, Pocono Mountains, PA


Keynote Speaker

We are really excited to have Scott Hunter presenting our keynote this year. If you work with .NET or ASP.NET you should know who he is! If you don’t, here is his bio:

Director of Program Management on the .NET team at Microsoft. His team builds .NET Core, .NET Framework, ASP.NET, Entity Framework, managed languages (C#/F#/VB) and the Web and .NET Tooling for Visual Studio.

Yes, you read the correctly, his team builds a lot of stuff. We told you we bring in the experts!

Full Day Workshops

Our attendees have been asking for these and we have delivered. This year, we are proud to offer you 4 choices. They are optional and cost extra. So you can buy a regular, 3-day ticket to TechBash, or you can opt for a 4-day ticket that includes the workshop + the conference. Again, we weren’t kidding when we said we bring in the experts. Check out the talks and the presenters and click the links for more details.

Get Started Building a Web Application with ASP.NET Core

Presented by Jeff Fritz – Sr. Program Manager, Microsoft

DevOps with Visual Studio Team Services (VSTS)

Presented by Paul Hacker – DevOps Architect, Microsoft and Mitch Denny – Sr. Program Manager, Microsoft

Azure for Developers

Presented by Jeremy Likness – Cloud Developer Advocate, Microsoft, Anthony Chu – Cloud Developer Advocate, Microsoft and Brandon Minnick – Cloud Developer Advocate, Microsoft

Deploying Multi-OS applications with Docker EE

Presented by Anoop Kumar – Solution Architect, Docker

Early Bird Discount

TechBash is always a great deal. But, it’s even better when you get the early bird discount. Our best deal of the year expires on June 30th. Get your tickets now!

It’s time to convince your boss!

There are so many reasons to attend TechBash 2018. Here’s a list of things to help you convince your boss to send you to TechBash:

What you’ll learn:

  • TechBash has great content on topics like ASP.NET, Azure, DevOps, C#, and JavaScript
  • TechBash includes great sessions on current topics to help you get your job done!
  • TechBash has great sessions that help you take your skills to the next level!
  • TechBash offers great sessions that give you a glimpse at what’s new!
  • Yeah, TechBash has non-technical content too. Soft skills matter!

Who you’ll meet:

  • We bring in experts from around the country to teach you!
  • Since TechBash is smaller than a lot of other events, we provide great
    networking opportunities. We have a great Attendee Lounge where you can meet
    with your peers, follow up with speakers, and meet our sponsors too!

Here’s how you’ll save money:

  • If you live in the region, travel is easy by car. That means no expensive plane tickets. No need to fly to Orlando or Las Vegas for a conference. We bring the content to you!
  • Also, if you live in the region, you don’t need extra travel days out of the office!
  • TechBash is not-for-profit event. We aren’t in this to make money and our price reflects that! Our goal is to make TechBash affordable.

You’ll have fun:

  • You don’t have to tell your boss that you’ll have fun too! TechBash is hosted at the Kalahari Resort, home to the largest indoor water park in the country. Our Kalahari hotel prices are great and include water park admission.

I hope to see you in the Poconos this October!

-Andy

First, an important note. This content is for Bot Builder SDK v4 which is, at the time of writing this, in pre-release.

In preparing for some upcoming presentations on Creating Bots, I’m upgrading a bot from Bot Builder SDK v3 to v4. It’s new so there isn’t a ton of documentation or samples out there. But if you are building bots for Azure, now is the time to start learning about v4. It’s quite different than the predecessor.

With the old version, you could use the FormFlow feature to easily create “forms” that would gather information needed by the bot to accomplish a task. Consider that if a bot is taking a pizza order, it would need to ask the customer what kind of pizza, what size, find out about side orders and drinks, etc. We had access to the FormBuilder to easily compose a set of prompts to gather the data. Well, in v4, the FormFlow is gone. That’s ok, the new Bot Builder Framework is better Smile.

Again, I am still learning about the new version of the framework and I won’t begin to explain it all here. I found most of the docs very helpful and it was pretty easy to get going. And of course, you can see the source code for the framework on github. However, when it came to providing choices for the user, I couldn’t quite figure it out. I reached out for some help (being a Microsoft MVP has its privileges) and Gary Pretty came to the rescue, pointing me to a sample here. While that sample was helpful, I’ll provide more of an explanation.

So, here is the part about how it works…

The full solution is on github, check it out if you want.

The replacement for the FormFlow is to use a DialogContainer with a list of WaterfallSteps. You can then add a waterfall step for each question you want the user to answer. The questions are asked with the help of a prompt. There are prompts to collect text, numbers, dates, and more. I want to prompt the user to pick an item from a list, so I use the ChoicePrompt. In the constructor of the DialogContainer I have created a prompt:

    var auto = new ChoicePrompt(Culture.English) { Style = ListStyle.Auto };
    Dialogs.Add("auto", auto);

I’ve set the ListStyle to Auto. I’ll get into more detail on that later.

In my constructor I have a list of choices (List<Choice>) and ChoicePromptOptions which wrap the choices and a few other properties including the RetryPromptString.

    var choices = new List<Choice>();
    choices.Add(new Choice { Value = "Plain Pizza", Synonyms = new List<string> { "plain" } });
    choices.Add(new Choice { Value = "Pizza with Pepperoni", Synonyms = new List<string> { "4 Day", "workshop", "full" } });
    choices.Add(new Choice { Value = "Pizza with Mushrooms", Synonyms = new List<string> { "mushroom", "mushrooms", "shrooms" } });
    choices.Add(new Choice { Value = "Pizza with Peppers, Mushrooms and Brocolli", Synonyms = new List<string> { "vegtable", "veggie" } });
    choices.Add(new Choice { Value = "Pizza with Anchovies" });

    _choicePromptOptions = new ChoicePromptOptions { Choices = choices, RetryPromptString = "Sorry, that isn't on the list. Please pick again."};

I also created a WaterFallStep which is really just a method that looks like this:

    private async Task AutoPrompt(DialogContext dc, IDictionary<string, object> args, SkipStepFunction next)
    {
        await dc.Prompt("auto", "What kind of Pizza would you like?", _choicePromptOptions);
    }

Note that here I am telling the DialogContext to show the ChoicePrompt (referring to it by name “auto”), I supply text (“What kind of pizza…”) and the ChoicePromptOptions. This means I can reuse the prompt by providing different text and choices if I want to.

Back in my constructor, I add that waterfall step to my Dialogs collection:

    Dialogs.Add(Id, new WaterfallStep[]
    {
        AutoPrompt
    });

Check it out, it works! Here are some screen shots from the emulator:

image.

 

More Options

While we are here, let’s get into some other settings.

First there are the list style options:

image

 

Prompt Style Samples

I used Auto before, you can see the result above.

Here is a sample using Inline

image

List looks a lot like auto right? (I think Auto will change depending on the channel for your bot. List is just a list.

image

As the name suggests, None doesn’t provide any prompts at all.

image

Lastly, here is SuggestedAction. It provides a list of buttons for the user to click. Depending on your situation this can be a great option.

image

 

Also the RetryPromptString allows you to provide text to display if the user enters a value that doesn’t match up to one of the provided options. Note that if you don’t supply a RetryPromptString and in response to the pizza question, a user enters “hot dog”, the bot won’t react well. In my full sample code I have multiple WaterfallSteps and if a user enters an incorrect response, the bot resets the steps and starts from the beginning. Including RetryPromptString let’s the bot ask again and everything works out.

There are other ChoiceOptions for a ChoicePrompt. You can specify if the numbers should be displayed alongside the list items and customize character used to separate the items in the list such as using a comma or pipe.

image

User Input

The cool part about this is that regardless of which option you use, the user can respond in a variety of ways.

  • For any of these options, the user can simply enter a “3” to indicate “Pizza with Mushrooms”.
  • Users can also input “Pizza with Mushrooms” to select that option.
  • User can also input “mushroom” and get the right selection. That’s because I provided Synonyms for most of the choices. This is a really cool feature.
  • Interestingly, using a number, the text or a synonym all work for the None prompt as well.
  • And Of course, for the SuggestedAction type, users can click the button.

If you want to see all of the code, you can get it on github. I’ve created a sample that includes all of the prompts.

 

 

 

OK, I’m a little late at getting to this but I have just posted the code for my recent talk: Creating Awesome Chat Bots with the Bot Framework and C#.

To all that attended, thanks for joining me. I had a lot of fun preparing and presenting.

The code is here: https://github.com/schwammy/bot-demo

Unfortunately, this isn’t the easiest sample to get running. I think the code serves as a good example of some great things you can do with bots. However, if you want to actually use it, there are several steps that need to be done in advance. I’ve copied the text below from the readme file. As I say in a lot of my presentations, each step is pretty easy. However, putting them all together, especially for the first time, can be tricky. There are lots of good articles and videos on the web already for getting started with Bot Framework (and LUIS and QnA). I suggest reading up a bit and then follow my very basic instructions to get the code sample running.

Contact me if you have any questions or issues. Have Fun!

Getting Started

Before using this code you need to get set up

  1. Follow the instructions in the Prerequisites section here: https://docs.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-quickstart
  2. Install the emulator. The link is on the same page as above in the section: “Test your bot”

  3. You will also need:

Resources Setup

  1. After you create a LUIS account, create a LUIS app. You can leave it blank if you want. TechBashBot.sln contains a file LuisModel.json that can be imported to get started quickly.

  2. After you create a QnA Maker account, create a QnA service. You can import the questionsn and answers from TechBashBot.sln using the QnAMaker.tsv file.
  3. After you create your Azure Account, create a Web App Bot. Just add a resource and search “bot”, then choose Web App Bot

App Configuration

Once all of your resources are set up, you need to configure the code:

  1. Update the web.config file with the MicrosoftAppId and MicrosoftAppPassword for your new Web App Bot

  2. Update LuisDialog.cs by setting the new LUIS model id and subscription key
  3. Update QnADialog.cs by setting the QnA Service subscription key and knowledgebase id

Not a lot has changed with LINQ over the years. But I still find that developers aren’t completely familiar with the differences with some of the methods. In this post I’ll show the differences between:

  • Single()
  • SingleOrDefault()
  • First()
  • FirstOrDefault()

Of course these methods are similar but there are times when using the wrong one could lead to big problems with your application. The obvious similarity between these methods is that they are meant to return a single item. This is quite different from methods like Where() which returns a collection of items.

Now let’s focus on the differences.

I have noticed that in most cases, developers tend to use First() as the go to method for returning a single item from a collection. In my opinion, this is a bad idea. I tend to use Single() more often but of course there are times when each is appropriate. Here’s why…

Let’s start with a data set to work from. Here are some members of two great bands:

	List<Person> list = new List<Person>();
	list.Add(new Person {Id = 1, FirstName = "John", LastName = "Lennon"});
	list.Add(new Person {Id = 2, FirstName = "Paul", LastName = "McCartney"});
	list.Add(new Person {Id = 3, FirstName = "George", LastName = "Harrison"});
	list.Add(new Person {Id = 4, FirstName = "Ringo", LastName = "Starr"});
	list.Add(new Person {Id = 5, FirstName = "Jimmy", LastName = "Page"});
	list.Add(new Person {Id = 6, FirstName = "Robert", LastName = "Plant"});
	list.Add(new Person {Id = 7, FirstName = "John", LastName = "Bohnam"});
	list.Add(new Person {Id = 8, FirstName = "John Paul", LastName = "Jones"});

Let’s assume that the Id field is unique.

First, the method Single()

If I want to select a user by Id, I could use Single()

Person x = people.Single(p => p.Id == 1);

That will return the Person object for John Lennon.

For Single, the big difference comes when things aren’t as I expect them to be. Consider the following examples.

Person x = people.Single(p => p.Id == 9);

In this case, there is no person with an Id of 9. So Single() will throw an exception: “Sequence contains no matching element”.

Here’s another scenario

Person x = people.Single(p => p.FirstName == "John");

This too will throw an exception. This time it is “Sequence contains more than one matching element”.

So which is the best to use? It really depend on the situation. Often when you are selecting an item by Id, it is because you already know the Id. And if you do, I think it is safe to expect that the object with that Id exists. So I use Single(). In this case, the exception will be thrown if the user doesn’t exist but maybe that is ok because exceptions are for when things go wrong and in this case, something must have gone wrong. I also showed using Single(p => p.FirstName == “John”). But why would I do that? What reason could I have for selecting a Single item by a field that is not unique? Was I just curious to know if we had any Johns in the system? Would I have been better off with Any(p => p.FirstName == “John”) that returns a boolean?

Another option is SingleOrDefault()

Person x = people.SingleOrDefault(p => p.Id == 1);

This too will return the object for John Lennon.

Person x = people.SingleOrDefault(p => p.Id == 9);

SingleOrDefault() is safer. This time instead of an exception, x will be Null. Of course, as the developer, only I can decide which is better (Single or SingleOrDefault). It really depends on what I expect to happen and what other code exists to deal with unexpected results.

Person x = people.SingleOrDefault(p => p.FirstName == "John");

And SingleOrDefault() will still throw an exception if there is more than one “John”: “Sequence contains more than one matching element”

Next, a look at First() and FirstOrDefault()

Often, First() will give similar results but I find it misleading and using First() where inappropriate may actually hide problems. Consider the following:

Person x = people.First(p => p.Id == 1);

This too returns the object John Lennon.

Seems like everything is fine. But what if our data was bad. What if somehow we had two people with Id 1. Before you say “that would never happen”, think about some of the systems that you have supported. What if there was a mistake in the data entry validation? What if there was a bad import. My point is, it could happen. So now, if we use First(), we will get the first item in the collection that has the matching Id. It seems to me like in this case, I’d rather have Single throw an exception for me!

Unlike Single(), First() will NOT throw an exception if there is more than one matching element. Consider this:

Person x = people.First(p => p.FirstName == "John");

You can’t just assume that the result is John Lennon. It could depend on your data source and how the data was entered. Also, if a statement also had an OrderBy()

Person x = people.OrderBy(o => o.LastName).First(p => p.FirstName == "John");

Now I’m getting John Bohnam.

Yes, there are definitely cases when this is OK. But most of the time, I’d bet it is not. Why would I ever want the First() John?

Person x = people.FirstOrDefault(p => p.FirstName == "John");

This would have the same result as above. I could get John Lennon or John Bohnam depending on other factors.

Person x = people.FirstOrDefault(p => p.FirstName == "Pete");

Here, I get Null again (no exception). Sorry Pete Best, you’re not in the list.

So which to use?

There are circumstances for all of these. It’s great that we have 4 options. The important part is that as the developer, you understand that these are different. Please just don’t fall back on First() and use it all the time. Think about which is right for the circumstances you have at the moment.

One last tip

These statements may work correctly but they are just wasting keystrokes. I always say “less is more” with code.

Person x = people.Where(p => p.Id == 1).Single();
Person x = people.Where(p => p.Id == 1).First();

Please don’t do that. It’s much simpler to just say:

Person x = people.Single(p => p.Id == 1);
Person x = people.First(p => p.Id == 1);

The Microsoft Bot Framework makes it pretty easy to get started creating Chat Bots. If you haven’t gotten started yet, I recommend checking out this site: Bot Framework.

For a recent Bot that I created, we had the need for the Bot to expand. What I mean is, I want my bot chat UI to start out collapsed like a search box but then expand once a user starts talking to my bot.

7F9021F8-69F8-40A0-A26B-8EEC0CD32A1B

 

There are lots of examples for getting started with the Bot Framework. For this post, I will assume you already know how to do that. Hopefully you already know how to hook up the Web Chat control to communicate with your bot – here are some details about that.

I’ll start with the client-side code for this feature

For this feature, we will utilize the Web Chat’s backchannel using the DirectLine connection to the Bot. Then we can respond to events sent to the Web Chat from the bot. Here is the JavaScript needed to do this.

First, create a connection to the Bot with DirectLine:

        var directLine = new BotChat.DirectLine({ secret: &quot;YOUR KEY GOES HERE&quot; })

Next, subscribe to the event. All I am doing is listening for the event named “init” and when it occurs, add a class “fullSize” to the HTML element that hosts the bot.

        directLine.activity$
            .filter(isInitEvent)
            .subscribe(changeSize);

        function isInitEvent(activity) {
            return activity.type === &quot;event&quot; &amp;&amp; activity.name === &quot;init&quot;;
        }

        function changeSize(activity) {
            console.log(&quot;here&quot;)
            var container = document.getElementById(&quot;bot-chat-container&quot;);
            container.classList.add(&quot;fullSize&quot;);
        }

Lastly, create the Web Chat:

        BotChat.App({
            botConnection: this.directLine,
            user: { id: &#39;user&#39; },
            bot: { id: &#39;bot&#39; },
        }, document.getElementById(&quot;bot-chat-container&quot;));

I’m just using a little CSS to hide and show the rest of the Web Chat UI. Feel free to enhance this part a little, it could be better. Hopefully you get the idea.

        #bot-chat-container {
            border: 1px solid #333;
            height: 50px;
        }

        #bot-chat-container.fullSize {
            height: 300px;
        }

        .wc-header {
            display: none;
        }

        .fullSize .wc-header {
            display: block;
        }

        .wc-console svg {
            fill: black;
            margin: 11px;
        }

        /* These styles are used to hide the upload button...*/

        .wc-console label {
            display: none;
        }

        .wc-console .wc-textbox {
            left: 10px;
        }

All that is left to show of the UI is this DIV. But this isn’t too exciting:

<div id="bot-chat-container" />

Here is the Server-Side Code

This whole thing is based on an event coming to the Web Chat UI from the Bot on the server. I’m using C# and it is pretty simple stuff. When you create a Bot, the MessagesController is stubbed out for you to handle various Activity Types. In this case, I am concerned with ActivityType.ConversationUpdate. Check to see if the a new member is added to the conversation and if so, send event named “init”.

private async Task&lt;Activity&gt; HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
		// ...
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                using (var scope = Microsoft.Bot.Builder.Dialogs.Internals.DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var client = scope.Resolve&lt;IConnectorClient&gt;();
                    if (message.MembersAdded.Any())
                    {
                        foreach (var newMember in message.MembersAdded)
                        {
                            if (newMember.Id != message.Recipient.Id)
                            {
                                var reply = message.CreateReply();
                                reply.Type = ActivityTypes.Event;
                                reply.Name = &quot;init&quot;;
                                await client.Conversations.ReplyToActivityAsync(reply);

                            }
                        }
                    }
                }
            }
		// ... etc. etc.

That’s all.