Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
ASP.NET Core 5 and React

You're reading from   ASP.NET Core 5 and React Full-stack web development using .NET 5, React 17, and TypeScript 4

Arrow left icon
Product type Paperback
Published in Jan 2021
Publisher Packt
ISBN-13 9781800206168
Length 568 pages
Edition 2nd Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Carl Rippon Carl Rippon
Author Profile Icon Carl Rippon
Carl Rippon
Arrow right icon
View More author details
Toc

Table of Contents (21) Chapters Close

Preface 1. Section 1: Getting Started
2. Chapter 1: Understanding the ASP.NET 5 React Template FREE CHAPTER 3. Chapter 2: Creating Decoupled React and ASP.NET 5 Apps 4. Section 2: Building a Frontend with React and TypeScript
5. Chapter 3: Getting Started with React and TypeScript 6. Chapter 4: Styling React Components with Emotion 7. Chapter 5: Routing with React Router 8. Chapter 6: Working with Forms 9. Chapter 7: Managing State with Redux 10. Section 3: Building an ASP.NET Backend
11. Chapter 8: Interacting with the Database with Dapper 12. Chapter 9: Creating REST API Endpoints 13. Chapter 10: Improving Performance and Scalability 14. Chapter 11: Securing the Backend 15. Chapter 12: Interacting with RESTful APIs 16. Section 4: Moving into Production
17. Chapter 13: Adding Automated Tests 18. Chapter 14: Configuring and Deploying to Azure 19. Chapter 15: Implementing CI and CD with Azure DevOps 20. Other Books You May Enjoy

Understanding the ASP.NET Core backend

In this section, we are going to start by creating an ASP.NET Core and React app using the standard template in Visual Studio. This template is perfect for us to review and understand basic backend components in an ASP.NET Core SPA.

Once we have scaffolded the app using the Visual Studio template, we will inspect the ASP.NET Core code, starting from its entry point. During our inspection, we will learn how the request/response pipeline is configured and how requests to endpoints are handled.

Creating an ASP.NET Core and React templated app

Let's open Visual Studio and carry out the following steps to create our templated app:

  1. In the start-up dialog, choose Create a new project:
    Figure 1.2 – Visual Studio start-up dialog

    Figure 1.2 – Visual Studio start-up dialog

  2. Next, choose ASP.NET Core Web Application in the wizard that opens and click the Next button:
    Figure 1.3 – Creating a new web app in Visual Studio

    Figure 1.3 – Creating a new web app in Visual Studio

  3. Give the project a name of your choice and choose an appropriate location to save the project to. Then, click the Create button to create the project:
    Figure 1.4 – Specifying a project name and location

    Figure 1.4 – Specifying a project name and location

    Another dialog will appear that allows us to specify the version of ASP.NET Core we want to use, as well as the specific type of project we want to create.

  4. Select ASP.NET Core 5.0 as the version and React.js in the dialog. Then, click the Create button, which will create the project: 
    Figure 1.5 – The project template and ASP.NET Core version

    Figure 1.5 – The project template and ASP.NET Core version

    Important Note

    If ASP.NET Core 5.0 isn't listed, make sure that the latest version of Visual Studio is installed. This can be done by choosing the Check for Updates option from the Help menu.

  5. Now that the project has been created, press F5 to run the app. After a minute or so, the app will appear in a browser:
Figure 1.6 – The home page of the app

Figure 1.6 – The home page of the app

We'll find out later in this chapter why the app took so long to run the first time. For now, we've created the ASP.NET Core React SPA. Now, let's inspect the backend code. 

Understanding the backend entry point

An ASP.NET Core app is a console app that creates a web server. The entry point for the app is a method called Main in a class called Program, which can be found in the Program.cs file in the root of the project:

public class Program
{
  public static void Main(string[] args)
  {
    CreateHostBuilder(args).Build().Run();
  }
  public static IHostBuilder CreateHostBuilder(string[] 
   args) =>
    Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      {
          webBuilder.UseStartup<Startup>();
      });
}

This method creates a web host using Host.CreateDefaultBuilder, which configures items such as the following:

  • The location of the root of the web content
  • Where the settings are for items, such as the database connection string
  • The logging level and where the logs are output

We can override the default builder using fluent APIs, which start with Use. For example, to adjust the root of the web content, we can add the highlighted line in the following snippet:

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
      webBuilder.UseContentRoot("some-path");
      webBuilder.UseStartup<Startup>();
    });

The last thing that is specified in the builder is the Startup class, which we'll look at in the following section.

Understanding the Startup class

The Startup class is found in Startup.cs and configures the services that the app uses, as well as the request/response pipeline. In this subsection, we will understand the two main methods within this class.

The ConfigureServices method

Services are configured using a method called ConfigureServices. This method is used to register items such as the following:

  • Our controllers, which will handle requests
  • Our authorization policies
  • Our CORS policies
  • Our own classes, which need to be available in dependency injection

Services are added by calling methods on the services parameter and, generally, start with Add. Notice the call to the AddSpaStaticFiles method in the following code snippet:

public void ConfigureServices(IServiceCollection services)
{0
  services.AddControllersWithViews();
  services.AddSpaStaticFiles(configuration =>
  {
     configuration.RootPath = "ClientApp/build";
  });
}

This is a key part of how the React app is integrated into ASP.NET Core in production since this specifies the location of the React app.

Important Note

It is important to understand that the ASP.NET Core app runs on the server, with the React app running on the client in the browser. The ASP.NET Core app simply serves the files in the ClientApp/Build folder without any interpretation or manipulation.

The ClientApp/Build files are only used in production mode, though. Next, we'll find out how the React app is integrated into ASP.NET Core in development mode.

The Configure method

When a request comes into ASP.NET Core, it goes through what is called the request/response pipeline, where some middleware code is executed. This pipeline is configured using a method called Configure. We will use this method to define exactly which middleware is executed and in what order. Middleware code is invoked by methods that generally start with Use in the app parameter. So, we would typically specify middleware such as authentication early in the Configure method, and in the MVC middleware toward the end. The pipeline that the template created is as follows:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...
    app.UseStaticFiles();
    app.UseSpaStaticFiles();
    app.UseRouting();
    app.UseEndpoints( ... );
    app.UseSpa(spa =>
    {
        spa.Options.SourcePath = "ClientApp";
        if (env.IsDevelopment())
        {
            spa.UseReactDevelopmentServer(npmScript: 
            "start");
        }
    });
}

Notice that a method called UseSpaStaticFiles is called in the pipeline, just before the routing and endpoints are set up. This allows the host to serve the React app, as well as the web API.

Also, notice that a UseSpa method is called after the endpoint middleware. This is the middleware that will handle requests to the React app, which will simply serve the single page in the React app. It is placed after UseEndpoints so that requests to the web API take precedence over requests to the React app.

The UseSpa method has a parameter that is actually a function that executes when the app is run for the first time. This function contains a branch of logic that calls spa.UseReactDevelopmentServer(npmScript: "start") if you're in development mode. This tells ASP.NET Core to use a development server by running npm start. We'll delve into the npm start command later in this chapter. So, in development mode, the React app will be run on a development server rather than having ASP.NET Core serve the files from ClientApp/Build. We'll learn more about this development server later in this chapter.

Next, we will learn how custom middleware can be added to the ASP.NET Core request/response pipeline.

Custom middleware

We can create our own middleware using a class such as the following one. This middleware logs information about every single request that is handled by the ASP.NET Core app:

public class CustomLogger
{
    private readonly RequestDelegate _next;
    public CustomLogger(RequestDelegate next)
    {
        _next = next ?? throw new 
         ArgumentNullException(nameof(next));
    }
    public async Task Invoke(HttpContext httpContext)
    {
        if (httpContext == null) throw new 
        ArgumentNullException(nameof(httpContext));
        // TODO - log the request
        await _next(httpContext);
        // TODO - log the response 
    }
}

This class contains a method called Invoke, which is the code that is executed in the request/response pipeline. The next method to call in the pipeline is passed into the class and held in the _next variable, which we need to invoke at the appropriate point in our Invoke method. The preceding example is a skeleton class for a custom logger. We would log the request details at the start of the Invoke method and log the response details after the _next delegate has been executed, which will be when the rest of the pipeline has been executed.

The following diagram is a visualization of the request/response pipeline and shows how each piece of middleware in the pipeline is invoked:

Figure 1.7 – Visualization of the request/response pipeline

Figure 1.7 – Visualization of the request/response pipeline

We make our middleware available as an extension method on the IApplicationBuilder interface in a new source file:

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseCustomLogger(this 
    IApplicationBuilder app)
    {
        return app.UseMiddleware<CustomLogger>();
    }
}

The UseMiddleware method in IApplicationBuilder is used to register the middleware class. The middleware will now be available in an instance of IApplicationBuilder in a method called UseCustomLogger.

So, the middleware can be added to the pipeline in the Configure method in the Startup class, as follows:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseCustomLogger();
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseSpaStaticFiles();
    app.UseMvc(...);
    app.UseSpa(...);
}

In the previous example, the custom logger is invoked at the start of the pipeline so that the request is logged before it is handled by any other middleware. The response that is logged in our middleware will have been handled by all the other middleware as well.

So, the Startup class allows us to configure how all requests are generally handled. How can we specify exactly what happens when requests are made to a specific resource in a web API? Let's find out.

Understanding controllers

Web API resources are implemented using controllers. Let's have a look at the controller that the template project created by opening WeatherForecastController.cs in the Controllers folder. This contains a class called WeatherForecastController that inherits from ControllerBase with a Route annotation:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
  ...
}

The annotation specifies the web API resource URL that the controller handles. The [controller] object is a placeholder for the controller name, minus the word Controller. This controller will handle requests to weatherforecast.

The Get method in the class is called an action method. Action methods handle specific requests to the resource for a specific HTTP method and subpath. We decorate the method with an attribute to specify the HTTP method and subpath the method handles. In our example, we are handling an HTTP GET request to the root path (weatherforecast) on the resource:

[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
  ...
}

Let's have a closer look at the web API at runtime by carrying out the following steps:

  1. Run the app in Visual Studio by pressing F5.
  2. When the app has opened in our browser, press F12 to open the browser developer tools and select the Network panel.
  3. Select the Fetch data option from the top navigation bar. An HTTP GET request to weatherforecast will be shown:
    Figure 1.8 – A request to the weatherforecast endpoint in the browser developer tools

    Figure 1.8 – A request to the weatherforecast endpoint in the browser developer tools

  4. An HTTP response with a 200 status code is returned with JSON content:
Figure 1.9 – The response body for the weatherforecast endpoint in the browser developer tools

Figure 1.9 – The response body for the weatherforecast endpoint in the browser developer tools

If we look back at the Get action method, we are returning an object of the IEnumerable<WeatherForecast> type. The MVC middleware automatically converts this object into JSON and puts it in the response body with a 200 status code for us.

So, that was a quick look at the backend that the template scaffolded for us. The request/response pipeline is configured in the Startup class and the endpoint handlers are implement using controller classes.

In the next section, we'll walk through the React frontend.

You have been reading a chapter from
ASP.NET Core 5 and React - Second Edition
Published in: Jan 2021
Publisher: Packt
ISBN-13: 9781800206168
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime
Visually different images