Render API responses in ASP.NET Core Blazor Web apps

Learn how to render API responses in ASP.NET Core Blazor Web apps.

Learning objectives

After completing this module, you’ll be able to:

  • Combine HTML and C# to define dynamic page rendering logic
  • Render API responses in Blazor Web apps
  • Create pages that perform HTTP operations

Prerequisites

  • Experience writing C# at an intermediate level
  • Ability to write HTML at an intermediate level
  • Knowledge of RESTful services and HTTP action verbs

iot internet of things training courses malaysia

Document an API by using Swashbuckle

Swashbuckle is a NuGet package that provides a way to automatically generate Swagger documentation for ASP.NET Web API projects. Swagger is a tool that helps developers design, build, document, and consume RESTful APIs. With Swashbuckle, you can easily add Swagger documentation to your Web API project by annotating your code with attributes that describe your API endpoints, parameters, and responses. Swashbuckle then uses this information to generate a Swagger JSON file, which can be used to generate interactive API documentation, client SDKs, and more.

There are three main components to Swashbuckle:

  • a Swagger object model and middleware to expose SwaggerDocument objects as JSON endpoints.
  • a Swagger generator that builds SwaggerDocument objects directly from your routes, controllers, and models. It’s typically combined with the Swagger endpoint middleware to automatically expose Swagger JSON.
  • an embedded version of the Swagger UI tool. It interprets Swagger JSON to build a rich, customizable experience for describing the web API functionality. It includes built-in test harnesses for the public methods.

The following dotnet add command installs the Swashbuckle NuGet package:

.NET CLICopy

dotnet add <name>.csproj package Swashbuckle.AspNetCore -v 6.5.0

Add and configure Swagger middleware

Add the Swagger generator to the services collection in Program.cs.

C#Copy

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

 Note

The call to AddEndpointsApiExplorer shown in the previous example is only required for minimal APIs.

Enable the middleware for serving the generated JSON document and the Swagger UI, also in Program.cs:

C#Copy

app.UseSwagger();
if (app.Environment.IsDevelopment())
{
    app.UseSwaggerUI();
}

The default endpoint for the Swagger UI is http:<hostname>:<port>/swagger.

 Note

SwaggerUI is very useful in your development environment. It can be enabled in production, but you should consider any security requirements for your specific application before doing so.

Customize and extend the Swagger documentation

Swagger provides options for documenting the object model and customizing the UI. The configuration action passed to the AddSwaggerGen method can include additional information through the OpenApiInfo class.

The following code sample shows how to add information to display in the API documentation.

C#Copy

// Add using statement for the OpenApiInfo class
using Microsoft.OpenApi.Models;

builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Version = "v1",
        Title = "Fruit API",
        Description = "API for managing a list of fruit their stock status.",
        TermsOfService = new Uri("https://example.com/terms")
    });
});

The Swagger UI displays the version and the added information:

Screenshot showing additional descriptive information added to an API.

You can group operations in your API with the .WithTags option. You can also add descriptive text describing the operation with the .WithSummary option. The following sample code shows using .WithTags to group the POST operation into both a post group, and a fruit group. It also adds the summary specified in the .WithSummary option to the operation.

C#Copy

app.MapPost("/fruits", async (Fruit fruit, FruitDb db) =>
{
    db.Fruits.Add(fruit);
    await db.SaveChangesAsync();

    return Results.Created($"/{fruit.Id}", fruit);
})
    .Produces<Fruit>(201)
    .WithTags("post", "fruits")
    .WithSummary("Create a new fruit");

The Swagger UI displays the specified grouping and summary description.

Screenshot of the Swagger UI displaying the post operation in two groups with a summary description.

isaca certification training courses malaysia

Explore ASP.NET Core APIs

ASP.NET Core supports two approaches to creating APIs: a controller-based approach and minimal APIs. A controller-based API is a traditional approach to building APIs in which each endpoint is mapped to a specific controller class. The controller handles the request, performs any necessary business logic, and returns a response.

Controller-based API

A controller-based web API consists of one or more controller classes that derive from ControllerBase. Following is an example of a controller:

C#Copy

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

Web API controllers should typically derive from ControllerBase rather from ControllerController derives from ControllerBase and adds support for views, so it’s for handling web pages, not web API requests.

The ControllerBase class provides many properties and methods that are useful for handling HTTP requests. For example, in the following code sample CreatedAtAction returns a 201 status code:

C#Copy

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Minimal API

Minimal APIs are a simplified approach for building fast HTTP APIs with ASP.NET Core. You can build fully functioning REST endpoints with minimal code and configuration. Skip traditional scaffolding by declaring API routes and actions. For example, the following code creates an API at the root of the web app that returns the text, “Hello World!”.

C#Copy

var app = WebApplication.Create(args);

app.MapGet("/", () => "Hello World!");

app.Run();

Most APIs accept parameters as part of the route.

C#Copy

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/users/{userId}/books/{bookId}", 
    (int userId, int bookId) => $"The user id is {userId} and book id is {bookId}");

app.Run();

Minimal APIs support the configuration and customization needed to scale to multiple APIs, handle complex routes, apply authorization rules, and control the content of API responses.

iso iec 20000 certification training courses malaysia

Introduction

An API, or Application Programming Interface, is a set of rules and protocols that allows different software applications to communicate with each other. APIs provide a way for developers to access the functionality of another piece of software, such as a web service, and use that functionality in their own applications. APIs are used for many reasons, including:

  • Simplifying development: By using APIs, developers can access the functionality of other software without having to understand the details of how that software works. This can save time and effort when building new applications.
  • Enabling integration: APIs allow different software applications to work together, even if they weren’t originally designed to do so. This can help businesses integrate their systems and data, improving efficiency and productivity.

Learning objectives

After completing this module, you’ll be able to:

  • Describe the two types of APIs in ASP.NET Core.
  • Create Swagger documentation for an API by using Swashbuckle.
  • Interact with an API by using the Swagger interface.

istqb software testing certification training courses malaysia

Interact with an ASP.NET Core minimal API

Learn how APIs are implemented in ASP.NET Core, and how to use API documentation to learn the APIs requirements.

Learning objectives

After completing this module, you’ll be able to:

  • Describe the two model types of APIs in ASP.NET Core
  • Create Swagger documentation for an API by using Swashbuckle
  • Interact with an API by using the Swagger interface

Prerequisites

  • Knowledge of RESTful services and HTTP action verbs
  • Experience with JSON at a beginner level

itil certification training courses malaysia

Perform HTTP operations in Blazor Web apps

In this unit, you learn how to use the IHttpClientFactory to handle the HTTP client creation and disposal, and to use that client to perform REST operations in an ASP.NET Blazor Web app. The code samples used throughout this unit are based on interacting with an API that enables managing a list of fruit stored in a database. The information in this unit is based on using code-behind files in a Razor app.

The following code represents the data model that is referenced in the code examples:

C#Copy

public class FruitModel
{
    // An id assigned by the database
    public int id { get; set; }
    // The name of the fruit
    public string? name { get; set; }
    // A boolean to indicate if the fruit is in stock
    public bool instock { get; set; }
}

Register IHttpClientFactory in your app

To add IHttpClientFactory to your app, register AddHttpClient in the Program.cs file. The following code example uses the named client type and sets the base address of the API used in REST operations, and is referenced throughout the rest of this unit.

C#Copy

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// Add IHttpClientFactory to the container and set the name of the factory
// to "FruitAPI". The base address for API requests is also set.
builder.Services.AddHttpClient("FruitAPI", httpClient =>
{
    httpClient.BaseAddress = new Uri("http://localhost:5050/");
});

var app = builder.Build();

Identify the operation requirements in the API

Before performing operations with an API, you need to identify what the API is expecting:

  • API endpoint: Identify the endpoint for the operation so you can properly adjust the URI stored in the base address if needed.
  • Data requirements: Identify if the operation is returning/expecting an enumerable or just a single piece of data.

 Note

The code samples throughout the rest of this unit assume each HTTP operation is handled on a separate page in the solution.

Perform a GET operation

GET operation shouldn’t send a body and is used (as the method name indicates) to retrieve data from a resource. To perform an HTTP GET operation, given an HttpClient and a URI, use the HttpClient.GetAsync method. For example, if you wanted to create a table on a Razor Page app’s home page (Home.razor) to display the results of a GET operation you need to add the following to the code-behind (Home.razor.cs):

  • Use dependency injection to add the IHttpClientFactory to the page model.
  • Create an instance of the HttpClient
  • Perform the GEToperation and deserialize the results into your data model.

The following code example shows how to perform a GET operation. Be sure to read the comments in the code.

C#Copy

public partial class Home : ComponentBase
{
    // IHttpClientFactory set using dependency injection 
    [Inject]
    public required IHttpClientFactory HttpClientFactory { get; set; }

    [Inject]
    private NavigationManager? NavigationManager { get; set; }

    /* Add the data model, an array is expected as a response */
    private IEnumerable<FruitModel>? _fruitList;

    // Begin GET operation when the component is initialized
    protected override async Task OnInitializedAsync()
    {
        // Create the HTTP client using the FruitAPI named factory
        var httpClient = HttpClientFactory.CreateClient("FruitAPI");

        // Perform the GET request and store the response. The parameter
        // in GetAsync specifies the endpoint in the API 
        using HttpResponseMessage response = await httpClient.GetAsync("/fruits");

        // If the request is successful deserialize the results into the data model
        if (response.IsSuccessStatusCode)
        {
            using var contentStream = await response.Content.ReadAsStreamAsync();
            _fruitList = await JsonSerializer.DeserializeAsync<IEnumerable<FruitModel>>(contentStream);
        }
        else
        {
            // If the request is unsuccessful, log the error message
            Console.WriteLine($"Failed to load fruit list. Status code: {response.StatusCode}");
        }
    }
}

Perform a POST operation

POST operation should send a body and is used to add data to a resource. To perform an HTTP POST operation, given an HttpClient and a URI, use the HttpClient.PostAsync method. If you want to use a form to add items to the data on your home page you need to:

  • Use dependency injection to add the IHttpClientFactory to the page model.
  • Bind the data to the form using either the EditForm or EditContext model.
  • Serialize the data you want to add using the JsonSerializer.Serialize method.
  • Create an instance of the HttpClient
  • Perform the POSToperation.

 Note

Following our project model of a separate page for each REST operation the POST operation is performed in an Add.razor page with the code example in the Add.razor.cs code-behind file.

The following code example shows how to perform a POST operation. Be sure to read the comments in the code.

C#Copy

namespace FruitWebApp.Components.Pages;

public partial class Add : ComponentBase
{
    // IHttpClientFactory set using dependency injection 
    [Inject]
    public required IHttpClientFactory HttpClientFactory { get; set; }

    // NavigationManager set using dependency injection
    [Inject]
    private NavigationManager? NavigationManager { get; set; }

    // Add the data model and bind the form data to it
    [SupplyParameterFromForm]
    private FruitModel? _fruitList { get; set; }

    protected override void OnInitialized() => _fruitList ??= new();

    // Begin POST operation code
    private async Task Submit()
    {
        // Serialize the information to be added to the database
        var jsonContent = new StringContent(JsonSerializer.Serialize(_fruitList),
            Encoding.UTF8,
            "application/json");

        // Create the HTTP client using the FruitAPI named factory
        var httpClient = HttpClientFactory.CreateClient("FruitAPI");

        // Execute the POST request and store the response. The response will contain the new record's ID
        using HttpResponseMessage response = await httpClient.PostAsync("/fruits", jsonContent);

        // Check if the operation was successful, and navigate to the home page if it was
        if (response.IsSuccessStatusCode)
        {
            NavigationManager?.NavigateTo("/");
        }
        else
        {
            Console.WriteLine("Failed to add fruit. Status code: {response.StatusCode}");
        }
    }
}

Perform other REST operations

Other operations like PUT and DELETE follow the same model as shown previously. The following table defines common REST operations along with the associated HttpClient method:

RequestMethodDefinition
GETHttpClient.GetAsyncRetrieves a resource
POSTHttpClient.PostAsyncCreates a new resource
PUTHttpClient.PutAsyncUpdates an existing resource, or creates a new resource if it doesn’t exist
DELETEHttpClient.DeleteAsyncDeletes a resource
PATCHHttpClient.PatchAsyncPartially updates an existing resource

java ee enterprise edition training courses malaysia

Explore HTTP clients in .NET Core

The Hypertext Transfer Protocol (or HTTP) is used to request resources from a web server. Many types of resources are available on the web, and HTTP defines a set of request methods for accessing these resources. In .NET Core, those requests are made through an instance of the HttpClient.

There are two options for implementing HttpClient in your app and the recommendation is to choose the implementation based on the clients lifetime management needs:

  • Long-lived clients: create a static or singleton instance using the HttpClient class and set PooledConnectionLifetime
  • Short-lived clients: use clients created by IHttpClientFactory

Implement with the HttpClient class

The System.Net.Http.HttpClient class sends HTTP requests and receives HTTP responses from a resource identified by a URI. An HttpClient instance is a collection of settings applied to all requests executed by that instance, and each instance uses its own connection pool, which isolates its requests from others. Beginning with .NET Core 2.1, the SocketsHttpHandler class provides the implementation, making behavior consistent across all platforms.

HttpClient only resolves DNS entries when a connection is created. It doesn’t track time to live (TTL) durations specified by the DNS server. If DNS entries change regularly the client is unaware those updates. To solve this issue, you can limit the lifetime of the connection by setting the PooledConnectionLifetime property, so that DNS lookup is repeated when the connection is replaced.

In the following example, HttpClient is configured to reuse connections for 15 minutes. After the TimeSpan specified by PooledConnectionLifetime elapses, the connection is closed and a new one is created.

C#Copy

var handler = new SocketsHttpHandler
{
    PooledConnectionLifetime = TimeSpan.FromMinutes(15) // Recreate every 15 minutes
};
var sharedClient = new HttpClient(handler);

Implement with IHttpClientFactory

The IHttpClientFactory serves as a factory abstraction that can create HttpClient instances with custom configurations. IHttpClientFactory was introduced in .NET Core 2.1. Common HTTP-based .NET workloads can take advantage of middleware with ease.

When you call any of the extension methods, you’re adding the IHttpClientFactory and related services to the IServiceCollection. The IHttpClientFactory type offers the following benefits:

  • Exposes the HttpClient class as a dependency injection-ready type.
  • Provides a central location for naming and configuring logical HttpClient instances.
  • Codifies the concept of outgoing middleware via delegating handlers in HttpClient.
  • Provides extension methods for Polly based middleware to take advantage of delegating handlers in HttpClient.
  • Manages the caching and lifetime of underlying instances. Automatic management avoids common Domain Name System (DNS) problems that occur when manually managing HttpClient lifetimes.
  • Adds a configurable logging experience for all requests sent through clients created by the factory.

You should let HttpClientFactory and the framework manage the lifetimes and instantiation of HttpClient instances. The lifetime management helps avoid common issues such as DNS (Domain Name System) problems that can occur when manually managing HttpClient lifetimes.

dynamics 365 marketing training courses malaysia

Introduction

Hypertext Transfer Protocol (HTTP) requests are a way of asking a web server to provide or update a resource. HTTP defines a set of methods for sending requests to a web server. The server responds to the request by sending back the requested resource, or an error message if the resource isn’t available or the request is invalid.

Learning objectives

After completing this module, you’ll be able to:

  • Implement HTTP clients in .NET Core.
  • Use HTTP clients to perform safe and unsafe operations.
  • Add code to support HTTP operations in an ASP.NET Blazor Web app.

java programming training courses malaysia

Implement HTTP operations in ASP.NET Core Blazor Web apps

Learning objectives

After completing this module, you’ll be able to:

  • Implement HTTP clients in .NET Core
  • Use HTTP clients to perform safe and unsafe operations
  • Add code to support HTTP operations in an ASP.NET Core Blazor Web Apps

Prerequisites

  • Experience writing C# at an intermediate level
  • Knowledge of RESTful services and HTTP action verbs

oracle java training courses malaysia

Service lifetimes

When you register a service, you must choose a lifetime that matches how the service is used in the app. The lifetime affects how the service behaves when it’s injected into components. So far, you’ve registered services using the AddSingleton method. This method registers a service with a singleton lifetime. There are three built-in lifetimes for services in ASP.NET Core:

  • Singleton
  • Scoped
  • Transient

Singleton lifetime

Services registered with a singleton lifetime are created once when the app starts and are reused for the lifetime of the app. This lifetime is useful for services that are expensive to create or that don’t change often. For example, a service that reads configuration settings from a file can be registered as a singleton.

Use the AddSingleton method to add a singleton service to the service container.

Scoped lifetime

Services registered with a scoped lifetime are created once per configured scope, which ASP.NET Core sets up for each request. A scoped service in ASP.NET Core is typically created when a request is received and disposed of when the request is completed. This lifetime is useful for services that access request-specific data. For example, a service that fetches a customer’s data from a database can be registered as a scoped service.

Use the AddScoped method to add a scoped service to the service container.

Transient lifetime

Services registered with a transient lifetime are created each time they’re requested. This lifetime is useful for lightweight, stateless services. For example, a service that performs a specialized calculation can be registered as a transient service.

Use the AddTransient method to add a transient service to the service container.

Services that depend on other services

A service can depend on other services, typically by having its dependencies injected through its constructor. When you register a service that depends on another service, you must take service lifetime into account. For example, a singleton services shouldn’t depend on a scoped service because the scoped service is disposed of when the request is completed but a singleton lives for the lifetime of the app. Fortunately, ASP.NET Core will by default check for this misconfiguration and will report a scope validation error when the app starts up so the issue can be quickly identified and addressed.

jboss training courses malaysia