Blazor Server怎么进行HTTP请求,有哪些要点
Admin 2022-08-05 群英技术资讯 636 次浏览
翻译自 Waqas Anwar 2021年5月4日的文章 《Making HTTP Requests in Blazor Server Apps》 [1]
Blazor Server 应用使用标准的 ASP.NET Core 应用程序,在服务端执行 .NET 代码。在 Blazor Server 应用程序中,我们可以像在 ASP.NET Core Web 应用程序中那样,使用相同的方式访问任意 .NET 库或服务端功能。这其中的一项功能是,使用 HTTP Client 实例向第三方 Web API 发送 HTTP 请求。在本教程中,我将向您展示创建 HTTP Client 实例的不同方法。另外,我还会向您展示如何在 Blazor Server 应用程序中使用第三方 API 来获取和显示数据。
下载源码[2]
我们将开发一个 Blazor Server 应用程序,该应用允许用户在 Blazor 页面组件上输入国家代码和年份,然后我们将调用第三方 API 以获取指定国家和年份的公共假期列表。我们使用的第三方 API 是Nager.Date[3],它是一个全球公共假期 API。
这是一个非常简单的 API,您可以轻松地在 Postman 中输入以下 URL 测试此 API。
https://date.nager.at/api/v2/PublicHolidays/2021/CN
该 API 的响应是 JSON 格式的公共假期列表,如下所示:
在 Visual Studio 2019 中创建一个 Blazor Server 应用程序,并新建一个名为 Models 的文件夹。在 Models 文件夹中添加以下两个模型类,以映射上述 Holidays API 的请求和响应。
HolidayRequestModel.cs
public class HolidayRequestModel { public string CountryCode { get; set; } public int Year { get; set; } }
HolidayResponseModel.cs
public class HolidayResponseModel { public string Name { get; set; } public string LocalName { get; set; } public DateTime? Date { get; set; } public string CountryCode { get; set; } public bool Global { get; set; } }
接下来,在 Pages 文件夹中创建一个新的 Razor 组件 HolidaysExplorer.razor 和代码隐藏文件 HolidaysExplorer.razor.cs。如果您想了解有关 Razor 组件和代码隐藏文件的更多知识,可以阅读文章《Blazor 组件入门指南》。
HolidaysExplorer.razor.cs
public partial class HolidaysExplorer { private HolidayRequestModel HolidaysModel = new HolidayRequestModel(); private List<HolidayResponseModel> Holidays = new List<HolidayResponseModel>(); [Inject] protected IHolidaysApiService HolidaysApiService { get; set; } private async Task HandleValidSubmit() { Holidays = await HolidaysApiService.GetHolidays(HolidaysModel); } }
HolidaysModel 字段是 HolidayRequestModel 类的一个实例,它将帮助我们创建一个简单的表单来向用户询问国家代码和年份。下面的代码片段显示了使用 HolidaysModel 对象创建的 Blazor 表单,其中 HandleValidSubmit 方法是使用 Blazor Form 的 OnValidSubmit 事件配置的,用户提交表单时该方法将被调用。
<EditForm Model="@HolidaysModel" OnValidSubmit="@HandleValidSubmit" class="form-inline"> <label class="ml-2">Country Code:</label> <InputText id="CountryCode" @bind-Value="HolidaysModel.CountryCode" class="form-control" /> <label class="ml-2">Year:</label> <InputNumber id="Year" @bind-Value="HolidaysModel.Year" class="form-control" /> <button class="btn btn-primary ml-2" type="submit">Submit</button> </EditForm>
Holidays 列表用来显示从第三方 API 返回的假期。我们需要使用一个 @foreach 循环迭代返回的假期来生成一个简单的 bootstrap 表格。
@if (Holidays.Count > 0) { <table class="table table-bordered table-striped table-sm"> <thead> <tr> <th>Date</th> <th>Name</th> <th>Local Name</th> <th>Country Code</th> <th>Global</th> </tr> </thead> <tbody> @foreach (var item in Holidays) { <tr> <td>@item.Date.Value.ToShortDateString()</td> <td>@item.Name</td> <td>@item.LocalName</td> <td>@item.CountryCode</td> <td>@item.Global</td> </tr> } </tbody> </table> }
HolidaysExplorer.razor 视图的完整代码如下:
@page "/" <h3>Holidays Explorer</h3> <br /> <EditForm Model="@HolidaysModel" OnValidSubmit="@HandleValidSubmit" class="form-inline"> <label class="ml-2">Country Code:</label> <InputText id="CountryCode" @bind-Value="HolidaysModel.CountryCode" class="form-control" /> <label class="ml-2">Year:</label> <InputNumber id="Year" @bind-Value="HolidaysModel.Year" class="form-control" /> <button class="btn btn-primary ml-2" type="submit">Submit</button> </EditForm> <br /> @if (Holidays.Count > 0) { <table class="table table-bordered table-striped table-sm"> <thead> <tr> <th>Date</th> <th>Name</th> <th>Local Name</th> <th>Country Code</th> <th>Global</th> </tr> </thead> <tbody> @foreach (var item in Holidays) { <tr> <td>@item.Date.Value.ToShortDateString()</td> <td>@item.Name</td> <td>@item.LocalName</td> <td>@item.CountryCode</td> <td>@item.Global</td> </tr> } </tbody> </table> }
此时如果您运行该应用程序,您将看到一个不显示任何假期的简单 HTML 表单。这是因为方法 HandleValidSubmit 是空的,我们还未调用任何 API 来获取假期数据。
在 Blazor Server 应用程序中使用 HttpClient 请求第三方 API 有多种不同的方式,让我们从一个基础的示例开始,在该示例中我们使用 IHttpClientFactory
创建 HttpClient
对象。
在项目中创建一个 Services 文件夹,并创建如下的 IHolidaysApiService 接口。该接口只有一个方法 GetHolidays,它以 HolidayRequestModel 作为参数并返回 HolidayResponseModel 对象的列表。
IHolidaysApiService.cs
public interface IHolidaysApiService { Task<List<HolidayResponseModel>> GetHolidays(HolidayRequestModel holidaysRequest); }
接下来,在 Services 文件夹中创建一个 HolidaysApiService 类,实现上面的接口。
public class HolidaysApiService : IHolidaysApiService { private readonly IHttpClientFactory _clientFactory; public HolidaysApiService(IHttpClientFactory clientFactory) { _clientFactory = clientFactory; } public async Task<List<HolidayResponseModel>> GetHolidays(HolidayRequestModel holidaysRequest) { var result = new List<HolidayResponseModel>(); var url = string.Format("https://date.nager.at/api/v2/PublicHolidays/{0}/{1}", holidaysRequest.Year, holidaysRequest.CountryCode); var request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Add("Accept", "application/vnd.github.v3+json"); var client = _clientFactory.CreateClient(); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var stringResponse = await response.Content.ReadAsStringAsync(); result = JsonSerializer.Deserialize<List<HolidayResponseModel>>(stringResponse, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); } else { result = Array.Empty<HolidayResponseModel>().ToList(); } return result; } }
在上面的 GetHolidays 方法中,我们首先为第三方 API 创建了一个 URL,并将国家代码和年份参数添加到 URL 中。
var url = string.Format("https://date.nager.at/api/v2/PublicHolidays/{0}/{1}", holidaysRequest.Year, holidaysRequest.CountryCode);
接下来,我们创建了 HttpRequestMessage 对象并配置它以向第三方 API URL 发送 HTTP GET 请求。
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Add("Accept", "application/vnd.github.v3+json");
可以使用依赖注入 (DI) 请求一个 IHttpClientFactory,这正是我们将其注入到前面类的构造函数的原因。下面这行代码使用 IHttpClientFactory 创建了一个 HttpClient 实例。
var client = _clientFactory.CreateClient();
有了 HttpClient 对象之后,我们简单地调用它的 SendAsync 方法来发送一个 HTTP GET 请求。
var response = await client.SendAsync(request);
如果 API 调用成功,我们使用下面这行代码将其响应读取为字符串。
var stringResponse = await response.Content.ReadAsStringAsync();
最后,我们使用 JsonSerializer 类的 Deserialize 方法反序列化该响应。
result = JsonSerializer.Deserialize<List<HolidayResponseModel>>(stringResponse,
new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
在测试该应用程序之前,我们需要在 Startup.cs 文件中注册 HolidaysApiService 服务。我们还需要调用 AddHttpClient 方法注册 IHttpClientFactory。
Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton<IHolidaysApiService, HolidaysApiService>(); services.AddHttpClient(); }
运行应用程序并在文本框中提供任意国家代码和年份。点击 Submit 按钮就会在后台调用我们的 GetHolidays 方法,然后您应该能看到如下所示的公共假期列表。
上面的示例适用于您正在重构现有的应用程序,希望在不影响整个应用程序的情况下,在某些方法中使用 IHttpClientFactory 创建 HttpClient 对象的场景。如果您要创建一个全新的应用程序,或者您想要将创建 HttpClient 对象的方式集中化,那么您必须使用命名 HttpClient。
下面是创建命名 HTTP 客户端的好处:
我们可以在 Startup.cs 文件的 ConfigureServices 方法中,使用前面用过的名为 AddHttpClient 方法指定一个命名的 HttpClient。
Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton<IHolidaysApiService, HolidaysApiService>(); services.AddHttpClient("HolidaysApi", c => { c.BaseAddress = new Uri("https://date.nager.at/"); c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); }); }
我们需要指定客户端的名称(例如 HolidaysApi),我们还可以配置如上所示的 BaseAddress、DefaultRequestHeaders 和其他属性。
配置了命名 HttpClient 之后,我们可以使用相同的 CreateClient 方法在整个应用程序中创建 HttpClient 对象,不过这次我们需要指定想要创建哪个已命名的客户端(例如 HolidaysApi)。
HolidaysApiService.cs
public class HolidaysApiService : IHolidaysApiService { private readonly IHttpClientFactory _clientFactory; public HolidaysApiService(IHttpClientFactory clientFactory) { _clientFactory = clientFactory; } public async Task<List<HolidayResponseModel>> GetHolidays(HolidayRequestModel holidaysRequest) { var result = new List<HolidayResponseModel>(); var url = string.Format("api/v2/PublicHolidays/{0}/{1}", holidaysRequest.Year, holidaysRequest.CountryCode); var request = new HttpRequestMessage(HttpMethod.Get, url); var client = _clientFactory.CreateClient("HolidaysApi"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var stringResponse = await response.Content.ReadAsStringAsync(); result = JsonSerializer.Deserialize<List<HolidayResponseModel>>(stringResponse, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); } else { result = Array.Empty<HolidayResponseModel>().ToList(); } return result; } }
我们在 CreateClient 方法中传递的名称(比如 HolidaysApi)必须与我们在 Startup.cs 文件中配置的名称一致。每次调用 CreateClient 方法时,都会为我们创建一个新的 HttpClient 实例。
另外,我们不需要在请求的 URL 中指定 API 主机名称,因为我们在 Startup.cs 文件中已经指定过基地址了。
再次运行应用程序并提供国家代码和年份值,您应该能看到以下公共假期列表。
创建和使用 HttpClient 对象的第三种选择是使用类型化客户端。这种客户端具有以下好处:
要配置类型化的 HTTPClient,我们需要在 Startup.cs 文件中使用相同的 AddHttpClient 方法注册它,但这一次,我们需要传递我们的服务名称 HolidaysApiService 作为它的类型。
Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton<IHolidaysApiService, HolidaysApiService>(); services.AddHttpClient<HolidaysApiService>(); }
在上面的代码片段中,HTTP 客户端和我们的服务 HolidaysApiService 都将注册为瞬时客户端和服务。这将允许我们在服务的构造函数中传递 HttpClient,如以下代码片段所示。请注意,HttpClient 是如何公开为服务的 public 属性的。
HolidaysApiService.cs
public class HolidaysApiService : IHolidaysApiService { public HttpClient Client { get; } public HolidaysApiService(HttpClient client) { client.BaseAddress = new Uri("https://date.nager.at/"); client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); Client = client; } public async Task<List<HolidayResponseModel>> GetHolidays(HolidayRequestModel holidaysRequest) { var result = new List<HolidayResponseModel>(); var url = string.Format("api/v2/PublicHolidays/{0}/{1}", holidaysRequest.Year, holidaysRequest.CountryCode); var response = await Client.GetAsync(url); if (response.IsSuccessStatusCode) { var stringResponse = await response.Content.ReadAsStringAsync(); result = JsonSerializer.Deserialize<List<HolidayResponseModel>>(stringResponse, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); } else { result = Array.Empty<HolidayResponseModel>().ToList(); } return result; } }
类型化客户端的配置也可以不在类型化客户端的构造函数中指定,而在注册期间在 Startup.cs 文件的 ConfigureServices 方法中指定。
Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddHttpClient<IHolidaysApiService, HolidaysApiService>(c => { c.BaseAddress = new Uri("https://date.nager.at/"); c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); }); }
如果您使用的是这种方式,则无需单独注册您的服务。您可以从 ConfigureServices 方法中删除下面这行代码。
services.AddSingleton<IHolidaysApiService, HolidaysApiService>();
可以将 HttpClient 对象密封在一个类型化客户端中,而不公开为 public 属性。然后,我们可以在服务内部的任意方法中使用这个客户端。
public class HolidaysApiService : IHolidaysApiService { private readonly HttpClient _httpClient; public HolidaysApiService(HttpClient client) { _httpClient = client; } public async Task<List<HolidayResponseModel>> GetHolidays(HolidayRequestModel holidaysRequest) { var result = new List<HolidayResponseModel>(); var url = string.Format("api/v2/PublicHolidays/{0}/{1}", holidaysRequest.Year, holidaysRequest.CountryCode); var response = await _httpClient.GetAsync(url); if (response.IsSuccessStatusCode) { var stringResponse = await response.Content.ReadAsStringAsync(); result = JsonSerializer.Deserialize<List<HolidayResponseModel>>(stringResponse, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); } else { result = Array.Empty<HolidayResponseModel>().ToList(); } return result; } }
再次运行应用程序,并提供国家代码和年份值,您应该能够看到以下公共假期列表。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
SQL 克隆数据表 有些情况下,你可能需要原样拷贝某张数据表。但是,CREATE TABLE 却不能满足你的需要,因为复制表必须和原表拥有一样的索引、默认值等等。 如果你在使用 MySQL 关系型数据库管理系统的话,下面几个步骤可以帮你解决这个问题: 使用 SHOW CREATE TABLE 命令来获取一条指定了原表的结构、索引等信息的 CREATE TABLE 语句。 将语句中的表名修改为克隆表的名字,然后执行该语句。这样你就可以得到一张与原表完全相同的克隆表了。 如果你还想要复制表中的数据的话_来自SQL 教程,w3cschool编程狮。
如果日常的开发和维护均在类似dos窗口中进行,对于编程初学者来说,上手就略微有点困难,增加了学习成本。我们一般使用mysql图形管理工具来连接Mysql,然后在图形化界面上操作Mysql。MySQL的管理维护工具非常多,除了系统自带的命令行管理工具之外,还有许多其他的图形化管理工具。
DataReader和DataSet最大的区别在于,DataReader使用时始终占用SqlConnection(俗称:非断开式连接),在线操作数据库时,任何对SqlConnection的操作都会引发DataReader的异常。下面同本文对dataset与datareader的区别详细学习吧
对于一些新手来说,sql存储过程是比较难理解的知识点之一,也是学习SQL server需要掌握的内容,对下本文给大家分享一些sql存储过程的示例,希望对帮助大家学习和理解sql存储过程有帮助。
删除索引的sql语句是:【drop index [indexname] on mytable;】。我们可以使用【alter table tbl_name add index index_name (column_list):】语句添加索引。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008