Skip to content
  • iImagine
  • Register
  • Log In

Web Development School

Learning made easy.

  • Books
    • Beginning Web Development with ASP.Net Core & Client-Side Technologies
      • TOC
      • Part 1
        • Chapter 1: Static HTML – Designing the landing page
      • Part 2
        • Chapter 2: ASP.Net Core – Let’s talk Dynamic
        • Chapter 3: Introduction to ASP.Net Core MVC
          [ASP.Net Core v9]
      • Part 4
        • Chapter 7: Using Server Side & Client Side technologies together
          [ASP.Net Core v7 & Angular 15]
  • Environment Setup
    • Installing Angular
    • Installing Visual Studio 2022
    • Installing SQL Server 2022 Express
    • Installing Postman
    • Installing Git for Windows
  • Blog
  • iImagine WebSolutions
  • Events
  • Learning Videos
  • Toggle search form

Create the Details page

Most of the time a complete list of details is not summarized on an index, list, or search results page like our sortable, pageable table of Vehicles on our Home Index page.

A separate Details page is commonly devoted to showing all of the information about an object or entity like a Vehicle.

So in this module we are going to create a Details page to show the complete list of details for a vehicle.

Table Of Contents
  1. Create the Vehicles controller
    • Inject the repository into the constructor
    • Create the Details action method
      • Unit Test the Details action
  2. Create the View
  3. Create Navigation from the main page to the Details page
  4. What's Next

Create the Vehicles controller

Up until now we have only had one controller, the Home controller, whose Index method handles the request to display the landing page for the Fred’s Cars dealership which shows a list of results for Vehicles.

We are going to separate out the rest of the Vehicles functionality into a second controller called of course, VehiclesController.

When we created the Home controller we manually created a class named HomeController and had to write the code to inherit from the base Controller class ourselves. Let’s delve a little into some automated tools called scaffolding tools. To create the Vehicles controller right click on the controllers folder in the FredsCars project and select Add -> Controller.

In the Add New Scaffolded Item dialogue, select the selection for MVC Controller - Empty and click Add.

In the Add New Item dialogue, name the controller VehiclesController.cs and click Add.

Visual Studio then creates a C# class file with a class named VehiclesController that inherits from the base controller class with the following code.

using Microsoft.AspNetCore.Mvc;

namespace FredsCars.Controllers
{
    public class VehiclesController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

We don’t need the generated Index method since we already handle this in the Home controller so we can remove it. (Although there is nothing preventing us from having a method named Index in multiple controllers if that fits our design needs).

Modify the VehiclesController.cs file with the code below to remove the Index method.

FredsCars\Controllers\VehiclesController.cs

using Microsoft.AspNetCore.Mvc;

namespace FredsCars.Controllers
{
    public class VehiclesController : Controller
    {
        
    }
}

Inject the repository into the constructor

We don’t need to extend or modify the repository yet at this point. We can use the same existing Vehicles IQueryable property to return a single Vehicle for the details page as we used to return multiple Vehicles on the Home Controller’s Index page, or list page. But we do need to bring in the repository through constructor dependency injection just like we did with the Home Controller. Modify the Vehicles controller with the code below.

using FredsCars.Models.Repositories;
using Microsoft.AspNetCore.Mvc;

namespace FredsCars.Controllers
{
    public class VehiclesController : Controller
    {
        private IVehicleRepository _repo;

        public VehiclesController(IVehicleRepository repo)
        {
            _repo = repo;
        }
    }
}

Now we have the Vehicle repository ready to go to use in the Details action method which we will create next.

Create the Details action method

The next step is to create an asynchronous action method named Details. Modify the Vehicles controller with the code below.

FredsCars\Controllers\VehiclesController.cs

using FredsCars.Models;
using FredsCars.Models.Repositories;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace FredsCars.Controllers
{
    public class VehiclesController : Controller
    {
        private IVehicleRepository _repo;

        public VehiclesController(IVehicleRepository repo)
        {
            _repo = repo;
        }

        // GET: Students/Details/5
        public async Task<IActionResult> Details(int id)
        {
            Vehicle? vehicle = await _repo.Vehicles
                .AsNoTracking()
                .Include(v => v.VehicleType)
                .FirstOrDefaultAsync(v => v.Id == id);
  
            if (vehicle == null)
            {
               ViewBag.NoVehicleMessage =
               "Sorry, no vehicle with that id could be found.";
            }

            return View(vehicle);
        }
    }}

In the controller code above, we start off by using the Vehicle repository to fetch a single Vehicle from the database using the id passed to the action method which will come from a URL route data segment. We chain the AsNoTracking method on to the query to improve performance since we will not be altering any data. We then tack on the LINQ Include method to include the VehicleType (Car, Truck, or Jeep) for the vehicle and finally fetch it using the FirstOrDefaultAsyn method with a lambda expression.

Vehicle? vehicle = await _repo.Vehicles
    .AsNoTracking()
    .Include(v => v.VehicleType)
    .FirstOrDefaultAsync(v => v.Id == id);

Note we have marked the action method as asynchronous and used the await keyword along with FirstOrDefaultAsync rather then the synchronous FirstOrDefault method to execute the query.

Next we check if the vehicle variable is null. If so then the query was not able to find a vehicle with the id passed into the action method. In this case we set up a message to alert the user that the vehicle could not be found in the ViewBag object under a property named NoVehicleMessage.

if (vehicle == null)
{
    ViewBag.NoVehicleMessage =
    "Sorry, no vehicle with that id could be found.";
}

We then use the return keyword to return a ViewResult object using the View method and pass the vehicle to it in turn passing the Vehicle object down to the view.

Note here since the method is asynchronous it actually returns a Task of ViewResult or Task<ViewResult>.

This is comparable to a promise in JavaScript that the work will be completed and the current thread can be released to be used for other work. When the work is complete ASP.Net Core will ask for a thread in order to execute a callback method for the task. The async method we mark the method with sets up the callback method under the hood to call once the IO work has completed. IO work refers to tasks the application would have to wait for such as database queries and updates that could block the current thread.

Unit Test the Details action

In past modules we would complete all of the work in the controller, any components, and the view, and then go back and unit test the controller and any components. But, we really should be testing as we go. Testing a controller before moving on to the view can help us flush out any requirements like the fact if we can not find a vehicle by the id in the request URL, it would be nice to provide the user with a nice message rather than a blank 404 page as we did using the ViewBag object.

So, let’s create a new Test class called VehiclesControllerTests.cs in the FredsCars.Tests project in the controllers folder.

First we will create a test method called Can_Access_Vehicle_ById to make sure the Details action method can indeed fetch and return a vehicle by the id passed to it by the request URL.

FredsCars.Tests\Controllers\VehiclesControllerTests.cs

using FredsCars.Controllers;
using FredsCars.Models;
using FredsCars.Models.Repositories;
using MockQueryable;
using Moq;

namespace FredsCars.Tests.Controllers
{
    public class VehiclesControllerTests
    {
        [Fact]
        public async Task Can_Access_Vehicle_ById()
        {
            // Arrange
            // 1 - create a List<T> with test items
            var vehicles = new List<Vehicle>
            {
                new Vehicle
                {
                    Id = 1,
                    Make = "Make1",
                    Model = "Model1",
                    VehicleType = new VehicleType
                    {
                        Id = 1,
                        Name = "Car"
                    }
                },
                new Vehicle
                {
                    Id = 2,
                    Make = "Make2",
                    Model = "Model2",
                    VehicleType = new VehicleType
                    {
                        Id = 1,
                        Name = "Car"
                    }
                },
                new Vehicle
                {
                    Id = 3,
                    Make = "Make3",
                    Model = "Model3",
                    VehicleType = new VehicleType
                    {
                        Id = 2,
                        Name = "Truck"
                    }
                },
                new Vehicle
                {
                    Id = 4,
                    Make = "Make4",
                    Model = "Model4",
                    VehicleType = new VehicleType
                    {
                        Id = 3,
                        Name = "Jeep"
                    }
                }
            };

            // 2 - build mock using MockQueryable.Moq extension 
            var mockVehiclesIQueryable = vehicles.BuildMock();

            // 3 - build mock IVehicleRepository
            Mock<IVehicleRepository> mockVehicleRepo =
                new Mock<IVehicleRepository>();
            mockVehicleRepo.Setup(mvr => mvr.Vehicles).Returns(mockVehiclesIQueryable);

            VehiclesController controller = new VehiclesController(mockVehicleRepo.Object);

            // Act
            Vehicle? vehicleResult =
                (await controller.Details(3)).ViewData.Model
                    as Vehicle;
            var viewResult =
                (await controller.Details(3));


            // Assert
            Assert.Equal(3, vehicleResult?.Id);
            Assert.Null(viewResult.ViewData["NoVehicleMessage"]);
        }
    }
}

In the unit test above after our usual build up of test data and repo in the Arrange section, we instantiate a new Vehicles controller passing to its constructor the mocked Vehicle repo containing the Vehicle test data.

VehiclesController controller = new VehiclesController(mockVehicleRepo.Object);

In the Act and Assert sections we are checking two things.

  1. If the Details method receives an id that matches that of a Vehicle in the repo, it can return that Vehicle.
  2. Also, if the Details method receives an id that matches that of a Vehicle in the repo, there will be no property named NoVehicleMessage passed back in the ViewBag object of the ViewResult.

To accomplish this we make a first call to the controller in the Act section, pass 3 for the id, and return the Model converted to a Vehicle. We store the returned Vehicle in a variable named vehicleResult.

We then make a second call to the controller, pass 3 for the id, and this time store the whole ViewResult in a variable named viewResult.

Making two calls in this way enables us to more easily make two separate assertions on both the Vehicle returned as the Model and the whole ViewResult itself.

// Act
Vehicle? vehicleResult =
    (await controller.Details(3)).ViewData.Model
        as Vehicle;
var viewResult =
    (await controller.Details(3));

In the Assert section we verify that the returned Vehicle’s Id property is equal to the id we passed into the controller call in the Act section and that there is no ViewBag property named NoVehicleMessage in the ViewResult.

// Assert
Assert.Equal(3, vehicleResult?.Id);
Assert.Null(viewResult.ViewData["NoVehicleMessage"]);

For the second unit test, we need to ensure that if the id passed into the Details action method from the URL request does not match that of any Vehicle in the repository, we can send a message alerting the user.

Add a second unit test named Can_Send_NoVehicleFoundMessage to the VehiclesControllerTests class.

FredsCars.Tests\Controllers\VehiclesControllerTests.cs

... existing code ...
public class VehiclesControllerTests
{
    [Fact]
    public async Task Can_Access_Vehicle_ById()
    {
        ... existing code ...
    }

    [Fact]
    public async Task Can_Send_NoVehicleFoundMessage()
    {
        // Arrange
        // 1 - create a List<T> with test items
        var vehicles = new List<Vehicle>
        {
            new Vehicle
            {
                Id = 1,
                Make = "Make1",
                Model = "Model1",
                VehicleType = new VehicleType
                {
                    Id = 1,
                    Name = "Car"
                }
            },
            new Vehicle
            {
                Id = 2,
                Make = "Make2",
                Model = "Model2",
                VehicleType = new VehicleType
                {
                    Id = 1,
                    Name = "Car"
                }
            },
            new Vehicle
            {
                Id = 3,
                Make = "Make3",
                Model = "Model3",
                VehicleType = new VehicleType
                {
                    Id = 2,
                    Name = "Truck"
                }
            },
            new Vehicle
            {
                Id = 4,
                Make = "Make4",
                Model = "Model4",
                VehicleType = new VehicleType
                {
                    Id = 3,
                    Name = "Jeep"
                }
            }
        };

        // 2 - build mock using MockQueryable.Moq extension 
        var mockVehiclesIQueryable = vehicles.BuildMock();

        // 3 - build mock IVehicleRepository
        Mock<IVehicleRepository> mockVehicleRepo =
            new Mock<IVehicleRepository>();
        mockVehicleRepo.Setup(mvr => mvr.Vehicles).Returns(mockVehiclesIQueryable);

        VehiclesController controller = new VehiclesController(mockVehicleRepo.Object);

        // Act
        Vehicle? vehicleResult =
            (await controller.Details(5)).ViewData.Model
                as Vehicle;
        var viewResult =
            (await controller.Details(5));


        // Assert
        Assert.Null(vehicleResult);
        Assert.Equal("Sorry, no vehicle with that id could be found.",
            viewResult.ViewData["NoVehicleMessage"]);
    }
}
... existing code ...

The unit test in the code above is nearly identical to the first test in this module except that we have reversed the conditions.

We make the two calls to the Details action method in the Act section passing 5 as the id instead of 3. 5 does not match any Vehicle in the repo so we verify in the assert section that the Model returned is null rather then a vehicle and that the ViewBag object’s NoVehicleMessage property is equal to the string, “Sorry, no vehicle with that id could be found.”

Create the View

Let’s explore another feature of the Visual Studio scaffolding tools. In order to create a View for the Details action method in the Vehicles controller, right click on it in the code and select Add View.

In the Add New Scaffolded Item dialogue, select Razor View - Empty and click the Add button.

Name the Razor view Details.cshtml.

This will create a new Vehicles subfolder in the Views folder to match the name of the controller the Action method is in and in the new Vehicles subfolder create a new Razor view called Details.cshtml.

Modify Details.cshtml with the code below.

FredsCars\Views\Vehicles\Details.cshtml

@model Vehicle

@{
    ViewData["Title"] = "Details";
}

@if (Model == null)
{
    <div class="container text-danger text-center fw-bold mt-5">
        @ViewBag.NoVehicleMessage
    </div>
}

@if (Model != null)
{
<div class="container-fluid py-4">
    <h3 class="text-center bg-primary-subtle py-2"
        style="border: 1px solid black;">
        @Model.Year @Model.Make @Model.Model
    </h3>

    <center>
        <img src="@Model.ImagePath" />
    </center>

    <div class="container">
        <h2 class="mt-4">Details</h2>
        <table class="table table-primary table-striped">
            <tbody>
               <tr>
                   <th>
                       @Html.DisplayNameFor(model => Model.Status)
                   </th>
                   <td>
                       @Html.DisplayFor(model => model.Status)
                   </td>
                    <th>
                        @Html.DisplayNameFor(model => Model.Year)
                    </th>
                    <td>
                        @Html.DisplayFor(model => model.Year)
                    </td>
               </tr>
                <tr>
                    <th>
                        @Html.DisplayNameFor(model => Model.Make)
                    </th>
                    <td>
                        @Html.DisplayFor(model => model.Make)
                    </td>
                    <th>
                        @Html.DisplayNameFor(model => Model.Model)
                    </th>
                    <td>
                        @Html.DisplayFor(model => model.Model)
                    </td>
                </tr>
                <tr>
                    <th>
                        @Html.DisplayNameFor(model => Model.Color)
                    </th>
                    <td>
                        @Html.DisplayFor(model => model.Color)
                    </td>
                    <th>
                        @Html.DisplayNameFor(model => Model.Price)
                    </th>
                    <td>
                        @Html.DisplayFor(model => model.Price)
                    </td>
                </tr>
                <tr>
                    <th>
                        @Html.DisplayNameFor(model => Model.VIN)
                    </th>
                    <td>
                        @Html.DisplayFor(model => model.VIN)
                    </td>
                    <th>
                        @Html.DisplayNameFor(model => Model.VehicleType)
                    </th>
                    <td>
                        @Html.DisplayFor(model => model.VehicleType.Name)
                    </td>
                </tr>
            </tbody>
        </table>

        <div>
            <a asp-action="Edit" asp-route-id="@Model?.Id">Edit</a> |
            <a asp-controller="Home"
               asp-action="Index">Back to Vehicles</a>
        </div>
    </div>
</div>
}

Restart the application and navigate to https://localhost:40443/Vehicles/Details/1.

The results should look similar to the screenshot below.

Now navigate to a URL with an id that has no match in our test data like: https://localhost:40443/Vehicles/Details/14
The results should look similar to the following.

Let’s inspect the code in our new View, Details.cshtml.

At the top of the file we declare that the model we expect to be passed down from the controller action is of Type Vehicle and set the Title property of the ViewData dictionary to be used by the layout to set the text in the browser tab to “Fred’s Cars – Details”.

@model Vehicle

@{
    ViewData["Title"] = "Details";
}

Remember, the layout takes what we set ViewData[“Title”] to and concatenates it with “Fred’s Cars – “.

<head>
    <meta name="viewport" content="width=device-ixwidth" />
    <title>Fred's Cars - @ViewBag.Title</title>
    <link href="~/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
    <link href="~/css/site.css" rel="stylesheet" />
</head>

Next, we do our null check to see if the Model, of type Vehicle, is null. If so, we lay out the message we set for the NoVehicleMessage property of the ViewBag object in the controller for this condition.

@if (Model == null)
{
    <div class="container text-danger text-center fw-bold mt-5">
        @ViewBag.NoVehicleMessage
    </div>
}

We also added Bootstrap classes to make the message red, centered, bold and have a top margin of 5 pixels from the title bar.

If the Model is not null, we lay out the HTML mixed with Razor for a Details page. First we set up a div element with Bootstrap classes of container-fluid to keep it 100% of the screen but also py-4 to give it gutters of 4 pixels at its left and right. Within this parent div we create an inner title bar of sorts with the Vehicle’s Year, Make, and Model.

@if (Model != null)
{
<div class="container-fluid py-4">
    <h3 class="text-center bg-primary-subtle py-2"
        style="border: 1px solid black;">
        @Model.Year @Model.Make @Model.Model
    </h3>

   ... rest of code ...

</div>
}

Next, we add in the image for the Vehicle using the image tag and the Model’s ImagePath property.

@if (Model != null)
{
<div class="container-fluid py-4">
    
    ... rest of code ...
    
    <center>
	<img src="@Model.ImagePath" />
    </center>

   ... rest of code ...

</div>
}

After the image, we set up an inner child Bootstrap container div of the main parent container-fluid div to contain the details of the Vehicle. A container div has a max width rather then take up a 100% of the screen and the max width changes at different break points. It also centers the content and provides padding on the left and right.

Within the child div element we create a heading element (<h2>) to render a “Details” title for the html table containing the details of the vehicle.

<div class="container">
    <h2 class="mt-4">Details</h2>
    ... html details table ...
    
</div>

The table element gets Bootstrap classes of table, table-primary, and table-striped classes to give the table rows alternating shades of the primary blue scheme for table rows.

The table also gets tr elements to create table rows four columns wide so that it can fit two Vehicle properties per row using a table row header column containing a Model property’s display name and a table row data column containing the Model property’s value.

We use the HTML helper’s DisplayNameFor method to display a Model property display name and the DisplayFor method to display the property’s value.

After the table we create two links using anchor tag helpers.

The first tag helper has the asp-action html attribute set to “Edit”. Since no asp-controller attribute is present the link will route back to the same controller the Details page came from, Vehicles, and look for an Edit action method which we will create in an upcoming module. The asp-route-id attribute (a route-data attribute) is assigned the id of the model.

<a asp-action="Edit" asp-route-id="@Model?.Id">Edit</a>

The html created for the anchor element looks like this.

<a href="/Vehicles/Edit/1">Edit</a>

The second anchor tag helper simply routes the user back to the Home controller’s Index method, our list page.

<a asp-controller="Home"
   asp-action="Index">Back to Vehicles</a>

And the html it renders looks like this.

<a href="/">Back to Vehicles</a>

Create Navigation from the main page to the Details page

For the last step of this module we need to give the user a way to navigate to the Details page for a given Vehicle.

Modify the _VehicleTableRowResult.cshtml partial view with the following code below.

@model Vehicle

<tr>
    <td>
        <a asp-controller="Vehicles" 
           asp-action="Details"
           asp-route-id="@Model.Id">
            <img src="@Model.ImagePath"
                 class="result-image" />Details</a>
    </td>
    <td>
        @Html.DisplayFor(modelItem => Model.Status)
    </td>
    <td>
        @Html.DisplayFor(modelItem => Model.Year)
    </td>
    <td>
        @Html.DisplayFor(modelItem => Model.Make)
    </td>
    <td>
        @Html.DisplayFor(modelItem => Model.Model)
    </td>
    <td class="d-none d-lg-table-cell">
        @Html.DisplayFor(modelItem => Model.Color)
    </td>
    <td class="d-none d-md-table-cell">
        @Html.DisplayFor(modelItem => Model.Price)
    </td>
    <td class="d-none d-md-table-cell">
        @Html.DisplayFor(modelItem => Model.VehicleType.Name)
    </td>
</tr>

In the code above we simply embedded the already existing thumbnail image of each vehicle in an anchor element using the built in anchor tag helper to set the controller to Vehicles and action to Details with a route-data attribute of each Vehicle’s Id. We also added the text “Details” next to the image so that the user can click on either the thumbnail image or the text link to navigate to the Details page for any given Vehicle.

What’s Next

In this module we created a Details page template so that the user can view the complete information for any given Vehicle.

In the next several modules we are going to create page templates to Create, Edit (or Update), and Delete a vehicle.

< Prev
Next >

Leave a ReplyCancel reply

Chapter 1: Static HTML – Designing the landing page.

  • Static HTML – Designing the landing page.
  • Let’s get started!
  • Mock your site with HTML
  • Make CSS easy with Bootstrap
  • Mock your content
  • Introducing JavaScript
  • JavaScript Code Improvements
  • Results Data
  • Images and the HTML Image Element.
  • Revisiting Reusability for CSS and JavaScript
  • Reuse for HTML: PART 1
  • Reuse for HTML: PART 2
  • Details Page – Using a Bootstrap Component
  • Creating Links
  • Chapter One Conclusion

Chapter 2: ASP.Net Core – Let’s talk Dynamic

  • Introduction to ASP.Net Core
  • What is .Net?
  • What is ASP.Net
  • Introduction to Entity Framework Core

Chapter 3: ASP.Net MVC Core – Models, Views, and Controllers [ASP.Net Core v9]

  • Introduction to ASP.Net Core MVC
  • Create the project: ASP.Net Core MVC
  • Explore the ASP.Net Core Empty Web Project Template
  • Configure the Application for MVC
  • Create a Controller: Home Controller
  • Create a View: Index View for the Home Controller
  • Install Bootstrap using Libman
  • Create the Layout template
  • Create the Model
  • Install EF Core & Create the Database
  • Seed the Database: Loading test data
  • DI (Dependency Injection): Display a List of Vehicles
  • Repository Pattern: The Vehicles Repo
  • Unit Test 1: Home Controller Can Use Vehicle Repository
  • Unit Test 2: Vehicle Repository Can Return List
  • Add the ImagePath Migration and Thumbnail images to results
  • Pagination: Create a Custom Tag Helper
  • Sorting
  • Category Filter
  • Partial View: Break out the vehicle results
  • View Component: Create dynamic category buttons
  • Create the Details page
  • Create the Create Page
  • Create the Update Page
  • Create the Delete Page
  • Validation
  • Logging & Configuration
  • Storing Secrets
  • Error Handling
  • Security & Administration

Chapter 7: Using Server Side & Client Side technologies together. [ASP.Net Core v7 & Angular v15]

  • Intro to Full Stack Development
  • Fred’s Cars – Full Stack Development
  • Prepare the environment
  • Create the Visual Studio Solution
  • Add the ASP.Net Core Web API project
  • Add the Angular Project
  • Wire it up!
  • WeatherForecast: Understanding the basics
  • Vehicles API Controller: Mock Data
  • Vehicles Angular Component: Consuming Data
  • Routing and Navigation
  • Using a Component Library: Angular Material
  • Our first Angular Material Component: MatToolbar
  • Configuring for Saas: CSS with superpowers
  • Create the Header & Footer components
  • Displaying Results with MatTable
  • Loading: Using a Progress Spinner
  • MatTable: Client-Side Paging and Sorting
  • MatSidenav: Create a Search Sidebar
  • MatCheckbox: Category Search UI
  • Adding an image to the welcome page
  • Create the database with Entity Framework Core migrations
  • MatPaginator & PageEvent: Custom Server-Side Paging
  • Unit Testing: Custom Server-Side Paging
  • Repository Pattern: VehicleRepository
  • Unit Test: Paging in the Vehicles controller
  • Server-Side Sorting
  • Unit Tests: Sorting
  • Filter (Quick Search)
  • Unit Tests: Filter feature
  • Advanced Search: Categories
  • Unit Tests: Search by category
  • Progress Spinner: Final Fix

TOC

  • What were WebForms?
  • Enter MVC
    • Understanding MVC
    • Advantages of MVC
  • ASP.Net Core MVC – A total rewrite
  • ASP.Net Core 2 MVC – Here come Razor Pages
    • Understanding Razor Pages
  • ASP.Net Core 3 – Dropping the MVC reference
    • Understanding Blazor
  • Dropping the MVC reference
  • Hello .Net 5!
  • What’s Next? – Here comes .Net 6.

Recent Posts

  • Angular Commands Cheat Sheet
  • Installing Git for Windows
  • Installing Postman
  • Installing SQL Server 2022 Express
  • Installing Visual Studio 2022

Recent Comments

No comments to show.

Archives

  • November 2023
  • October 2023
  • June 2023
  • October 2021

Categories

  • Angular
  • ASP.Net
  • Environment Setup
  • See All
  • SQL Server
  • Visual Studio
  • Web API & Rest Services

WordPress Theme Editor

Copyright © 2025 Web Development School.

Powered by PressBook Blog WordPress theme