Blazor Walkthrough: Act I - rochellew/csci_1260_spring2025 GitHub Wiki

Digital Tome of Magical Flora & Fauna

🧙 "Greetings, intrepid developer! You have been chosen for a task of the utmost importance. A nameless traveling explorer has documented some of their incredible discoveries in their field guide; creatures and plants possessed of great magical abilities.

Through these hallowed tutorials, I will help you to create a digital application using the fabled Microsoft Blazor framework to catalogue these organisms. Consult these guides as your knowledge grows over the next few weeks, as new tasks will be laid before you.

Best of luck!"

NPC art by William H. Rochelle

Task 1 - Setting Up the Solution

For your first task, we will be performing a simple setup of a blank Blazor application. The steps below will describe what you should do, as well as explain what the various components of a .NET project are.

Before you begin, take some time to familiarize yourself with the information listed below.

  • A .sln file (the solution file) is used by Visual Studio. Its purpose is to hold several projects together, not unlike a 3-ring binder can hold several writing projects or notes.
    • You open the .sln file when you want to work on the whole application in Visual Studio.
    • In this walkthrough, your solution will include:
      • The Blazor project
      • A class library
  • A .csproj file (the C# project file) is essentially a blueprint for a specific project inside the solution. Metadata about the project(s) are located in this file.
    • Visual Studio can use the .csproj file to build the project.
      • What files to include
      • Which NuGet (external) packages to use
      • Which .NET version to use
    • Each project in a given solution will have its own .csproj file. For example, in this walkthrough, your solution will have two projects:
      • The Blazor project
      • A class library

Step 1: Create a New Solution and Blazor Project

  1. Open Visual Studio and navigate to the screen to create a new project.
  2. When selecting the project type, choose Blazor Web App, and click 'Next'.

🧙 Wizard Wisdom: A Blazor Web App is a new project type as of .NET 8 that combines the best of Blazor Server and Blazor WebAssembly into a single application type.

  1. On the next screen, we are going to name both the project and the solution different things for sake of clarity. Name your project TomeBlazorProject and name your solution TomeSolution.
    • Choose a good storage location on your computer for your work in the Location field.
    • Make sure that the checkbox labeled 'Place solution and project in the same directory' is NOT checked.
  2. The next screen gives us some additional control over how this Blazor project will be created. We can choose the version of .NET, an authentication type, etc. Make sure you're using the latest version of .NET you have installed (likely .NET 9.0). Do not change any other field except for ensuring the checkbox labeled 'Include sample pages' is NOT checked.

Step 2: Create a Class Library Project

Assuming you have followed the instructions so far, you should now see a newly-created project and solution in the Visual Studio workspace. The Solution Explorer, likely located on the right side of your screen, shows you all of the projects inside of whatever solution you have opened.

🧙 Wizard Wisdom: Make sure that you're opening the .sln file when you're working on these projects (double-click it in File Explorer or open via Visual Studio's interface) as you will not be able to take advantage of the tools Visual Studio offers when working with projects if you fail to do so.

🧙 Wizard Wisdom: If you ever lose the Solution Explorer pane in Visual Studio, do not fret! Click View in the ribbon at the top, and select Solution Explorer to conjure it back! If you're a fan of hotkeys, you can also press Ctrl+Alt+L to do the same thing.

We now want to create a second project as part of the solution. This second project will be a class library that will contain all of our model classes used in the Blazor application.

🧙 Wizard Wisdom: It is always a good idea to separate your code in ways that make sense for the given scenario; here, we are going to use some object-oriented programming to simulate a virtual book of creatures and plants. As such, it makes sense to put all of the classes and interfaces (known as models) in a separate project to keep our work organized and clean.

  1. Right-click on the solution in the Solution Explorer (should be called TomeSolution) and select Add -> New Project.... This will take you the project creation screen.
  2. Choose Class Library for the project type and click 'Next'.
  3. On the next screen, name this project TomeLibraryProject and click 'Next'.
  4. On the next screen, make sure the latest .NET version is selected and click 'Create'.

Your solution explorer should now show two projects as part of the TomeSolution solution: TomeBlazorProject and TomeLibraryProject.

🧙 Wizard Wisdom: Just because we have created a new class library does NOT mean that our Blazor project can access it. We need to add something called a project reference to our Blazor project in order to make that happen. And, as luck would have it, I am going to help you do that next!

Step 3: Adding a Project Reference

By adding a reference to our newly-created class library project, we can allow our Blazor project to access the classes within it. This is necessary if we want to use our models in the Blazor application, which we absolutely do.

  1. Right-click on the TomeBlazorProject project in the Solution Explorer, and select Add -> Project Reference... to open the Reference Manager.
  2. In the reference manager, select 'Solution' under the 'Projects' group on the lefthand side of the window (this should be selected by default). You should see TomeLibraryProject here. Check the box next to its name, and click 'OK'.

You now have a project reference to your class library in the Blazor project! To verify that this worked, in the Blazor Project, expand the 'Dependencies' dropdown, then 'Projects', and you should see TomeLibraryProject listed.

🧙 Wizard Wisdom: While we don't have any code written in either project yet, getting the references set up will help us out in the long run. The next steps of the walkthrough will detail setting up the class library and displaying some basic information via the Blazor app.

Task 2: Adding Models to the Library & Basic Blazor Output

The bones of the project have been laid out, and now it's time to add some functionality.

Step 1: Adding Models to the Class Library

Make sure that for this section, you're paying attention to which project you're adding files to. Because they're both open in the Solution Explorer, it's important to keep track of what you're working on.

🧙 Wizard Wisdom: It can be helpful to collapse the dropdown of the project you're NOT working on in the Solution Explorer to keep it out of mind for the moment.

  1. Your class library may have a .cs file inside of it (likely called Class1.cs). Delete this file if it exists.
  2. For each of the classes in the following UML diagram, right-click on the class library project, and select Add -> Class and make sure that 'Class' or 'Interface' is selected depending on what you're adding.
    • Note that the Rarity class is labeled as an enumeration or enum. Add a new class called Rarity. The next step will discuss implementing an enum in its own class file.
  3. After adding each of the classes and interfaces, add the properties shown in the UML. Make sure that you're paying attention to their accessibility (+ means public) and that the relationships between classes are being implemented properly.
    • Change the internal keyword in all of the added classes/interfaces to the public keyword.
    • Change the class keyword in Rarity.cs to the enum keyword. See below for the contents of Rarity.cs.
namespace TomeLibraryProject
{
    public enum Rarity
    {
        Common, Uncommon, Rare, Legendary, Mythical
    }
}

🧙 Wizard Wisdom: Make sure you are creating the attributes of the classes as properties with a public modifier and a { get; set; } after each one. You can type prop and hit the tab key in Visual Studio if you'd like a keyboard shortcut.

classDiagram
    class Rarity {
        <<enumeration>>
        Common
        Uncommon
        Rare
        Legendary
        Mythical
    }

    class IOrganism {
        +string Name
        +string ImageUrl
        +string Description
        +Rarity Rarity
    }

    class ICreature {
        +string Habitat
        +bool IsHostile
    }

    class IPlant {
        +bool IsMedicinal
        +string BloomSeason
        +bool IsPoisonous
    }

    class Creature {
        +string Name
        +string ImageUrl
        +string Description
        +Rarity Rarity
        +string Habitat
        +bool IsHostile
    }

    class Plant {
        +string Name
        +string ImageUrl
        +string Description
        +Rarity Rarity
        +bool IsMedicinal
        +string BloomSeason
        +bool IsPoisonous
    }

    Rarity <|-- IOrganism
    ICreature --|> IOrganism
    IPlant --|> IOrganism

    Creature ..|> ICreature
    Plant ..|> IPlant
Loading

🧙 Wizard Wisdom: Make sure that you're following the naming conventions of the UML diagram (e.g., for the BloomSeason property in the Plant class, that line of code might look like the following: public string BloomSeason { get; set; }). Failure to follow the proper naming convention for these properties will result in some issues for you later in this walkthrough.

Step 2: Displaying Example Data in Blazor

Now that we have a model, let's add a Service to the Blazor project to use these classes to show some data on a webpage.

  1. Ensure that you are working with the TomeBlazorProject project in the solution explorer.
  2. Add a new class to the Blazor project called OrganismService.
  3. Paste or write the following code into OrganismService.cs.
using TomeLibraryProject;

namespace TomeBlazorProject.Services
{
    public class OrganismService
    {
        public Creature GetSampleCreature() => new Creature
        {
            Name = "Skywhale",
            ImageUrl = "https://t4.ftcdn.net/jpg/08/28/33/25/360_F_828332571_NeEXZmhJ19tQ2CybnLwLPEUTQ7WtRbMr.jpg",
            Description = "A gentle giant that floats above the clouds.",
            Habitat = "Sky Isles",
            IsHostile = false,
            Rarity = Rarity.Legendary
        };

        public Plant GetSamplePlant() => new Plant
        {
            Name = "Moonblossom",
            ImageUrl = "https://www.socalcamelliasociety.org/Camelliae%20Floris%20Bibliotheca/images/Moon%20Blossom.jpg",
            Description = "A glowing flower that only blooms at night.",
            IsMedicinal = true,
            BloomSeason = "Winter",
            IsPoisonous = false,
            Rarity = Rarity.Rare
        };
    }
}

🧙 Wizard Wisdom: While we will be changing the functionality of this service later, it is useful for now to generate a new object of the Plant and Creature type and return it (e.g., the => new Plant code means that GetSamplePlant() will return a new Plant object that is instantiated via the code inside the braces.

  1. Register the service in Program.cs in the Blazor project by pasting the following code after the var builder = WebApplication.CreateBuilder(args); line and before the var app = builder.Build(); line.
builder.Services.AddSingleton<OrganismService>();

🧙 Wizard Wisdom: Registering a service with your app essentially tells Blazor that you want to use that class anywhere in the app. Depending on the lifecycle you choose (in our case a singleton), Blazor will then make it available as needed per that lifecycle.

  1. Display the data with Home.razor by replacing the contents of Home.razor with the following code.
    • Home.razor can be found in /Components/Pages in your Blazor project.
@page "/"
@inject TomeBlazorProject.Services.OrganismService OrganismService

<h1>Magical Field Guide</h1>

<h2>Creature</h2>
<div class="organism-card">
    <h3>@Creature.Name (@Creature.Rarity)</h3>
    <img src="@Creature.ImageUrl" alt="@Creature.Name" />
    <p>@Creature.Description</p>
    <p><strong>Habitat:</strong> @Creature.Habitat</p>
    <p><strong>Hostile:</strong> @(Creature.IsHostile ? "Yes" : "No")</p>
</div>

<h2>Plant</h2>
<div class="organism-card">
    <h3>@Plant.Name (@Plant.Rarity)</h3>
    <img src="@Plant.ImageUrl" alt="@Plant.Name" />
    <p>@Plant.Description</p>
    <p><strong>Bloom Season:</strong> @Plant.BloomSeason</p>
    <p><strong>Medicinal:</strong> @(Plant.IsMedicinal ? "Yes" : "No")</p>
    <p><strong>Poisonous:</strong> @(Plant.IsPoisonous ? "Yes" : "No")</p>
</div>


@code {
    private Creature Creature;
    private Plant Plant;

    protected override void OnInitialized()
    {
        Creature = OrganismService.GetSampleCreature();
        Plant = OrganismService.GetSamplePlant();
    }
}
  1. You should have a file called app.css in the wwwroot directory in your Blazor project. This CSS file is linked by default in /Components/App.razor. Add the following code to app.css.
body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f9f9f9;
    margin: 0;
    padding: 0;
    color: #333;
}

h1, h2, h3 {
    color: #2c3e50;
}

div {
    margin-bottom: 2rem;
}

.organism-card {
    background-color: white;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    padding: 1.5rem;
    max-width: 600px;
    margin: 1rem auto;
    text-align: center;
}

.organism-card img {
    max-width: 100%;
    height: auto;
    border-radius: 8px;
    margin-top: 1rem;
    margin-bottom: 1rem;
}

.organism-card p {
    margin: 0.5rem 0;
}

🧙 Wizard Wisdom: Feel free to change any of this CSS to be to your liking. The organism-card classes are not necessary in your HTML, and are simply included in this walkthrough as a styling baseline/example.

  1. Run the Blazor project and verify that you can see the two objects displayed in the browser. If you can, congratulations -- you're done! If not, make sure that you go back over the instructions.
    • If you run into any issues with the code I provided, the problem is likely found in your implementation of the classes, interfaces, and enum in the class library.

Act I Conclusion

Congratulations! You have completed Act I of this walkthrough. There will be more to come, but this is likely going to be one of the more involved pieces of this app development. If things aren't working properly, make sure that you've followed the instructions carefully.

If there is an issue with these instructions, please let them be known! Stay tuned for more, and thank you for your time.

NPC art by William H. Rochelle

⚠️ **GitHub.com Fallback** ⚠️