public class Blazor in WordPress – Multiple Components

{

In my previous post, I showed how to simply embed a single Blazor Component inside a WordPress page or post. However, what I really want is the chance to willy-nilly throw in as many components as I want, wherever I want. This runs into some problems. If you try to just copy/paste my code from the first post multiple times, and run it with your dev tools open, you’ll see multiple errors.

 

The first issue is with the line <script src="_framework/blazor.webassembly.js"></script>. As with any javascript file, you should only import blazor.webassembly one time, not multiple times. Sure, I could remember just to do that the first time, but it would be even nicer to have it built into my WordPress blog, and never have to worry about adding that line. It’s also more “correct” for websites to import scripts and other files in the head or at the bottom of the body (footer area), rather than in the midst of the content.

 

If this were a custom website, I would just add the tag to index.html. But with WordPress, there’s lots of warnings about interfering scripts, loading order, and so forth, so they don’t recommend you do this yourself. Instead, I installed a plugin, Header and Footer Scripts, which gives you WP UI-level control over custom tags in a header and/or footer.

 

After installing the plugins, I moved the blazor.webassembly script to the header, and reloaded to make sure everthing still worked. I discovered that I also had to move <base href="/" /> to make it still work. But again, this is something you would only want to do once per page. (And, side note, it’s the biggest failing of this whole setup, as redirecting all url calls can interfere with other WP plugins.)

 

Finally, if we’re going to move scripts, we should also move any stylesheet link tags. With all those moved out of the way, now the in-post html looks much more concise and neat:

 

<div id="app">Loading...</div>

 

Great! But now…I want two different components. OK, so, obviously, I should replace the id="app" with some other ids. Let’s look again at what the reference looks like in our Blazor Web Assembly Program.cs file:

 

public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");

builder.Services.AddScoped(
sp => new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)});

await builder.Build().RunAsync();
}

[Program.Main]

 

We already mentioned in the last post that you can replace <App> and "#app" with your own razor component file and id tag. So I tried adding two.

 

builder.RootComponents.Add<DataGrid>("#grid");
builder.RootComponents.Add<MusicKeyboard>("#keyboard");

 

And this definitely worked with two Id’ed div elements in a page! Unfortunately…if you happen to only want to use one of your two components, then Blazor throws an error that it can’t find the matching div for the other one!

 

My first attempt to fix this was to revert back to just loading the App razor component, and using logic inside that to decide which other component to show. This turned out to work for single components, but Blazor would get confused if it saw two "app" divs!

 

Luckily, after some more Google-fu, I stumbled on this GitHub issue: Unable to use RootComponents twice on same page, where the original poster, Ecroyd, came up with a clever workaround of using a custom element tag (type) for each component, looking up which components are on the page with JSInterop, and then only adding the RootComponents that are found!

 

You can see Ecroyd’s version on the link above, but I did some more tweaking. I decided I would rather keep these div elements, and instead add a class="blazor-component" to identify each.

 

var jsRuntime = builder.Services.BuildServiceProvider().GetRequiredService<IJSRuntime>();
var module = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "/componentFinder.js");
var json = await module.InvokeAsync<JsonElement>("getBlazorComponents");
foreach(var id in json.EnumerateArray())
{
switch (id.ToString())
{
case "blazor-data-grid":
builder.RootComponents.Add<BdGridDemo>("#blazor-data-grid");
break;
case "blazor-music-keyboard":
builder.RootComponents.Add<MusicKeyboardDemo>("#blazor-music-keyboard");
break;
}
}

[Program.Main changed code]

 

export function getBlazorComponents() {
return Array.from(document.querySelectorAll('.blazor-component')).map(a => a.id);
}

[componentFinder.js lookup module]

 

Now, for each component I want to embed, I add the following (some styling added for layout):

 

<div class="blazor-component" style="height: 550px; background: white; padding: 10px; overflow-x: scroll;" id="blazor-music-keyboard">Loading Blazor Music Keyboard ... </div>

 

 

Loading Blazor Music Keyboard …

 

Or

 

<div class="blazor-component" style="height: 800px; overflow-y: scroll; width: 100%; background: white; color: black; padding: 20px; font-family: arial;" id="blazor-data-grid">Loading Blazor Data Grid ... </div>

 

 

Loading Blazor Data Grid …
}

public class Embedding Blazor Components in WordPress

{

In my previous post, Blazor Data Grid, I showed off a new Blazor web component, and at the bottom of the post, I actually had a demo version of the component right here in this blog, which is running on WordPress. Hat tip to Virtual Dan at http://dano.vfsystems.net/2020/03/blazor-and-wordpress/ for getting me pointed in the right direction!

 

The gist of it is, since Blazor components can run in WebAssembly, all you need for a functioning embedded component is a Blazor WebAssembly project with a single component, published up to a folder in your WordPress (or other site) directory, a script tag to load blazor’s runtime, and a div with a pre-determined Id.

 

I started with the default Blazor Web Assembly template in Rider (my IDE of choice, but VS or VS Code work fine as well). In Program.Main, you see the following line:

 

builder.RootComponents.Add<App>("#app");

 

This defines the key div as having id="app", and points to a blazor component or razor file named App.razor. You can of course change both the Id string value and the razor file loaded. In my case, I decided that I didn’t need all the routing logic in App.razor for an embedded component project, so I deleted this (and many other files). At first, I just pointed to the component I wanted to render. Note that if you change the Id, you will also want to update your index.html file to match, so you can test your application. Running in debug, you get a simple rendering of your component in a blank page.

 

Loading Blazor Music Keyboard …

[Demo Musical Keyboard (Xylophone) Component]

 

Now that we have a working Blazor Wasm component, we want to get it up to our WordPress server. I recommend setting up some form of automated deployment on git commit, so that you don’t have to manually copy files every time you make a change (I use Azure DevOps Pipelines, but there are many solutions). Basically, you want everything in the /wwwroot folder of your publishing step to be directly copied into your root WordPress folder, like say /etc/wordpress/. This should be the same folder as wp-config.php.

 

That “everything” mentioned above includes two important folders, _content and _framework. _framework is the .NET Runtime and Wasm assemblies. We will discuss _content later. You should also see your index.html (although we won’t be using this), and any css or javascript files you created in your wwwroot.

 

Once the files are in place, load up the WordPress post or page editor, and add a “Custom HTML” block. Add the following code (I’m reverting back to the default “app” id here):

 

<div>
  <base href="/" />
<link href="YourApplication.styles.css" rel="stylesheet" />
  <div id="app">Loading...</div>
<script src="_framework/blazor.webassembly.js"></script>
</div>

 

This is based on Virtual Dan’s version, (thanks again). Let’s break it down.

 

The stylesheet link is only important if you actually created any styles for your component. We’ve already mentioned that we need a div with the correct Id. Whatever you put inside the div (e.g., “Loading…”) will show for a second or two while blazor boots up. Then it gets overwritten by the contents of your component. Below this is the script that loads Blazor Web Assembly.

 

I noticed the <base href="/" /> in Virtual Dan’s source code on his site. He doesn’t mention it in the explanations, but I figured out the reason for this. Without re-setting the base url, I would get errors with looking for blazor.webassembly.js at whatever the page url is, like https://tocode.software/2021/03/04/Blazor/_framework/blazor.webassembly.js. Obviously, I don’t want to put my framework at this location on disk, if I want to share it with multiple pages in the future, and prevent it from breaking if the url ever changes. I did tinker around with starting the script src with and without the forward slash, but it didn’t seem to work either way, until I discovered what Dan was doing with the base href.

 

If you’ve successfully followed thus far, publish or preview your wordpress page, and give yourself a high five for running Blazor in WordPress! I will follow up in the next few days with another post about refactoring and supporting multiple components.

}

public class Episode 13: Collections & Generics

{

Subscribe

public void Summary()

{

Tim & Tim discuss collections, all the way from IL arrays to .NET Lists, Dictionaries, HashSets, and generics!

}

public void Links()

{

}

public void HotSpot()

{

}

}

public class Black Lives Matter

{

Last weekend, our hearts were too heavy with the news of yet another brutal murder of a black man by authorities, reflecting on our own privileges, and trying to come up with ways to help in the ongoing protest movement. So, we did not make a podcast episode. I will be posting a new tech blog article soon, and we hope to be back up and running with new episodes next week!

}

public class Episode 4: Teaming Up!

{

Subscribe

public void Summary()

{

Tim & Tim discuss the challenges and rewards of becoming team members vs. working as a solo dev.

}

public void Links()

{

}

public void HotSpot()

{

  • Display Fusion – Advanced Multi-Monitor support tool.
  • PowerToys – Free Windows plugin for multimonitor, shortcut keys, and other simple tools.

}

}

public class Episode 3: Abstract Thoughts on Abstractions

{

Subscribe

public void Summary()

{

Tim & Tim pontificate on the layers of abstractions that both make coding possible, and sometimes get in the way.

}

public void News()

{

public void HotSpot()

{

  • NotePad++ – Replacement for NotePad that will open any file, search through text of all files, and even function as a simple code editor
  • DotNetFiddle.net – Online environment for writing and compiling simple .NET test programs. Embeddable in other applications!

}

}

public class Lesson6_GoFish_Pt2

{

void StartingTheGame()

{

This is a continuation of Lesson5_GoFish_Pt1. The full project code can be viewed or downloaded at https://github.com/TimPurdum/GoFish. In the previous post, we created a model of all the pieces needed to play the game, namely a Deck of Cards and Players with Hands and Sets.

For this part, we will be describing and programming the action or gameplay. Since the project is short, we will do this all within the Program class, although you could certainly create a Game class and move most of the code there. Let’s start by instantiating two players (one human and one computer) and a deck of cards as class fields that can be accessed from any method. The readonly tag means that these objects cannot be recreated (written to) later, although the methods and properties within are still writable.

        static readonly Deck Deck = new Deck();
        static readonly Player AI = new Player();
        static readonly Player Player = new Player();

Now let’s look at our Main method. Of course, you could put the entire logic into this method, but that would be poor design, and harder to read. Instead, we will simply deal with the introduction, shuffling the deck, and starting a while loop to create the game turns.

        static void Main()
        {
            Console.WriteLine("Let's play Go Fish!");
            Console.WriteLine("Type the letter 's' to shuffle the deck.");
            if (Console.ReadLine()?.ToLower() == "s")
            {
                Console.WriteLine("Shuffling...");
                Deck.Shuffle();
                Console.WriteLine();
                Deck.Deal(new List{Player, AI}, 7);

                while (Deck.Count > 0)
                {
                    ShowHand();
                    Guess();
                    AIGuess();
                }

                GameOver();
            }
        }

Notice that just like in our ChatBot project, we are using Console.WriteLine and Console.Readline to communicate with the user. Of course, you don’t have to introduce the game at all, or you could make it more involved (get the player’s name, for example).

The while loop represents rounds of the game. In each round, first we will ShowHand to the player, so they know what cards they have. Then, they will make a Guess, and we will deal with the results of that guess. Finally, the computer player (AI) will make their AIGuess, and the loop starts over. It ends when the deck is empty.

}

void ShowYourCards()

{

Each turn, we want to tell the player what cards they are holding.

        static void ShowHand()
        {
            Console.WriteLine("Here is your hand:");
            foreach (var card in Player.Hand)
            {
                Console.WriteLine($" - {card.Rank} of {card.Suit}");
            }
        }

}

void PlayersTurn()

{

Now it’s time for the player to take a turn. For this, we need to use Console.ReadLine() again. The player must have that rank in their hand (and if they have none, they simply draw). If the card is found, it is removed from the AI’s hand and given to the player. If not, the player must draw.

        static void Guess()
        {
            if (Player.Hand.Count == 0)
            {
                Console.WriteLine("No cards, you must draw this turn!");
                Deck.Draw(Player, 1);
                return;
            }
            
            Console.WriteLine();
            Console.WriteLine("Ask me if I have a card...");
            Console.WriteLine("(e.g., Ace, Two, Three, Four, King...)");
            var guess = Console.ReadLine();

            while (Player.Hand.All(c => c.Rank.ToString().ToLower() != guess?.ToLower()))
            {
                Console.WriteLine("You may only guess card numbers that you already have.");
                Console.WriteLine("Ask me if I have a card...");
                guess = Console.ReadLine();
            }
            
            Console.WriteLine();
            var cards = FindCards(guess, AI);
            
            if (cards != null)
            {
                var message = $"You got {cards.Count} {cards.First().Rank}!";
                if (cards.Count > 1)
                {
                    message = $"You got {cards.Count} {cards.First().PluralName}!";
                }
                Console.WriteLine(message);
                
                Player.Hand.AddRange(cards);
                foreach (var c in cards)
                {
                    AI.Hand.Remove(c);
                }
                LayoutSets(Player);
                Guess();
            }
            else
            {
                Console.WriteLine("No! Go Fish!");
                Thread.Sleep(1000);
                Deck.Draw(Player, 1);
                var newCard = Player.Hand.Last();
                Console.WriteLine($"You drew the {newCard.Rank} of {newCard.Suit}");
                LayoutSets(Player);
            }
        }

There are two places here where we have called new methods. The first is FindCards, which will search the AI player’s hand for the rank that was guessed. We are making heavy use of LINQ lambda expressions here, which you can learn more about. Any and Where are two LINQ statements that allow you to query a collection, such as a List or Array. Within each one, we declare an internal variable c, which represents each Card in the List, similar to a foreach statement. If the rank isn’t found, we can simply return null, which means no List was found.

        static List FindCards(string guess, Player p)
        {
            var cardGuess = guess.Trim().ToLower();

            if (p.Hand.Any(c => c.Rank.ToString().ToLower() == cardGuess))
            {
                return p.Hand.Where(c => c.Rank.ToString().ToLower() == cardGuess).ToList();
            }
           
            return null;
        }

The second new method is LayoutSets. This is where we will check to see if the player has four matching cards, and if so, move those sets to the Sets List.

        static void LayoutSets(Player p)
        {
            Console.WriteLine();
            
            var numberGroups = p.Hand.GroupBy(c => c.Rank);
            foreach (var numberGroup in numberGroups)
            {
                if (numberGroup.Count() == 4)
                {
                    var numberCards = numberGroup.ToList();
                    p.Sets.Add(numberCards);
                    foreach (var c in numberCards)
                    {
                        p.Hand.Remove(c);
                    }
                }
            }
            
            if (p.Sets.Count == 0)
            {
                return;
            }

            ShowSets(p);
        }

Notice that both FindCards and LayoutSets take a Player as an argument. This means that we can reuse these classes when it comes to the AI’s turn.

}

void ComputersTurn()

{

Once the player has finished, we give the computer (AI) a turn. Using Thread.Sleep() here and there can give the game a more pleasant pace, as modern computers are so fast that they will run through all these commands in less than a second.

Of course, in order to guess, we have to have the AI choose a random card rank from its hand. Luckily, .Net has a function called Random() that can do just that!

        static void AIGuess()
        {
            if (AI.Hand.Count == 0)
            {
                Console.WriteLine("No cards, I must draw this turn!");
                Deck.Draw(AI, 1);
                return;
            }
            
            var randomGenerator = new Random();

            var guessCard = AI.Hand[randomGenerator.Next(0, AI.Hand.Count - 1)];
            
            Console.WriteLine("My turn.");
            
            Console.WriteLine($"Do you have any {guessCard.PluralName}?");
            Thread.Sleep(2000);
            Console.WriteLine();
            var cards = FindCards(guessCard.Rank.ToString(), Player);
            
            if (cards != null)
            {
                if (cards.Count == 1)
                {
                    Console.WriteLine($"Yes? I'll take that {guessCard.Rank}!");
                }
                else
                {
                    Console.WriteLine($"Yes? I'll take those {guessCard.PluralName}!");
                }
                
                AI.Hand.AddRange(cards);
                foreach (var c in cards)
                {
                    Player.Hand.Remove(c);
                }
                LayoutSets(AI);
                AIGuess();
            }
            else
            {
                Console.WriteLine("No? I have to draw...");
                Thread.Sleep(1000);
                Deck.Draw(AI, 1);
                LayoutSets(AI);
            }
        }

As mentioned above, we re-use FindCards and LayoutSets for both players. Code re-use is an important principal in good programming.

}

void GameOver()

{

Let’s wrap up the game by totaling up the sets laid out and declaring a winner!

        static void GameOver()
        {
            Console.WriteLine("Game Over!");
            var playerPoints = 0;
            Player.Sets.ForEach(set => playerPoints += set.Count);
            Console.WriteLine($"Your score is {playerPoints}");
            var aiPoints = 0;
            AI.Sets.ForEach(set => aiPoints += set.Count);
            Console.WriteLine($"My score is {aiPoints}");
            if (playerPoints > aiPoints)
            {
                Console.WriteLine("You Win!");
            }
            else if (aiPoints > playerPoints)
            {
                Console.WriteLine("I Win!");
            }
            else
            {
                Console.WriteLine("Tie Game!");
            }
        }

If you have cloned the GitHub GoFish repository, and made changes to your version, feel free to create a pull request, to share your improvements back to our main repo! Or if you have a variation (maybe a new card game), you can share a link in the comments below.

}

}

public class Lesson5_GoFish_Pt1

{

void LetsPlayAGame()

{

It’s time to tackle a more complex assignment. We will start with a simple card game, “Go Fish.”

If you’ve never played, take a look at the directions at https://www.bicyclecards.com/how-to-play/go-fish/. We will be using a simple version of these rules to make our game. And if you would like to download or view the completed code project, go to https://github.com/TimPurdum/GoFish.

}

void ModelTheWorld()

{

Object-Oriented Programming is excellent for creating models of the real world, which, after all, is made up of objects. Let’s start by creating a model of a deck of cards. Actually, though, a deck of cards is just a collection of card objects, and we already know how to create collections! So, let’s start by creating a card object. What defines a card?

  • Suit – The color and symbol of the card. Hmm…maybe we need to represent suits as an object too. (In some other card games, the red suits are interchangeable, as are the black suits, so color might be important as well.)
  • Rank – The number or name of the card.

One simple way to create a list of value options is to create an enum. We will create two enums, one for Suit:

namespace GoFish
{
    public enum Suit
    {
        Hearts,
        Diamonds,
        Spades,
        Clubs
    }
}

And one for Rank:

namespace GoFish
{
    public enum Rank
    {
        Ace,
        Two,
        Three,
        Four,
        Five,
        Six,
        Seven,
        Eight,
        Nine,
        Ten,
        Jack,
        Queen,
        King
    }
}

In VS Code, go to File => New File, and add the code above for Suit. Save as Suit.cs, and then repeat and create Rank.cs. You should see these files added to your sidebar explorer, as well as the tabs at the top.

Now let’s create our Card file, saving it as Card.cs. Add the code below. Notice that this is now a class, out of which we can create all our cards. I’ve also created a property called PluralName so that I can return a string representation of the rank in its plural form.

namespace GoFish
{
    public class Card
    {
        public Suit Suit;
        public Rank Rank;
        
        public Card (Suit suit, Rank rank)
        {
            Suit = suit;
            Rank = rank;
        }


        public string PluralName
        {
            get
            {
                if (Rank == Rank.Six)
                {
                    return Rank + "es";
                }

                return Rank + "s";   
            }
        }
    }
}

Once we have the Card class, it is easy to build a collection of cards into a Deck. But instead of creating a collection by hand, I am using inheritance to create a special SubClass of List. Notice in the class declaration line, : List<Card>. This means that a Deck will inherit all the properties and methods of a List, such as Add and Remove. But in addition, we can add our own methods, like Shuffle and Draw.

using System;
using System.Collections.Generic;
using System.Linq;

namespace GoFish
{
    public class Deck : List
    {
        readonly Suit[] suits =
        {
            Suit.Hearts,
            Suit.Clubs,
            Suit.Diamonds,
            Suit.Spades
        };

        public Deck()
        {
            for (var i = 0; i < 13; i++)
            {
                foreach (var suit in suits)
                {
                    Add(new Card(suit, (Rank)i));
                }
            }
        }


        public void Shuffle()
        {
            var rnd = new Random();
            for (var i = 0; i < Count - 1; i++)
            {
                Swap(i, rnd.Next(i, Count));
            }
        }


        public void Deal(List players, int numberOfCards)
        {
            foreach (var player in players)
            {
                player.Hand = new List();
                Draw(player, numberOfCards);
            }
        }


        public void Draw(Player player, int numberOfCards = 1)
        {
            for (var cardNum = 0; cardNum < numberOfCards; cardNum++)
            {
                player.Hand.Add(this.First());
                RemoveAt(0);
            }
        }


        public Card Peek()
        {
            return this.First();
        }


        void Swap(int a, int b)
        {
            var temp = this[a];
            this[a] = this[b];
            this[b] = temp;
        }
    }
}

}

void ReadyPlayerOne()

{

We will create one more data model class, to signify a Player. Very simply, each player needs to have a Hand and Sets, or laid down 4-of-a-kind matches. Rather than create subclasses like we did for Deck, Hand uses the default List<Card> definition. Sets, however, is a List of a List, which allows you to track multiple groups of cards.

using System.Collections.Generic;

namespace GoFish
{
    public class Player
    {
        public List Hand { get; set; }
        
        public List<list> Sets { get; } = new List<list>();
    }
}</list</list

In our next post, we will explore how to lay out the action of the game!

}

}

public class Lesson4_Classes

{

public void WeNeedMoreClass()

{

While it’s nice to see all of your code in one place, as programs get larger, organization can become a hassle with long files. Just as we split up our Program class into multiple methods, we can also split up our code into multiple class files.

Actually, a class is just another OOP encapsulation, and multiple classes could live in the same file.

This allows me to show you two classes functioning in dotnetfiddle (which is limited to one file for console apps), but it mostly defeats the purpose of separating the code into classes. Traditionally for larger projects, classes are saved each to their own file. In VS or VS Code, you can manage these files just like any other file-based application. Right-click over the Explorer sidebar and choose New C# Class from the dropdown.

Once you’ve named your new file, it should open for you in the editor, and you will see tabs at the top to switch between files.

Note that although the classes are in separate files, as long as the Namespace at the top of each file is the same, and they are in the same folder, they will have no trouble communicating with each other.

}

public void InstantiatingAClass()

{

Once you have created a class file, in order to access the code in that file from another class, such as Program, you must instantiate, or create, an object of that class type. The class itself is a description, but you could have as many objects created with that type as you wish.

To instantiate an object, you use the new statement, and save the result to a variable.

var classObject = new ExtraClassy();

Then, to access features (methods, properties) on that object, use the dot syntax.

classObject.ClassyString = "Set the string";

}

public void Constructors()

{

In the example above, the parentheses following ExtraClassy represent an empty Constructor. Every class has an empty constructor by default. However, sometimes we want to pass in parameters when instantiating an object, just like we pass data to methods.

Notice that a constructor, unlike a method, has no return type, and its name is the same as that of the class.

}

public void Properties()

{

Above, you’ve seen several examples of a new item called a property. Properties are designed as accessible variables that can be set or get (retrieved) from outside the class. This is in contrast to fields, which are used primarily within a class.

A property always requires either a getter or setter, and can have both as well. An auto-property is one with the simplest form of these accessors, { get; set; }. This tells us that the property can be simply written to and read from. Sometimes, more complex logic might be used in either the get or set block, in which case they are encapsulated in curly braces and include a return like a method. These properties are often paired with a private field, which actually stores the data.

}

public void DesignPrincipals()

{

Many amazing books and blog posts have been written about Object-Oriented Design principals, and it is not the purpose of this site to make you an expert in these. However, one simple design principal I have found extremely useful is to separate my classes into two groups: Data Transfer Objects (DTOs) and Business Logic classes. The examples on this page so far have been DTOs. That is, they exist primarily as a repository to store, transfer, and retrieve data, in the form of properties.

A Business Logic class, on the other hand, is one that does something, in the form of methods. In a short program, this might be all handled by the Program class, but it should be separated out into other classes for more complex designs.

}

}

public class Lesson3_ChatBot

{

void HelloAnyone()

{

We are going to create a simple chat bot, using the Console in DotNetFiddle or VSCode and a new command: Console.ReadLine().

Feel free to personalize the opening message and greeting. Can you add a second prompt? Maybe a follow-up question? (Typing anywhere in the code window will also reset the console output).

}

void DictionaryResponses()

{

To create a good list of responses to user input, it’s helpful to use a Dictionary, which is a new .NET Type, similar to the List, but with a matched pair of variables (key and value). Don’t forget to import System.Collections.Generic!

Here are some challenges for you

  1. Add more commands and responses to the dictionary.
  2. Can you make the program smart enough to understand both capitalized and uncapitalized strings? (hint: check for a method on the input variable by typing a period after and seeing what pops up)
  3. Use a for loop to have the program ask for commands more than once.
  4. Can you figure out a way to prevent the error message if someone types in an unknown command?

Don’t peek ahead until you’ve at least tried to solve #3-4!

}

void WhileLoops()

{

If you succeeded at creating a for loop for challenge #3 above, it probably looked something like this:

This saves us from writing out the code five times, but what if we want to keep going as long as the person is interested? That’s what a while loop is for. While loops continue as long as a certain variable or formula is true.

We’ll also take this time to introduce a new kind of variable, the field. The only difference between a regular variable and a field is that fields are created and maintained at the class level, so they are accessible from any method in that class.

}

void SafetyChecks()

{

No one likes seeing error codes pop up when running a program! To avoid the error that occurs when someone types in random commands, we need to understand why it is happening. In this instance, we have sent an input as a key to our Dictionary. The dictionary looks, but finds that key doesn’t exist. It doesn’t know what we want to do, so it throws an exception. Notice that even with the while loop code, the program terminates at the exception.

There are several ways to handle this problem. First, we can check to see if the key exists ahead of time. Luckily, the Dictionary class has a method for that purpose, called ContainsKey, that returns a boolean value to tell you whether or not to proceed.

The other approach is to use a Try/Catch block. The advantage of this approach is that we don’t need to check ahead, but we can still continue running if an exception is thrown. You can choose whether to print the exception, log it, ignore it, or have it trigger some other code. If there is no exception, the catch block is skipped.

}

void SaveYourWorkAndShare()

{

By now, hopefully you have lots of ideas of what your chat bot could do. Make sure to save your work! You can go to DotNetFiddle.Net and create a free account to save your fiddles.

Of course, if you are using VS Code, the files are already saved on your machine. If you want to share your local code, you should learn about using Git and GitHub with VSCode. Github also allows you to accept pull requests, or code contributions from other programmers.

Want to share your ideas with us? From DotNetFiddle or GitHub, you can simply copy the address of your code and paste it in a comment on this page! Let us know what your chatbot can do.

}

}