钉钉开发系列(十)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的交互就实现了。

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

转载请注明出处。







原文地址:https://www.cnblogs.com/sparkleDai/p/7604921.html