杭州网站建设费用多少,个人网站设计欣赏,wps免费模板网站,网站页面尺寸本文内容
使用 AutoClientAttribute使用谓词属性定义 HTTP 方法HTTP 有效负载HTTP 头
显示另外 2 个 备注
此 API 是实验性的。 它可能会在后续版本的库中更改#xff0c;并且无法保证向后兼容性。
HttpClient是使用 REST API 的好方法#xff0c;但存在挑战。 其中一个挑…本文内容
使用 AutoClientAttribute使用谓词属性定义 HTTP 方法HTTP 有效负载HTTP 头
显示另外 2 个 备注
此 API 是实验性的。 它可能会在后续版本的库中更改并且无法保证向后兼容性。
HttpClient是使用 REST API 的好方法但存在挑战。 其中一个挑战是需要写入以使用 API 的样板代码量。 本文介绍了如何使用Microsoft.Extensions.Http.AutoClient NuGet 包修饰接口并生成 HTTP 客户端依赖项。 AutoClient 的基础源生成器生成接口的实现以及用于将其注册到依赖项注入容器中的扩展方法。 此外AutoClient 会为每个 HTTP 请求生成遥测数据该请求随Microsoft.Extensions.Http.Telemetry一起发送。
使用 AutoClientAttribute
AutoClientAttribute负责触发 AutoClient 生成器以发出修饰接口的相应实现。 它接受要从IHttpClientFactory中检索的HttpClient的httpClientName。 请考虑以下接口定义
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(httpClientName: GeneratedClient)]
public interface IProductClient
{
}提示
接口名称必须以I开头。 该名称去除了前导I并用作遥测RequestMetadata的RequestMetadata.DependencyName。 如果名称以Api或Client结尾则排除这些名称。 例如如果接口命名为IProductClient则依赖项名称为Product。
要替代计算的依赖项名称请使用AutoClientAttribute的customDependencyName参数。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(httpClientName: GeneratedClient,customDependencyName: Widget Service)]
public interface IWidgetClient
{
}备注
上述两个代码示例都会导致编译警告因为接口未定义任何 HTTP 方法。 该警告由 AutoClient 生成器发出提醒发出实现是无用的。
使用谓词属性定义 HTTP 方法
空接口不是有用的抽象。 要定义 HTTP 方法必须使用 HTTP 谓词属性。 每个 HTTP 方法都会返回TaskTResult其中T是以下类型之一
返回类型说明Taskstring响应的原始内容以字符串形式返回。TaskT当T是任何可序列化的类型时响应内容从 JSON 反序列化并返回。TaskHttpResponseMessage如果需要HttpResponseMessage本身如从HttpClient.SendAsync中返回请使用此类型。
当 HTTP 响应的内容类型未application/json且方法的返回类型不是Taskstring时会引发异常。
HTTP 谓词属性
使用以下属性之一定义 HTTP 方法
Microsoft.Extensions.Http.AutoClient.GetAttributeMicrosoft.Extensions.Http.AutoClient.PostAttributeMicrosoft.Extensions.Http.AutoClient.PutAttributeMicrosoft.Extensions.Http.AutoClient.PatchAttributeMicrosoft.Extensions.Http.AutoClient.DeleteAttributeMicrosoft.Extensions.Http.AutoClient.HeadAttributeMicrosoft.Extensions.Http.AutoClient.OptionsAttribute
每个属性都需要path参数该参数路由到基础 REST API并且它应相对于HttpClient.BaseAddress。 path不能包含查询字符串参数而是使用QueryAttribute。 从遥测的角度来看path用作RequestMetadata.RequestRoute。
使用任何谓词属性修饰的 HTTP 方法必须具有CancellationToken参数并且它应是定义的最后一个参数。 CancellationToken参数用于取消 HTTP 请求。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(GeneratedClient)]
public interface IUserClient
{[Get(/api/users)]public TaskUser[] GetUsersAsync(CancellationToken cancellationToken default);
}前面的代码
使用GetAttribute定义 HTTP 方法。path 为 /api/users。该方法返回TaskTResult其中T是User[]。此方法接受可选的CancellationToken参数该参数在未提供参数时分配给default。
路由参数
URL 可能包含路由参数例如/api/users/{userId}。 要定义路由参数方法还必须接受名称相同的参数本例中为userId
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(IRouteParameterUserClient), User Service)]
public interface IRouteParameterUserClient
{[Get(/api/users/{userId})]public TaskUser GetUserAsync(string userId,CancellationToken cancellationToken default);
}在上述代码中
GetUserAsync方法具有名为userId的路由参数。userId参数用于请求的path替换{userId}占位符。
遥测请求名称
方法名称用作RequestMetadata.RequestName。 如果方法名称包含Async后缀会将其删除。 例如名为GetUsersAsync的方法计算为GetUsers。
要替代名称请使用 HTTP 谓词属性的每个属性的RequestName属性。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(IRequestNameUserClient), User Service)]
public interface IRequestNameUserClient
{[Get(/api/users, RequestName CustomRequestName)]public TaskListUser GetUsersAsync(CancellationToken cancellationToken default);
}HTTP 有效负载
要使用请求发送 HTTP 有效负载请在方法的参数上使用BodyAttribute。 如果不向其传递任何参数它会将内容类型视为 JSON在发送之前对参数进行序列化。 否则请定义显式BodyContentType并在BodyAttribute内使用它。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(IPayloadUserClient), User Service)]
public interface IPayloadUserClient
{[Post(/api/users)]public TaskUser CreateUserAsync(// The content type is JSON// The parameter is serialized before sending[Body] User user,CancellationToken cancellationToken default);[Put(/api/users/{userId}/displayName)]public TaskUser UpdateDisplayNameAsync(string userId,// The content type is text/plain// The parameter is sent as is[Body(BodyContentType.TextPlain)] string displayName,CancellationToken cancellationToken default);
}HTTP 头
可通过两种方式使用 HTTP 请求发送标头。 其中一个方式最适合永不更改值的标头静态标头。 另一种方式是基于方法的参数更改的标头。
静态标头
要定义静态标头请在接口定义上使用StaticHeaderAttribute。 将标头名称和值传递给其构造函数。
还可以在方法中一起使用多个StaticHeaderAttribute。 在方法上使用StaticHeader属性时该 HTTP 标头仅针对该方法发送而接口级StaticHeader属性针对所有方法发送。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(IStaticHeaderUserClient), User Service)]
[StaticHeader(X-ForAllRequests, GlobalHeaderValue)]
public interface IStaticHeaderUserClient
{[Get(/api/users)][StaticHeader(X-ForJustThisRequest, RequestHeaderValue)]public TaskListUser GetUsersAsync(CancellationToken cancellationToken default);
}参数标头
使用HeaderAttribute定义基于参数的标头可以从方法的属性接收标头的值。 将标头名称传递给其构造函数。
该参数可以是任何类型。 当标头类型不是string时对参数的值调用.ToString()方法。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(IParameterHeaderUserClient), User Service)]
public interface IParameterHeaderUserClient
{[Get(/api/users)]public TaskListUser GetUsersAsync([Header(X-MyHeader)] string myHeader,CancellationToken cancellationToken default);
}查询参数
使用方法参数上的QueryAttribute定义查询参数。 所有类型都有效并且查询值依赖于.ToString()方法以在不是string类型时获取参数的值。
QueryAttribute.Key从参数的名称分配。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(IQueryUserClient))]
public interface IQueryUserClient
{[Get(/api/users)]public TaskListUser GetUsersAsync([Query] string search,CancellationToken cancellationToken default);
}GetUsersAsync方法生成 HTTP 请求其 URL 格式为/api/users?search{search}。 此格式用作遥测的RequestMetadata.RequestRoute。
如果需要更改查询键可以调用key基于参数的构造函数QueryAttribute(String)。
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(ICustomQueryUserClient))]
public interface ICustomQueryUserClient
{[Get(/api/users)]public TaskListUser GetUsersAsync([Query(customQueryKey)] string search,CancellationToken cancellationToken default);
}GetUsersAsync方法生成 HTTP 请求URL 格式类似于/api/users?customQueryKey{customQueryKey}因为密钥名称被替代为customQueryKey。
依赖项注入挂钩
除了接口的实现外生成扩展方法以在依赖项注入容器中注册客户端。 生成的扩展方法的名称与接口名称相同将前导I替换为Add。
例如请考虑以下接口定义
C#复制
using Microsoft.Extensions.Http.AutoClient;[AutoClient(nameof(ICompleteUserClient))]
[StaticHeader(User-Agent, dotnet-auto-client sample)]
public interface ICompleteUserClient
{[Get(users)]public TaskUser[] GetAllUsersAsync(CancellationToken cancellationToken default);[Get(users)]public TaskUser[] GetUserByNameAsync([Query] string name,CancellationToken cancellationToken default);[Get(users/{userId})]public TaskUser GetUserByIdAsync(int userId,CancellationToken cancellationToken default);[Post(users)][StaticHeader(X-CustomHeader, custom-value)]public TaskHttpResponseMessage CreateUserAsync([Body(BodyContentType.ApplicationJson)] User user,CancellationToken cancellationToken default);[Delete(user/{userId})]public TaskUser DeleteUserAsync(int userId,[Header(If-None-Match)] string eTag,CancellationToken cancellationToken default);
}虽然生成器发出ICompleteUserClient接口的实现但它还会在IServiceCollection上生成AddCompleteUserClient扩展方法。 请考虑以下示例Program.cs代码
C#复制
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;HostApplicationBuilder builder Host.CreateEmptyApplicationBuilder(null);// Add a named HTTP client ICompleteUserClient.
builder.Services.AddHttpClient(nameof(ICompleteUserClient), options
{options.BaseAddress new(https://jsonplaceholder.typicode.com);
});builder.Services.AddCompleteUserClient(options
{options.JsonSerializerOptions new(JsonSerializerDefaults.Web){PropertyNameCaseInsensitive true};
});builder.Services.AddSingletonUserService();using IHost host builder.Build();UserService service host.Services.GetRequiredServiceUserService();await service.ProcessUsersAsync();host.Run();在前面的示例代码中
Host.CreateEmptyApplicationBuilder用于创建HostApplicationBuilder。从HostApplicationBuilder.Services属性中检索IServiceCollection以调用AddHttpClient(IServiceCollection, String, ActionHttpClient)扩展方法。 使用要注册的HttpClient的名称和用于配置HttpClient实例的委托调用AddHttpClient扩展方法。调用AddCompleteUserClient扩展方法以注册ICompleteUserClient接口及其实现。
可以将客户端注入服务构造函数以使用客户端
C#复制
using System.Net.Http.Json;internal sealed class UserService(ICompleteUserClient userClient)
{public async Task ProcessUsersAsync(){// Create a new user.HttpResponseMessage response await userClient.CreateUserAsync(new(Id: null, /* Is populated upon successful HTTP POST when creating user */Name: Ada Lovelace,Username: ada.lovelace,Email: 1st-computer-programmerexample.com,Address: new(Street: 123 Engineer Lane,Suite: null,City: London,ZipCode: EC1A,Geo: new(Lat: 51.509865m, Lng: -0.118092m)),Phone: 1234567890,Website: www.example.com,Company: new(Name: Babbage, LLC.,CatchPhrase: works on my machine,Bs: This is the future)));User? createdUser await response.Content.ReadFromJsonAsyncUser();Console.WriteLine($CreateUserAsync: Created user{createdUser}...);// Get user by id.User receivedUser await userClient.GetUserByIdAsync(7);Console.WriteLine($GetUserAsync: Received user{receivedUser}...);// Get list of all users.User[] allUsers await userClient.GetAllUsersAsync();Console.WriteLine($GetUsersAsync: Received a total of {allUsers.Length} users...);}
}有关详细信息请参阅.NET 依赖项注入。