• 使用WebApiClient请求和管理Restful Api


    前言

    本篇文章的内容是WebApiClient应用说明篇,如果你没有了解过WebApiClient,可以先阅读以下相关文章:

    背景

    随着Wcf、Webservice等的SOAP的份额越来越少,以及Restful Api的兴起,目前几乎所有新平台提供的接口,都只提供Restful Api,而.net平台下,没有类似Wcf这么简单的客户端可以直接请求和管理这些Restful api的解决方案,.net平台提供的HttpWebRequest、WebClient和HttpClient这三个类库,可用于实现Http接口的请求,但相比wcf得益于soap自我描述实现的自动生成客户端调用代码,Restful就没这么方便了,无论使用HttpWebRequest还是HttpClient,都需要对每个Api缩写沉长的调用代码。

    使用WebApiClient

    WebApiClient是在这样的背景下产生一款Http全异步的客户端库,它的出现,大幅度减轻了接口调用者的工作量,而且在调用Http接口上还非常容易维护和更新,还可以轻松应对设计不太友好的一些http接口。

    使用WebApiClient,编程人员不再需要手动实现路径拼接、参数拼接、请求体组装和响应映射为模型这些繁琐的过程,以下为WebApiClient应用到项目中的一般流程:

    1 声明http接口的Interface

    [JsonReturn]
    public interface IIotRemotePush : IDisposable
    {
        /// <summary>
        /// 创建远程推送账号
        /// </summary>
        /// <param name="auth">授权</param>
        /// <returns></returns>
        [HttpPost("/v1/RemotePush/CreateAccount")]
        ITask<ApiResult<PushAccount>> CreateAccountAsync(IotBasicAuth auth);
    
        /// <summary>
        /// 获取推送服务信息
        /// </summary>
        /// <param name="id">pushId</param>
        /// <returns></returns>
        [HttpGet("/v1/Mqtt/GetPushSevice?id={id}")]
        ITask<ApiResult<MqttService>> GetPushSeviceAsync(string id);
    }
    
    /// <summary>
    /// Api结果接口
    /// </summary>
    public interface IApiResult
    {
        /// <summary>
        /// 错误码
        /// </summary>      
        ErrorCode Code { get; set; }
    
        /// <summary>
        /// 相关提示信息
        /// </summary>
        string Msg { get; set; }
    }
    
    
    /// <summary>
    /// 表示Api结果
    /// </summary>
    public class ApiResult<T> : IApiResult
    {
        /// <summary>
        /// 错误码
        /// </summary>
        public ErrorCode Code { get; set; }
    
        /// <summary>
        /// 相关提示信息
        /// </summary>
        public string Msg { get; set; }
    
        /// <summary>
        /// 业务数据
        /// </summary>
        public T Data { get; set; }
    }
    

    2 调用http接口

    WebApiClient不需要开者实现接口,使用HttpApiClient.Create方法可以动态创建接口的实现类的实例,调用实例的方法,就完成一个Api的请求。

    using (var iotApi = HttpApiClient.Create<IIotRemotePush>())
    {
        var auth = new IotBasicAuth(config.AppId, config.AppToken);
        var createResult = await iotApi.CreateAccountAsync(auth);
        if (createResult.Code != ErrorCode.NoError)
        {
            return null;
        }
    
        config.PushId = createResult.Data.Id;
        config.PushToken = createResult.Data.Token;
        await db.SaveChangesAsync();
    
        return config;
    }
    

    3 异常定义与异常处理

    在以上接口中,接口返回的都是ApiResult类型,此类型定义了一个ErrorCode类型的Code字段,这是业务的错误码,我们可以把它转换为.net的异常来处理。

    /// <summary>
    /// 表示Iot异常
    /// </summary>
    public class IotException : Exception
    {
        /// <summary>
        /// 错误码
        /// </summary>
        public ErrorCode ErrorCode { get; private set; }
    
        /// <summary>
        /// Iot异常
        /// </summary>
        /// <param name="apiResult">api结果值</param>
        public IotException(IApiResult apiResult)
            : base(apiResult.Msg)
        {
            this.ErrorCode = apiResult.Code;
        }
    }
    

    我们还应该在Interface上扩展JsonResult,用于将ApiResult的ErrorCode转换为IotException,并抛出:

    /// <summary>
    /// 表示IotJson结果
    /// </summary>
    public class IotJsonResultAttribute : JsonReturnAttribute
    {
        protected override async Task<object> GetTaskResult(ApiActionContext context)
        {
            var apiResult = await base.GetTaskResult(context) as IApiResult;
            if (apiResult != null && apiResult.Code != ErrorCode.NoError)
            {
                throw new IotException(apiResult);
            }
            return apiResult;
        }
    }
    

    然后将新的IotJsonResultAttribute在Interface上替换JsonReturnAttribute:

    [IotJsonResult]
    public interface IIotRemotePush : IDisposable
    {
       ...
    }
    

    最后,调用http接口的时候,可以使用Handle()扩展方法处理异常:

    using (var iotApi = HttpApiClient.Create<IIotRemotePush>())
    {
        var auth = new IotBasicAuth(config.AppId, config.AppToken);
        var createResult = await iotApi.CreateAccountAsync(auth)
            .Handle()
            .WhenCatch<IotException>(ex =>
            {
                // process exception
                return default(ApiResult<PushAccount>);
            })
            .WhenCatch<Exception>(ex =>
            {
                // process exception
                return default(ApiResult<PushAccount>);
            });
    
        if (createResult == null)
        {
            return null;
        }
    
        config.PushId = createResult.Data.Id;
        config.PushToken = createResult.Data.Token;
        await db.SaveChangesAsync();
    
        return config;
    }
    

    WebApiClient现状

    WebApiClient项目目前已加入.NET China Foundation,正在为.net开源作出自己的一点贡献。

  • 相关阅读:
    JavaScript 格式化数字
    浅析C#中单点登录的原理和使用
    从银行转账失败到分布式事务:总结与思考
    计算机网络资料
    阿里巴巴Java开发规约插件p3c详细教程及使用感受
    程序员如何打造属于自己的云笔记服务
    sql server2016里面的json功能
    mac pro 开启三只滑动选中文本
    技术网站
    idea gradle项目导入
  • 原文地址:https://www.cnblogs.com/kewei/p/8529695.html
Copyright © 2020-2023  润新知