zoukankan      html  css  js  c++  java
  • ABP开发框架前后端开发系列---(10)Web API调用类的简化处理

    原文:https://www.cnblogs.com/wuhuacong/p/11103110.html


    在较早期的随笔《ABP开发框架前后端开发系列---(5)Web API调用类在Winform项目中的使用》已经介绍了Web API调用类的封装处理,虽然这些调用类我们可以使用代码生成工具快速生成,不过自定义接口,还是需要我们对这些接口进行实现,以便发起对Web API的调用,并获得相应的数据返回。本篇随笔介绍使用API调用类的封装类,进行函数的抽象,根据方法名称的推断,构建URL或者WebClient的请求类型,从而实现所有API调用函数的简化处理。

    1、ABP框架服务端和客户端的处理

    ABP框架的架构图示,如下图所示(以字典模块为例说明)

    针对Web API接口调用的封装,为了适应客户端快速调用的目的,这个封装作为一个独立的封装层,以方便各个模块之间进行共同调用。

    而ABP的Web API调用类则需要对Web API接口调用进行封装,如下所示。

    如对于字典模块的API封装类,它们继承一个相同的基类,然后实现特殊的自定义接口即可,这样可以减少常规的Create、Get、GetAll、Update、Delete等操作的代码,这些全部由调用基类进行处理,而只需要实现自定义的接口调用即可。

    2、Web API调用类的简化处理

    我们对于常规的Web API调用接口处理,如下代码所示。

            public async virtual Task<AuthenticateResult> Authenticate(string username, string password)
            {
                var url = string.Format("{0}/api/TokenAuth/Authenticate", ServerRootAddress);
                var input = new
                {
                    UsernameOrEmailAddress = username,
                    Password = password
                };
    
                var result = await apiClient.PostAsync<AuthenticateResult>(url, input);
                return result;
            }

    这种方法的处理,就需要自己拼接URL地址,以及传递相关的参数,一般情况下,我们的Web API Caller层类的函数和Web API控制器的方法是一一对应的,因此方法名称可以通过对当前接口名称的推断进行获得,如下所示。

            public async Task<bool> ChangePassword(ChangePasswordDto input)
            {
                AddRequestHeaders();//加入认证的token头信息
                string url = GetActionUrl(MethodBase.GetCurrentMethod());//获取访问API的地址(未包含参数)
    
                return await apiClient.PostAsync<bool>(url, input);
            }

    函数AddRequestHeaders 通过在调用前增加对应的AccessToken信息,然后URL通过当前方法的推断即可构建一个完整的URL,但是这个也仅仅是针对POST的方法,因为ABP框架根据方法的名称前缀的不同,而采用POST、GET、Delete、PUT等不同的HTTP处理操作。

    如GET方法,则是需要使用GET请求

            public async Task<List<RoleDto>> GetRolesByUser(EntityDto<long> input)
            {
                AddRequestHeaders();//加入认证的token头信息
                string url = GetActionUrl(MethodBase.GetCurrentMethod());//获取访问API的地址(未包含参数)
                url = GetUrlParam(input, url);
    
                var result = await apiClient.GetAsync<List<RoleDto>>(url);
                return result;
            }

    而对于删除方法,则使用下面的DELETE请求,DELETE 和PUT操作,需要把参数串联成GET的URL形式,类似 url += string.Format("?Id={0}", id); 这样方式

            public virtual async Task Delete(TDeleteInput input)
            {
                AddRequestHeaders();//加入认证的token头信息
                string url = GetActionUrl(MethodBase.GetCurrentMethod());//获取访问API的地址(未包含参数)
                url += GetUrlParam(input, url);
                var result = await apiClient.DeleteAsync(url);
                return result;
            }

    对于更新的操作,使用了PUT方法

            public async virtual Task<TEntityDto> Update(TUpdateInput input)
            {
                AddRequestHeaders();//加入认证的token头信息
                string url = GetActionUrl(MethodBase.GetCurrentMethod());//获取访问API的地址(未包含参数)
                var result = await apiClient.PutAsync<TEntityDto>(url, input, null);
                return result;
            }

    上面这些方法,我们根据规律,其实可以进一步进行简化,因为这些操作大多数类似的。

    首先我们看到变化的地方,就是根据方法的前缀采用GET、POST、DELETE、PUT方法,还有就是URL串联字符串的不同,对于GET、Delete方法,参数使用的是组成URL方式,参数使用的是JSON提交内容方式。

    根据这些变化,我们在基类提炼一个统一的处理方法DoActionAsync 来处理这些不同的操作。

            /// <summary>
            /// 根据方法名称自动执行GET/POST/PUT/DELETE请求方法
            /// </summary>
            /// <param name="method"></param>
            /// <param name="input"></param>
            protected virtual async Task DoActionAsync(MethodBase method, object input = null)
            {
                await DoActionAsync<object>(method, input);
            }
            /// <summary>
            /// 根据方法名称自动执行GET/POST/PUT/DELETE请求方法
            /// </summary>
            /// <param name="method"></param>
            /// <param name="input"></param>
            protected virtual async Task<TResult> DoActionAsync<TResult>(MethodBase method, object input = null)
            {
                AddRequestHeaders();//加入认证的token头信息
    
                string action = GetMethodName(method);
                var url = string.Format("{0}/api/services/app/{1}/{2}", ServerRootAddress, DomainName, action);//获取访问API的地址(未包含参数)
                var httpVerb = DynamicApiVerbHelper.GetConventionalVerbForMethodName(action);
                if(httpVerb == HttpVerb.Get || httpVerb == HttpVerb.Delete)
                {
                    if (input != null)
                    {
                        //Get和Delete的操作,需要组装URL参数
                        url = GetUrlParam(input, url);
                    }
                }
    
                int? timeout = null;
                return await apiClient.DoActionAsync<TResult>(url, timeout, httpVerb.ToString().ToLower(), input);
            }

    这样,有了这两个函数的支持,我们可以简化很多操作代码了。

    例如对于Update方法,简化的代码如下所示。

            public async virtual Task<TEntityDto> Update(TUpdateInput input)
            {
                return await DoActionAsync<TEntityDto>(MethodBase.GetCurrentMethod(), input);
            }

    对于删除操作,简化的代码依旧也是一行代码

            public virtual async Task Delete(TDeleteInput input)
            {
                await DoActionAsync(MethodBase.GetCurrentMethod(), input);
            }

    GET操作,也是一行代码

            public async virtual Task<TEntityDto> Get(TGetInput input)
            {
                return await DoActionAsync<TEntityDto>(MethodBase.GetCurrentMethod(), input);
            }

    现在你看到,所有的客户端API封装类调用,都已经非常简化,大同小异了,主要就是交给基类函数进行推断调用处理即可。

    如用户操作的APICaller类的代码如下所示。

    这样我们再多的接口,都一行代码调用解决问题,非常简单,从此客户端封装类的实现就非常简单了,只需要注意有没有返回值即可,其他的都没有什么不同。

    只需要注意的是,我们定义接口的时候,尽可能使用复杂类型对象,这样就可以根据对象属性名称和值进行构建URL或者JSON的了。

  • 相关阅读:
    AngularJS Insert Update Delete Using PHP MySQL
    Simple task manager application using AngularJS PHP MySQL
    AngularJS MySQL and Bootstrap Shopping List Tutorial
    Starting out with Node.js and AngularJS
    AngularJS CRUD Example with PHP, MySQL and Material Design
    How to install KVM on Fedora 22
    Fake_AP模式下的Easy-Creds浅析
    河南公务员写古文辞职信
    AI
    政协委员:最大愿望是让小学生步行上学
  • 原文地址:https://www.cnblogs.com/springsnow/p/13901915.html
Copyright © 2011-2022 走看看