Norns.Urd.HttpClient

Norns.urd.HttpClient based on AOP framework Norns.urd implementation, is to System.Net.Http under the HttpClient package, so that we just need to be simple in the interface definition can achieve HTTP call, can reduce some repetitive code writing. Can and existing Norns. Urd. Extensions. Polly and Norns. Urd. Caching. The Memory.

Source code at: github.com/fs7744/Norn…

How do I enable the HttpClient function

  1. Introducing the Norns. Urd. HttpClient
dotnet add package Norns.Urd.HttpClient
Copy the code
  1. Code to enable HttpClient function, just
new ServiceCollection()
    .ConfigureAop(i => i.EnableHttpClient())
Copy the code
  1. Define the HttpClient interface to use

For example:

[BaseAddress("http://localhost.:5000")]
public interface ITestClient{[Get("WeatherForecast/file")]
    [AcceptOctetStream]
    Task<Stream> DownloadAsync();

    [Post("WeatherForecast/file")]
    [OctetStreamContentType]
    Task UpoladAsync([Body]Stream f);
}
Copy the code
  1. Register with IOC
new ServiceCollection()
    .AddSingleton<ITestClient>()  Norns.urd. HttpClient will generate the IL code for you
    .ConfigureAop(i => i.EnableHttpClient())
Copy the code
  1. Just use DI, for example
[ApiController]
[Route("[controller]")]
public class ClientController : ControllerBase
{
    private readonly ITestClient client;

    public ClientController(ITestClient client)
    {
        this.client = client;
    }

    [HttpGet("download")]
    public async Task<object> DownloadAsync()
    {
        using var r = new StreamReader(await client.DownloadAsync());
        return awaitr.ReadToEndAsync(); }}Copy the code

Features supported by HttpClient

The Url configuration

BaseAddress

You can use BaseAddressAttribute on an interface if the site domain name or underlying API address is used by many interfaces

Such as:

[BaseAddress("http://localhost.:5000")]
public interface ITestClient
Copy the code
Various Http methods support setting urls

Http Method supports the following:

  • GetAttribute
  • PostAttribute
  • PutAttribute
  • DeleteAttribute
  • PatchAttribute
  • OptionsAttribute
  • HeadAttribute

(If the method above is not enough, you can inherit the custom implementation of HttpMethodAttribute.)

All of these Http methods support Url configuration in one of two ways:

  • Static configuration
[Post("http://localhost.:5000/money/getData/")]
public Data GetData()
Copy the code
  • Dynamic configuration

Url configuration from IConfiguration via key is supported by default

[Post("configKey", IsDynamicPath = true)]
public Data GetData()
Copy the code

If such simple configuration form does not support your demand, can realize IHttpRequestDynamicPathFactory replacement interface configuration is implemented, just register to the IOC container can achieve a good class. ConfigurationDynamicPathFactory implementation examples can reference

Route Parameter Setting

If some URL route parameters need to be set dynamically, you can set them using RouteAttribute, for example

[Post("getData/{id}")]
public Data GetData([Route]string id)
Copy the code

If the parameter name does not match the Settings in the URL, you can use Alias =, for example

[Post("getData/{id}")]
public Data GetData([Route(Alias = "id")]string number)
Copy the code
Set the Query string

The Query String argument can be set in the method argument list

[Post("getData")]
public Data GetData([Query]string id);
//or
[Post("getData")]
public Data GetData([Query(Alias = "id")]string number);
Copy the code

The result of the Url is getData, right? id=xxx,

The parameter type can be a basic type or a class. When the parameter is class, the attribute of the class is taken as the parameter. Therefore, if the attribute name does not match the definition, you can use [Query(Alias = “XXX “)] on the attribute

Set the Request body

Request Body can be specified by setting the BodyAttribute parameter in the method parameter list. Note that only the first parameter with the BodyAttribute is valid, for example

public void SetData([Body]Data data);
Copy the code

The serializer will be selected to serialize the body based on the Request Content-Type set

The Response body set

Specify the type of Response body, just write the required type in the return type of the method, support the following

  • Void (ignore deserialization)
  • Task (ignore deserialization)
  • ValueTask (ignore deserialization)
  • T
  • Task
  • ValueTask
  • HttpResponseMessage
  • Stream (valid only if content-type is application/octet-stream)

For example:

public Data GetData();
Copy the code

Set the content-type

The content-type of both Request and Response affects the choice of serialization and deserializer,

Json/XML serialization and deserialization are supported by default

  • JsonContentTypeAttribute
  • XmlContentTypeAttribute
  • OctetStreamContentTypeAttribute

For example:

[OctetStreamContentType]
public Data GetData([Body]Stream s);
Copy the code

The corresponding Accept is set to

  • AcceptJsonAttribute
  • AcceptXmlAttribute
  • AcceptOctetStreamAttribute

For example:

[AcceptOctetStream]
public Stream GetData();
Copy the code

Json serializers default to system.text.json

Replace the JSON serializer with NewtonsoftJson

  1. The introduction ofNorns.Urd.HttpClient.NewtonsoftJson
  2. Registration methods in IOC, such as
new ServiceCollection().AddHttpClientNewtonsoftJosn()
Copy the code

Custom serializer

When existing serializers are insufficient to support your requirements, simply implement IHttpContentSerializer and register with the IOC container

The custom Header

In addition to the headers mentioned above, you can add other headers in either of the following ways:

  • useHeaderAttributeStatically configured on an interface or method
[Header("x-data"."money")]
public interface ITestClient {}
//or
[Header("x-data"."money")]
public Data GetData();
Copy the code
  • Method Parameters are dynamically configured
public Data GetData([SetRequestHeader("x-data")]string header);
Copy the code

Custom HttpRequestMessageSettingsAttribute

When existing HttpRequestMessageSettingsAttribute is insufficient to support demand, need to inherit HttpRequestMessageSettingsAttribute achieve its function, the corresponding interface/method can be used

Get the Response Header by setting the parameters

When sometimes we need to get returned to the header of the response, we can get the response out parameter + OutResponseHeaderAttribute header values (note that only the synchronization method, out parameters to work)

For example:

public Data GetData([OutResponseHeader("x-data")] out string header);
Copy the code

HttpClient some parameter setting methods

MaxResponseContentBufferSize
[MaxResponseContentBufferSize(20480)]
public interface ITestClient {}
//or
[MaxResponseContentBufferSize(20480)]
public Data GetData()
Copy the code
Timeout
[Timeout("00:03:00")]
public interface ITestClient {}
//or
[Timeout("00:03:00")]
public Data GetData()
Copy the code
ClientName

You can specify ClientNameAttribute when you need to obtain an HttpClient with a special setting in combination with HttpClientFactory

Such as

[ClientName("MyClient")]
public interface ITestClient {}
//or
[ClientName("MyClient")]
public Data GetData()
Copy the code

You can get the HttpClient as specified

services.AddHttpClient("MyClient", i => i.MaxResponseContentBufferSize = 204800);
Copy the code
HttpCompletionOption

The CompletionOption parameter on the HttpClient call can also be set

HttpCompletionOption ResponseHeadersRead is the default configuration

Such as

[HttpCompletionOption(HttpCompletionOption.ResponseContentRead)]
public interface ITestClient {}
//or
[HttpCompletionOption(HttpCompletionOption.ResponseContentRead)]
public Data GetData()
Copy the code

Global HttpRequestMessage and HttpResponseMessage handling

If HttpRequestMessage and HttpResponseMessage need to be handled globally, for example:

  • Set the link tracing ID
  • Response Custom processing of exceptions

This can be done by implementing IHttpClientHandler and registering with the IOC container using example default Status code checks such as:

public class EnsureSuccessStatusCodeHandler : IHttpClientHandler
{
    public int Order => 0;

    public Task SetRequestAsync(HttpRequestMessage message, AspectContext context, CancellationToken token)
    {
        return Task.CompletedTask;
    }

    public Task SetResponseAsync(HttpResponseMessage resp, AspectContext context, CancellationToken token)
    {
        resp.EnsureSuccessStatusCode();
        returnTask.CompletedTask; }}Copy the code

Of course, if the StatusCode check processing is not needed, it can be cleared directly from the IOC container, as in:

services.RemoveAll<IHttpClientHandler>();
// Then add your own handler
services.AddSingleton<IHttpClientHandler, xxx>();
Copy the code

Any questions are welcome to issue (^_^)