Exercise - Register and consume services

Completed

ASP.NET Core apps often have a need to access the same services across multiple components. ASP.NET Core uses a built-in dependency injection container to manage the services that an app uses.

Your team lead tasks you to create a barebones website for your company. The website should display a welcome message on the main page. You decide to create a service to generate the welcome message. You'll then register the service with the service container so that it can be injected into components that need it.

Create an ASP.NET Core app

You need an ASP.NET Core app to play the role of your team's app. Let's create a new ASP.NET Core app using the C# Dev Kit extension in Visual Studio Code.

  1. Launch Visual Studio Code.

  2. Press Ctrl+Shift+P to open the command palette.

  3. Search for and select .NET: New Project....

  4. Search for and select ASP.NET Core Empty.

    A screenshot of the command palette with ASP.NET Core Empty selected.

  5. Select or create a folder for the new project.

  6. Name the new app MyWebApp.

  7. Select Create project to create the project.

  8. When the new project opens, expand the Solution Explorer pane to view the project files.

    A screenshot of the Solution Explorer pane in Visual Studio Code.

Run the app

Test the app to make sure it runs.

  1. In Visual Studio Code, press F5 to build and run the app.

    1. When prompted, select C# as the debugger.
    2. When prompted, select C#: MyWebApp [Default Configuration] as the launch configuration to use.

    This command starts the app and hosts it on a local web server. A browser window opens and displays, "Hello, World!"

  2. Close the browser window and stop the app by pressing Shift+F5 in Visual Studio Code.

Create a service

Now that you have a working app, let's create a service that generates a welcome message for the main page.

  1. Right-click the MyWebApp project in the Explorer pane. Select New Folder. Name the folder Services.

  2. Right-click the Services folder. Select New File. Name the file WelcomeService.cs.

  3. Replace the contents of WelcomeService.cs with the following code:

    namespace MyWebApp.Services;
    
    public class WelcomeService : IWelcomeService
    {
    
        DateTime _serviceCreated;
        Guid _serviceId;
    
        public WelcomeService()
        {
            _serviceCreated = DateTime.Now;
            _serviceId = Guid.NewGuid();                
        }
    
        public string GetWelcomeMessage()
        {
            return $"Welcome to Contoso! The current time is {_serviceCreated}. This service instance has an ID of {_serviceId}";
        }
    }
    

    This code defines a WelcomeService class with a GetWelcomeMessage method that generates a welcome message. The message includes the current time when the service was created, as well as a unique identifier for each instance of the service.

    Note that the _serviceCreated and _serviceId fields are set in the constructor, and they never change for the lifetime of the service instance.

Register the service

Now that you have a service, you need to register it with the service container.

  1. Open the Program.cs file.

  2. Add the following directive to the top of the file:

    using MyWebApp.Services;
    

    This directive resolves the reference to the WelcomeService class.

  3. Immediately after the var builder = WebApplication.CreateBuilder(args); line, add the following code:

    builder.Services.AddSingleton<WelcomeService>();
    

    WebApplication.CreateBuilder creates a new instance of the WebApplicationBuilder class called builder. The preceding code registers the WelcomeService class with the service container with a singleton lifetime.

  4. Change the app.MapGet("/", () => "Hello World!"); line to the following code:

    app.MapGet("/", (WelcomeService welcomeService) => welcomeService.GetWelcomeMessage());
    

    This code maps an HTTP GET request to the root URL (/) to a delegate that returns the welcome message generated by the WelcomeService service.

    Your Program.cs file should look like this:

    using MyWebApp.Services;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddSingleton<WelcomeService>();
    
    var app = builder.Build();
    
    app.MapGet("/", (WelcomeService welcomeService) => welcomeService.GetWelcomeMessage());
    
    app.Run();
    

Test the changes

  1. Save all your changes and run the app as before.
  2. When the browser window opens, note the root URL displays the welcome message generated by the WelcomeService service.
  3. Close the browser window and stop the app by pressing Shift+F5 in Visual Studio Code.

Use an interface

Your team reviews your code, and another developer suggests that you use an interface to register services, as this approach makes the code more flexible and easier to maintain.

  1. Right-click the MyWebApp project in the Explorer pane. Select New Folder. Name the folder Interfaces.

  2. Right-click the Interfaces folder. Select New File. Name the file IWelcomeService.cs.

  3. Replace the contents of IWelcomeService.cs with the following code:

    namespace MyWebApp.Interfaces
    
    public interface IWelcomeService
    {
        string GetWelcomeMessage();
    }
    

    This code defines an IWelcomeService interface with a GetWelcomeMessage method. Any services that implement this interface must provide an implementation for the GetWelcomeMessage method.

  4. Open the Services/WelcomeService.cs file.

  5. Add the following directive to the top of the file:

    using MyWebApp.Interfaces;
    

    This directive resolves the reference to the IWelcomeService interface you add in the next step.

  6. Update the WelcomeService class declaration to implement the IWelcomeService interface:

    public class WelcomeService : IWelcomeService
    

    This is the only change you need to make to the WelcomeService class to implement the IWelcomeService interface. The WelcomeService class already has a GetWelcomeMessage method that matches the method signature in the IWelcomeService interface.

  7. Open the Program.cs file.

  8. Update the builder.Services.AddSingleton<WelcomeService>(); line to the following code:

    builder.Services.AddSingleton<IWelcomeService, WelcomeService>();
    

    This code registers the WelcomeService class with the service container using the IWelcomeService interface.

    Tip

    Think of this as saying, "When a component asks for an IWelcomeService, provide an instance of WelcomeService."

  9. Update the app.MapGet("/", (WelcomeService welcomeService) => welcomeService.GetWelcomeMessage()); line to the following code:

    app.MapGet("/", (IWelcomeService welcomeService) => welcomeService.GetWelcomeMessage());
    

    The anonymous function now expects an IWelcomeService instead of a WelcomeService.

    Your Program.cs file should look like this:

    using MyWebApp.Interfaces;
    using MyWebApp.Services;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddSingleton<IWelcomeService, WelcomeService>();
    
    var app = builder.Build();
    
    app.MapGet("/", (IWelcomeService welcomeService) => welcomeService.GetWelcomeMessage());
    
    app.Run();
    

Test the changes

Let's test the app to make sure it still works as expected.

  1. Save all your changes and run the app as before.
  2. When the browser window opens, note the root URL displays the welcome message generated by the WelcomeService service.
  3. Leave the app running for the next exercise.