zoukankan      html  css  js  c++  java
  • 钉钉开发系列(十)SaltUI与WebApi交互

    Asp.net中常用的数据交互是WebApi的方式,对于请求者只是向一个url发起请求。对于SaltUI,官方推荐使用salt-fetch.js来进行数据交互,当然直接使用zepto.js或者jquery.js以ajax来交互也是可以的。

    接上一篇《钉钉开发系列(九)SaltUI在VS中的开发》,我们在项目SaltUIDemo中构造WebApi端,在项目中添加一个Global.asax和WebApiConfig.cs,具体代码如下

    Global.asax

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    using System.Web.Mvc;
    using System.Web.Security;
    using System.Web.SessionState;
    
    namespace SaltUIDemo
    {
        public class Global : System.Web.HttpApplication
        {
    
            protected void Application_Start(object sender, EventArgs e)
            {
                AreaRegistration.RegisterAllAreas();
                WebApiConfig.Register(GlobalConfiguration.Configuration);
            }
    
            protected void Session_Start(object sender, EventArgs e)
            {
    
            }
    
            protected void Application_BeginRequest(object sender, EventArgs e)
            {
                
            }
    
            protected void Application_AuthenticateRequest(object sender, EventArgs e)
            {
    
            }
    
            protected void Application_Error(object sender, EventArgs e)
            {
    
            }
    
            protected void Session_End(object sender, EventArgs e)
            {
    
            }
    
            protected void Application_End(object sender, EventArgs e)
            {
    
            }
        }
    }

    需要添加System.Web.Http、System.Web.Http.WebHost、System.Web.Mvc的引用,我们采用4.0版本的。

    WebApiConfig.cs

    using System.Web.Http;
    
    namespace SaltUIDemo
    {
        public class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                //注册路由映射
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{action}/{id}",//action表示按方法路由
                    defaults: new { id = RouteParameter.Optional }
                );
            }
        }
    }
    
    在项目中添加Controllers文件夹,并在其下增加SystemController.cs的文件,代码如下

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    
    namespace SaltUIDemo.Controllers
    {
        public class SystemController:ApiController
        {
    
            #region Get Function              
            [HttpGet]
            public String Get()
            {
                return Guid.NewGuid().ToString();
            }
            #endregion
        }
    }
    重新编译,启动项目,然后测试api,结果如下

    可以看到我们以api/system/get访问时,得到了一串guid,这样WebApi端已经可以了,现在需要的是在SaltUI端向其发起请求。

    在SaltUIDemoSrc项目下的scr/app下有一个db.js文件,我们找到后,在里面配置要发起的请求,代码如下

    // See https://github.com/Jias/natty-fetch for more details.
    const context = salt.fetch.context({
        mockUrlPrefix: '/mock/api/',
        urlPrefix: '/api/',
        mock: false,
        // jsonp: true,
        withCredentials: false,
        traditional: true,
        data: {
            _tb_token_: ''
        },
        timeout: 5000,
        fit: function(response) {
            return {
                success: response.success,
                content: response.content,
                error: {
                    errorMsg: response.errorMsg,
                    errorCode: response.errorCode,
                    errorLevel: response.errorLevel
                }
            }
        }
    });
    
    context.create('SomeModuleAPI', {
        getSomeInfo: {
            mockUrl: 'query/getSomeInfo.json',
            url: 'query/getSomeInfo.json'
        }
    });
    
    context.create('System', {
        Get: {
            mockUrl: 'System/Get',
            url: 'System/Get'
        }
    });
    
    module.exports = context.api;
    
    其中mock改成了false,mockUrlPrefix和urlPrefix也作了修改,之后在后面添加了context.create('System',...)。

    请求配置设定好之后,我们在src/pages/system的action.js中添加一个action为get,代码如下

    action.js

    module.exports = Reflux.createActions([
        'fetch',
        'get'
    ]);

    然后在store.js中响应action的get,即设定onGet方法,代码如下

    const Actions = require('./actions');
    const DB = require('../../app/db');
    
    module.exports = Reflux.createStore({
        listenables: [Actions],
        data: {
            loaded: false
        },
    
        onFetch: function(params, cb) {
            let t = this;
            t.data.loaded = true;
            t.updateComponent();
            cb && cb(t.data);
        },
    
        onGet: function(params, cb) {
            let t = this;
            DB.System.Get(params)
            .then(function (content) {
                t.data.loaded = true;
                t.data.content = content;
                t.data.error = false;
                if (cb != undefined) {
                    cb(t.data);
                }
            })
            .catch(function (error) {
                t.data.error = error;
                if (cb != undefined) {
                    cb(t.data);
                }
            });
        },
    
        updateComponent: function() {
            this.trigger(this.data);
        },
    
        getInitialState: function() {
            return this.data;
        }
    });
    

    onGet中DB.System.Get就是发起请求的,以promise的方式来调用。

    现在我们在PageSystem.js中触发请求,修改其中的handleClick和render的代码,具体如下

        render() {
            let t=this;
            return (
                <div className="system">
                    page system-{t.state.guid}
                    <Button type='primary' onClick={t.handleClick.bind(t)}>测试</Button>
                </div>
            );
        }
    
        handleClick()
        {  let t=this;  
            Actions.get({}, function(data) {
                t.setState({guid:data.content});
            });  
        }
    其中handleClick中的t.setState是修改状态保存数据,同时触发render。render中的{t.state.guid}是动态获取state中的guid

    但是执行后会发现,数据并没有更新到界面中。

    为什么呢?原因在于db.js中我们需要对返回的数据进行一个预处理,即fit函数,修改后的代码如下

     fit: function(response) {
            return {
                success: true,//response.success,
                content:response,// response.content,
                error: {
                    errorMsg: response.errorMsg,
                    errorCode: response.errorCode,
                    errorLevel: response.errorLevel
                }
            }
        }
    再编译运行后,结果如下图

    界面中已经得到了guid的数据。

    现在我们回过头来看fit函数,需要将success设置为true时,数据才会正确响应,否则以错误的方式来处理。其实这样做是为了将数据的响应统一,为了配合这样的处理,我们可以将WebApi返回的数据也做成这样的格式,所以我们修改SystemController的代码,修改后的代码如下 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    
    namespace SaltUIDemo.Controllers
    {
        public class SystemController:ApiController
        {
    
            #region Get Function              
            [HttpGet]
            public ResponseResult<String> Get()
            {
                var result = new ResponseResult<String>
                {
                    success = true,
                    content = Guid.NewGuid().ToString(),
                    errorMsg = "OK",
                    errorCode = 10000,
                    errorLevel =0
                };
                return result;
            }
            #endregion
        }
    
        public class ResponseResult<T>
        {
            public bool success { get; set; }
    
            public T content { get; set; }
    
            public String errorMsg { get; set; }
    
            public int errorCode { get; set; }
    
            public int errorLevel { get; set; }
        }
    }
    我们测试一下api/system/get,结果如下图

    可以看到我们已经经得到了新的结构数据,这样我们再修改db.js的fit函数,其代码如下

     fit: function(response) {
            return {
                success: response.success,
                content:response.content,
                error: {
                    errorMsg: response.errorMsg,
                    errorCode: response.errorCode,
                    errorLevel: response.errorLevel
                }
            }
        }
    重新编译运行后,结果如下图

    这样一来,如果在SystemController中处理数据,得到了错误的,就可以直接将success置为false,然后设置errorMsg、errorCode、errorLevel,之后界面上就可以进行相应的处理了。

    除了发起Get请求之外,我们还会发起POST请求,这时在db.js的配置请求时,就需要指定post方法,同时指定header,示例如下

    context.create('System', {
        Get: {
            mockUrl: 'System/Get',
            url: 'System/Get'
        },
        Update: {
            mockUrl: 'System/Update',
            url: 'System/Update',
            method: 'POST',
            useOriginalData: true,
            header: {
                'Content-Type': 'application/json; charset=utf-8',
            }
        },
    });
    我们在Action.post的时候传输的是JSON.stringfy(param),在SystemController中是以[FromBody]的方式来接收数据,示例如下

    PageSystem.js的触发请求

    let t=this;
            let systemConfig=t.state.systemConfig;
            Actions.get(JSON.stringify(systemConfig), function(data) {
               //相应的处理
            });  

    SystemController.cs

            #region Update Function              
            [HttpPost]
            public void Update([FromBody]SystemConfig config)
            {
                //
            }
            #endregion


    经测试发现salt-fetch.js对于JSON.stringify的数据会进行参数化,导致不可预知的后果,这里采用一个暂时的处理方案,对salt-fetch.js中的配置增加一个useOriginalData的配置项,当遇到这个配置时,将原数据直接发送,salt-fetch.js修改的部分如下

    在salt-fetch.js中的defaultGlobalConfig中增useOriginalData


    salt-fetch.js中的makeVars进行修改


    对salt-fetch.js的sendajax作修改


    salt-fetch.js的ajax的defaultOptions进行修改


    salt-fetch.js中的ajax方法修改


    修改salt-fetch.js是一个不是很恰当的处理方案,只能暂且用之。

    至此SaltUI与WebApi的交互就实现了。

    欢迎打描左侧二维码打赏。

    转载请注明出处。







  • 相关阅读:
    机器学习的分类与主要算法对比
    关于在JSP页面中为什么一定要用${pageContext.request.contextPath}来获取项目路径,而不能用${request.contextPath}?
    Spring Boot静态资源处理
    Tomcat关闭后,重新启动,session中保存的对象为什么还存在解决方法
    Tomcat 7源码学习笔记 -9 tomcat重启后session仍然保留
    mysql-sql语句中变量的使用
    js检测对象中是否存在某个属性
    mysql :=和=的区别
    sql面试题(学生表_课程表_成绩表_教师表)
    ddd
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604921.html
Copyright © 2011-2022 走看看