.NET Core 使用 WebApiClient.JIT 调用第三方接口

开始前首先通过 NuGet 引入包,当前使用版本为 v1.0.9,发布日期 2019年5月21日

Github:https://github.com/dotnetcore/WebApiClient/tree/WebApiClient.JITAOT  注意底部有Wiki文档对使用非常有帮助,请仔细阅读。

1.新建 xxxHttpsModule 并在 Startup ConfigureServices 中注入。(单独新建 HttpsModule 是为了将不同的业务分离)

public static class xxxHttpsModule
{
    public static IServiceCollection Register(IServiceCollection services, IConfigurationRoot appConfiguration)
    {
        services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        void config(HttpApiConfig c)
        {
            c.HttpHost = new Uri(appConfiguration["Server:Url"]);//AppSettings.json 中的服务器地址
            c.GlobalFilters.Add(new DefaultHeaderAttribute(appConfiguration));
        }

        services.AddHttpApi<IxxxApi>().ConfigureHttpApiConfig(config);//注入接口

        return services;
    }
}

AddHttpApi 是一个扩展方法,这样写只是为了在多次使用时,看起来更协调。

/// <summary>
/// 基于DependencyInjection的扩展
/// </summary>
public static class DependencyInjectionExtensions
{
    /// <summary>
    /// 添加HttpApi
    /// 返回HttpApi工厂
    /// </summary>
    /// <typeparam name="TInterface">接口类型</typeparam>
    /// <param name="services"></param>
    /// <returns></returns>
    public static HttpApiFactoryBuilder<TInterface> AddHttpApi<TInterface>(this IServiceCollection services)
        where TInterface : class, IHttpApi
    {
        return new HttpApiFactoryBuilder<TInterface>(services);
    }
}

IxxxApi 接口中的内容就是第三方接口的内容

[TraceFilter(OutputTarget = OutputTarget.Console)]//这个设置可以将日志输入到控制台
public interface IxxxApi : IHttpApi
{
    /// <summary>
    /// 创建xxx信息
    /// </summary>
    /// <param name="input">实体</param>
    /// <returns></returns>
    [Timeout(10000)]
    [HttpPost("/api/v2/x/xxx")]
    ITask<AjaxResponse<List<xxxApiDto>>> GetxxxPagedList([JsonContent] xxxDto input);

    /// <summary>
    /// 获取xxx信息
    /// </summary>
    /// <param name="pageIndex">页码</param>
    /// <returns></returns>
    [Timeout(10000)]
    [HttpGet("/api/v2/x/xxx")]
    ITask<AjaxResponse<List<xxxApiDto>>> GetxxxPagedList(int pageIndex);
}

2.创建 HttpApi 实例工厂创建器类,具体内容如下。目前没有修改过里面的内容。

using System;
using WebApiClient;
using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;

/// <summary>
/// HttpApi实例工厂创建器
/// </summary>
/// <typeparam name="TInterface"></typeparam>
public class HttpApiFactoryBuilder<TInterface> where TInterface : class, IHttpApi
{
    private bool keepCookieContainer = true;

    private TimeSpan lifeTime = TimeSpan.FromMinutes(2d);

    private TimeSpan cleanupInterval = TimeSpan.FromSeconds(10d);

    private Action<HttpApiConfig, IServiceProvider> configOptions;

    private Func<IServiceProvider, HttpMessageHandler> handlerFactory;


    /// <summary>
    /// HttpApi实例工厂创建器
    /// </summary>
    /// <param name="services"></param>
    public HttpApiFactoryBuilder(IServiceCollection services)
    {
        services.AddSingleton<IHttpApiFactory<TInterface>, HttpApiFactory<TInterface>>(p =>
        {
            return new HttpApiFactory<TInterface>()
                .SetLifetime(this.lifeTime)
                .SetCleanupInterval(this.cleanupInterval)
                .SetKeepCookieContainer(this.keepCookieContainer)
                .ConfigureHttpMessageHandler(() => this.handlerFactory?.Invoke(p));
        });

        services.AddTransient(p =>
        {
            var factory = p.GetRequiredService<IHttpApiFactory<TInterface>>();
            factory.ConfigureHttpApiConfig(c =>
            {
                c.ServiceProvider = p;
                this.configOptions?.Invoke(c, p);
            });
            return factory.CreateHttpApi();
        });
    }

    /// <summary>
    /// 配置HttpApiConfig
    /// </summary>
    /// <param name="configOptions">配置选项</param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <returns></returns>
    public HttpApiFactoryBuilder<TInterface> ConfigureHttpApiConfig(Action<HttpApiConfig> configOptions)
    {
        if (configOptions == null)
        {
            throw new ArgumentNullException(nameof(configOptions));
        }
        return this.ConfigureHttpApiConfig((c, p) => configOptions.Invoke(c));
    }


    /// <summary>
    /// 配置HttpApiConfig
    /// </summary>
    /// <param name="configOptions">配置选项</param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <returns></returns>
    public HttpApiFactoryBuilder<TInterface> ConfigureHttpApiConfig(Action<HttpApiConfig, IServiceProvider> configOptions)
    {
        this.configOptions = configOptions ?? throw new ArgumentNullException(nameof(configOptions));
        return this;
    }

    /// <summary>
    /// 配置HttpMessageHandler的创建
    /// </summary>
    /// <param name="handlerFactory">创建委托</param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <returns></returns>
    public HttpApiFactoryBuilder<TInterface> ConfigureHttpMessageHandler(Func<HttpMessageHandler> handlerFactory)
    {
        if (handlerFactory == null)
        {
            throw new ArgumentNullException(nameof(handlerFactory));
        }
        return this.ConfigureHttpMessageHandler(p => handlerFactory.Invoke());
    }

    /// <summary>
    /// 配置HttpMessageHandler的创建
    /// </summary>
    /// <param name="handlerFactory">创建委托</param>
    /// <exception cref="ArgumentNullException"></exception>
    /// <returns></returns>
    public HttpApiFactoryBuilder<TInterface> ConfigureHttpMessageHandler(Func<IServiceProvider, HttpMessageHandler> handlerFactory)
    {
        this.handlerFactory = handlerFactory ?? throw new ArgumentNullException(nameof(handlerFactory));
        return this;
    }

    /// <summary>
    /// 置HttpApi实例的生命周期
    /// </summary>
    /// <param name="lifeTime">生命周期</param>
    /// <exception cref="ArgumentOutOfRangeException"></exception>
    /// <returns></returns>
    public HttpApiFactoryBuilder<TInterface> SetLifetime(TimeSpan lifeTime)
    {
        if (lifeTime <= TimeSpan.Zero)
        {
            throw new ArgumentOutOfRangeException(nameof(lifeTime));
        }
        this.lifeTime = lifeTime;
        return this;
    }


    /// <summary>
    /// 获取或设置清理过期的HttpApi实例的时间间隔
    /// </summary>
    /// <param name="interval">时间间隔</param>
    /// <exception cref="ArgumentOutOfRangeException"></exception>
    /// <returns></returns>
    public HttpApiFactoryBuilder<TInterface> SetCleanupInterval(TimeSpan interval)
    {
        if (interval <= TimeSpan.Zero)
        {
            throw new ArgumentOutOfRangeException(nameof(interval));
        }
        this.cleanupInterval = interval;
        return this;
    }

    /// <summary>
    /// 设置是否维护使用一个CookieContainer实例 该实例为首次创建时的CookieContainer
    /// </summary>
    /// <param name="keep">true维护使用一个CookieContainer实例</param>
    /// <returns></returns>
    public HttpApiFactoryBuilder<TInterface> SetKeepCookieContainer(bool keep)
    {
        this.keepCookieContainer = keep;
        return this;
    }
}

3.调用就和我们自己写的接口一样在构造函数中注入使用,如果不告诉你这是一个第三方接口,完全感觉不出来。

4.WebApiClient 还可以通过 AliasAs 属性自定义字段名称


[Serializable]
public class xxxApiDto
{
    /// <summary>
    /// 序列号
    /// </summary>
    [AliasAs("serialNum")]
    public string SerialNumber { get; set; }
}

目前发现如果在 xxxApiDto 类中属性存在类时, AliasAs 则不会被识别,目前的解决方案是使用 [JsonProperty(PropertyName = "serialNum")],再通过 JsonConvert.SerializeObject(xxx) 转换成 JSON 字符串。

5.请求注入 Headers ,可以通过继承 ApiActionFilterAttribute 类,然后重写 OnBeginRequestAsync 实现。

原文地址:https://www.cnblogs.com/fxck/p/13076679.html