UnityWebGL调研(2) WebApi通信

8 篇文章 4 订阅
2 篇文章 0 订阅

unity版本 2017.3.0f

通信方式 WebApi+WCF

wcf是用于将服务端的类定位更新到客户端用的,最后没想到是这个思路导致的问题。

 

1.WebApi通信

通信用全部代码

其中Location.WCFServiceReferences.LocationServices;是wcf服务引用的客户端类库,

核心是GetString,PostString等通信代码,通信结束获得结果,转换成类对象。

在网上的代码的基础上封装一下。

using Location.WCFServiceReferences.LocationServices;
using Newtonsoft.Json;

using System;
using System.Text;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class WebApiClient : MonoBehaviour,ICommunicationClient
{
    // Use this for initialization
    void Start()
    {
        //GetTags((txt) =>
        //{
        //    Debug.Log(txt);
        //});
        //GetTag(128, (txt) =>
        // {
        //     Debug.Log(txt);
        // });
        LoginOut();
    }

    public bool isGetTagsBusy = false;

    public string host = "localhost";
    public string port = "8733";

    public string GetBaseUrl()
    {
        return string.Format("http://{0}:{1}/api/", host, port);
    }

    IEnumerator GetArray<T>(string url, Action<T[]> callback,Action<string> errorCallback=null)
    {
        //Debug.Log("GetArray:" + url);
        yield return GetString(url, json =>
        {
            try
            {
                T[] array = null;
                if (json == null || json == "")
                {
                    array = null;
                }
                else
                {
                    array = JsonConvert.DeserializeObject<T[]>(json);
                }
                if (callback != null)
                {
                    callback(array);
                }

                //ThreadManager.Run(() => //将json解析过程放到子线程中处理
                //{
                //    T[] array = JsonConvert.DeserializeObject<T[]>(json);
                //    return array;
                //}, (array) =>
                //{
                //    if (callback != null)
                //    {
                //        callback(array);
                //    }
                //}, "DeserializeObject");
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.ToString());
            }
        }, errorCallback);
    }

    //IEnumerator GetList<T>(string url, Action<List<T>> callback, Action<string> errorCallback)
    //{
    //    //Debug.Log("GetArray:" + url);
    //    yield return GetString(url, json =>
    //    {
    //        try
    //        {
    //            //var jo = JArray.Parse(json);
    //            //T[] array = jo.ToObject<T[]>();//此处Data类和Java中的结构完全一样
    //            List<T> list = JsonConvert.DeserializeObject<List<T>>(json);
    //            if (callback != null)
    //            {
    //                callback(list);
    //            }
    //        }
    //        catch (Exception ex)
    //        {
    //            Debug.LogError(ex.ToString());
    //        }
    //    }, errorCallback);
    //}

    IEnumerator GetObject<T>(string url, Action<T> callback, Action<string> errorCallback=null)
    {
        //Debug.Log("GetObject:" + url);
        yield return GetString(url, json =>
        {
            try
            {
                //T obj = JObject.Parse(json).ToObject<T>();//此处Data类和Java中的结构完全一样

                T obj = default(T);
                if (json == null || json == "")
                {
                    obj = default(T);
                }
                else
                {
                    obj = JsonConvert.DeserializeObject<T>(json);
                }

                if (callback != null)
                {
                    callback(obj);
                }

                //ThreadManager.Run(() => //将json解析过程放到子线程中处理
                //{
                //    T obj = JsonConvert.DeserializeObject<T>(json);
                //    return obj;
                //}, (obj) =>
                // {
                //     if (callback != null)
                //     {
                //         callback(obj);
                //     }
                // }, "DeserializeObject");
            }
            catch (Exception ex)
            {
                Debug.LogError("WebApiClient.GetObject:"+url+"\n"+ex.ToString());
            }
        }, errorCallback);
    }

    IEnumerator DeleteString(string url, Action<string> callback, Action<string> errorCallback)
    {
        using (UnityWebRequest www = new UnityWebRequest())
        {
            www.url = url;
            www.method = UnityWebRequest.kHttpVerbDELETE;
            www.downloadHandler = new DownloadHandlerBuffer();
            yield return www.SendWebRequest();
            if (www.isNetworkError || www.isHttpError)
            {
                Debug.LogError(www.error + "|" + url);
                if (errorCallback != null)
                {
                    errorCallback(www.error);
                }
                else
                {
                    if (callback != null)
                    {
                        callback(null);
                    }
                }
            }
            else
            {
                string text = www.downloadHandler.text;
                //Debug.Log(text);
                if (callback != null)
                {
                    callback(text);
                }
            }
        }
    }


    IEnumerator DeleteObject<T>(string url, Action<T> callback, Action<string> errorCallback = null)
    {
        yield return DeleteString(url, json =>
        {
            try
            {
                //T obj = JObject.Parse(json).ToObject<T>();//此处Data类和Java中的结构完全一样

                T obj = default(T);
                if (json == null || json == "")
                {
                    obj = default(T);
                }
                else
                {
                    obj = JsonConvert.DeserializeObject<T>(json);
                }

                if (callback != null)
                {
                    callback(obj);
                }

                //ThreadManager.Run(() => //将json解析过程放到子线程中处理
                //{
                //    T obj = JsonConvert.DeserializeObject<T>(json);
                //    return obj;
                //}, (obj) =>
                // {
                //     if (callback != null)
                //     {
                //         callback(obj);
                //     }
                // }, "DeserializeObject");
            }
            catch (Exception ex)
            {
                Debug.LogError("WebApiClient.DeleteObject:" + url + "\n" + ex.ToString());
            }
        }, errorCallback);
    }



    IEnumerator GetString(string url, Action<string> callback,Action<string> errorCallback)
    {
        //Debug.Log("GetString:" + url);
        using (UnityWebRequest www = new UnityWebRequest())
        {
            www.url = url;
            www.method = UnityWebRequest.kHttpVerbGET;
            www.downloadHandler = new DownloadHandlerBuffer();
            yield return www.SendWebRequest();
            if (www.isNetworkError || www.isHttpError)
            {
                Debug.LogError(www.error+"|"+url);
                if (errorCallback != null)
                {
                    errorCallback(www.error);
                }
                else
                {
                    if (callback != null)
                    {
                        callback(null);
                    }
                }
            }
            else
            {
                string text = www.downloadHandler.text;
                //Debug.Log(text);
                if (callback != null)
                {
                    callback(text);
                }
            }
        }
    }

    public IEnumerator PostObject<T>(string url,object entity,Action<T> callback,Action<string> errorCallback)
    {
        using (UnityWebRequest www = new UnityWebRequest())
        {
            www.url = url;
            Debug.Log(url);
            www.method = UnityWebRequest.kHttpVerbPOST;
             string  json = JsonConvert.SerializeObject(entity);
             Debug.Log("获取json:" + json.ToString());
            if (json != null && json != "")
            {
                Debug.Log("转化为byte类型");
                byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
                Debug.Log("bodyRaw:byte");
                www.uploadHandler = new UploadHandlerRaw(bodyRaw);
                Debug.Log(www.uploadHandler.ToString());
                www.SetRequestHeader("Content-Type", "application/json");
            }
            else
            {
                Debug.Log("未生成");
            }

            www.downloadHandler = new DownloadHandlerBuffer();

            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log("错误:www.error =>"+www.error);
                if (errorCallback != null)
                {
                    errorCallback(www.error);
                }
            }
            else
            {
                // Show results as text
                string text = www.downloadHandler.text;
                Debug.Log(text);

                if(typeof(T) == typeof(string))
                {
                    T result = (T)Convert.ChangeType(text, typeof(T));
                    if (callback != null)
                    {
                        callback(result);
                    }
                }
                else
                {
                    if (!string.IsNullOrEmpty(text))
                    {
                        try
                        {
                            T t = JsonConvert.DeserializeObject<T>(text);
                            if (callback != null)
                            {
                                callback(t);
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.LogError("WebApiClient.PostObject:" + url + "\n" + ex.ToString());
                            if (errorCallback != null)
                            {
                                errorCallback(ex.ToString());
                            }
                        }
                    }
                    else
                    {
                        if (callback != null)
                        {
                            callback(default(T));
                        }
                    }
                }

                // Or retrieve results as binary data
                //byte[] results = www.downloadHandler.data;
            }
        }
    }


    IEnumerator PutObject<T>(string url, T entity, Action<T> callback, Action<string> errorCallback)
    {
        using (UnityWebRequest www = new UnityWebRequest())
        {
            www.url = url;
            Debug.Log(url);
            www.method = UnityWebRequest.kHttpVerbPUT;
            string json = JsonConvert.SerializeObject(entity);
            Debug.Log("获取json:" + json.ToString());
            if (json != null && json != "")
            {
                Debug.Log("转化为byte类型");
                byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
                Debug.Log("bodyRaw:byte");
                www.uploadHandler = new UploadHandlerRaw(bodyRaw);
                Debug.Log(www.uploadHandler.ToString());
                www.SetRequestHeader("Content-Type", "application/json");
            }
            else
            {
                Debug.Log("未生成");
            }

            www.downloadHandler = new DownloadHandlerBuffer();

            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log("错误:www.error =>" + www.error);
                if (errorCallback != null)
                {
                    errorCallback(www.error);
                }
            }
            else
            {
                // Show results as text
                string results = www.downloadHandler.text;
                Debug.Log(results);
                if (results != null && results != "")
                {
                    try
                    {
                        T t = default(T);
                        t = JsonConvert.DeserializeObject<T>(results);
                        if (t != null)
                        {
                            callback(t);
                        }

                    }
                    catch (Exception ex)
                    {
                        Debug.LogError("WebApiClient.PostObject:" + url + "\n" + ex.ToString());
                    }
                }
                // Or retrieve results as binary data
                //byte[] results = www.downloadHandler.data;
            }
        }
    }


    

    string getTagsUrl;

    private Tag[] tagsBuffer;

    public void GetTags(Action<Tag[]> callback)
    {
        getTagsUrl = GetBaseUrl() + "tags/detail";
        if (isGetTagsBusy == true && tagsBuffer!=null)//必须有这个,不然和InvokeRepeating结合会导致一直发送没有接收。奇怪,又没有了
        {
            //Log.Alarm("WebApi.GetTags", "isBusy == true");
            if (callback != null)
            {
                callback(tagsBuffer);//有缓存数据把缓存给他。
            }
            return;
        }
        isGetTagsBusy = true;//奇怪,又没有了
        StartCoroutine(GetArray<Tag>(getTagsUrl, (tags) =>
        {
            tagsBuffer = tags;
            if (callback != null)
            {
                callback(tags);
            }
            isGetTagsBusy = false;
        },error=>
        {
            if (callback != null)
            {
                callback(null);//这个不能忘记
            }
            isGetTagsBusy = false;//断线重连的情况
        }));
    }

    public void GetRealPositions(Action<TagPosition> callback)
    {
        string url = GetBaseUrl() + "pos";
        StartCoroutine(GetObject(url, callback));
    }

    public void GetTag(int id, Action<Tag> callback)
    {
        string url = GetBaseUrl() + "tags/" + id;
        StartCoroutine(GetObject(url, callback));
    }
    public void GetPersonTree(Action<AreaNode> callback)
    {
        string url = GetBaseUrl() + "areas/tree?view=2";
        StartCoroutine(GetObject(url, callback));
    }

    public void GetDepartmentTree(Action<Department> callback)
    {
        string url = GetBaseUrl() + "deps/tree?view=2";
        StartCoroutine(GetObject(url, callback));
    }


    public void GetTopoTree(Action<PhysicalTopology> callback)
    {
        string url = GetBaseUrl() + "areas/tree/detail?view=0";
        StartCoroutine(GetObject(url, callback));
    }

    public void GetAreaStatistics(int id, Action<AreaStatistics> callback)
    {
        string url = GetBaseUrl() + "areas/statistics?id=" + id;
        StartCoroutine(GetObject(url, callback));
    }

    public void GetPointsByPid(int areaId, Action<AreaPoints[]> callback)
    {
        string url = GetBaseUrl() + "areas/getPointsByPid?pid=" + areaId;
        StartCoroutine(GetArray(url, callback));
    }

    public void HeartBeat(string info, Action<string> callback, Action<string> errorCallback)
    {
        string url = GetBaseUrl() + "users/HeartBeat/" + info;
        StartCoroutine(GetString(url, callback,errorCallback));
    }
    /// <summary>
    /// 登录
    /// </summary>
    /// <param name="info"></param>
    /// <param name="callback"></param>
    /// <param name="errorCallback"></param>
    public void Login(LoginInfo info, Action<LoginInfo> callback,Action<string> errorCallback)
    {
     string url = GetBaseUrl() + "users/LoginPost";
        Debug.Log(url);
        StartCoroutine(PostObject(url,info,callback,errorCallback));
    }

    /// <summary>
    /// 登出
    /// </summary>
    /// <param name="info"></param>
    /// <param name="callback"></param>
    /// <param name="errorCallback"></param>
    public void LoginOut(LoginInfo info, Action<LoginInfo> callback, Action<string> errorCallback)
    {
        string url = GetBaseUrl() + "users/LogoutPost";
        Debug.Log(url);
        StartCoroutine(PostObject(url,info,callback,errorCallback));
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="info"></param>
    /// <param name="callback"></param>
    /// <param name="errorCallback"></param>
    public void KeepLive(LoginInfo info, Action<LoginInfo> callback, Action<string> errorCallback)
    {
        string url = GetBaseUrl() + "users/KeepLivePost";
        Debug.Log(url);
        StartCoroutine(PostObject(url, info, callback, errorCallback));

    }



    /// <summary>
    /// 获取人员列表
    /// </summary>
    /// <param name="name"></param>
    /// <param name="callback"></param>
    /// <param name="errorCallback"></param>
    public void getListPersonls(string name, Action<Personnel[]> callback, Action<string> errorCallback)
    {
        Debug.Log(name);
        string url = GetBaseUrl();
        //if (name != null && name != "")
        //{
        //    url += "persons/list";
        //}
        //else
        //{
        //    url += "persons/search/?name="+name;
        //}
        url += "persons/list";

        Debug.Log(url);
        StartCoroutine(GetArray(url, callback, errorCallback));
    }

    /// <summary>
    /// 添加人员
    /// </summary>
    /// <param name="person"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void AddPersonnel(Personnel person, Action<Personnel> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl()+ "persons";
        Debug.Log(url);
        StartCoroutine(PostObject(url,person,callBack,errorBack));
    }
    /// <summary>
    /// 修改人员
    /// </summary>
    /// <param name="person"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void UpdatePersonnel(Personnel person, Action<Personnel> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl() + "persons";
        Debug.Log(url);
        StartCoroutine(PutObject(url, person, callBack, errorBack));
    }

    /// <summary>
    /// 删除人员
    /// </summary>
    /// <param name="id"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void DeletePersonnel(string id, Action<Personnel> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl()+ "persons/"+id;
        Debug.Log(url);
        StartCoroutine(DeleteObject(url,callBack,errorBack));
    }

    /// <summary>
    /// 根据ID查询人员信息
    /// </summary>
    /// <param name="id"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void GetPersonnelById(string id, Action<Personnel> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl() + "persons/" + id;
        Debug.Log(url);
        StartCoroutine(GetObject(url, callBack, errorBack));
    }


    /// <summary>
    /// 获取设备列表
    /// </summary>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void GetDevList(Action<DevInfo[]> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl() + "devices/list";
        Debug.Log(url);
        StartCoroutine(GetArray(url,callBack,errorBack));
    }

    /// <summary>
    /// 获取设备详细信息
    /// </summary>
    /// <param name="id"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void GetDevinfoById(string id, Action<DevInfo> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl() + "devices/"+id;
        Debug.Log(url);
        StartCoroutine(GetObject(url, callBack, errorBack));
    }

    /// <summary>
    /// 添加设备
    /// </summary>
    /// <param name="devinfo"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void AddDevinfo(DevInfo devinfo, Action<DevInfo> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl() + "devices" ;
        Debug.Log(url);
        StartCoroutine(PostObject(url, devinfo,callBack, errorBack));
    }


    /// <summary>
    /// 修改设备
    /// </summary>
    /// <param name="devinfo"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void UpdateDevinfo(DevInfo devinfo, Action<DevInfo> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl() + "devices";
        Debug.Log(url);
        StartCoroutine(PutObject(url, devinfo, callBack, errorBack));
    }
    /// <summary>
    /// 删除设备
    /// </summary>
    /// <param name="id"></param>
    /// <param name="callBack"></param>
    /// <param name="errorBack"></param>
    public void DeleteDevinfo(string id, Action<DevInfo> callBack, Action<string> errorBack)
    {
        string url = GetBaseUrl() + "devices?id="+id;
        Debug.Log(url);
        StartCoroutine(DeleteObject(url, callBack, errorBack));

    }





}

2.对象转换

这个就比较坑了,先说明一下情况,有个wcf的客户端服务引用的类库,wcf.dll吧,有个通信用的类库 client.dll吧,就是放上面的WebApiClient的代码的。client.dll引用了wcf.dll,都放到unity的Plugins文件夹里面,在脚本中调用。

弄了个在简单字符串通信测试没问题的基础上,弄了个登录接口。

 /// <summary>
    /// 登录
    /// </summary>
    /// <param name="info"></param>
    /// <param name="callback"></param>
    /// <param name="errorCallback"></param>
    public void Login(LoginInfo info, Action<LoginInfo> callback,Action<string> errorCallback)
    {
     string url = GetBaseUrl() + "users/LoginPost";
        Debug.Log(url);
        StartCoroutine(PostObject(url,info,callback,errorCallback));
    }

wcf服务端的类

public class LoginInfo
    {
        public string UserName { get; set; }

        public string Password { get; set; }

        public bool IsEncrypted { get; set; }

        public string Session { get; set; }

        public string Authority { get; set; }

        public bool Result { get; set; }

        public string ClientIp { get; set; }

        public int ClientPort { get; set; }

        public DateTime LoginTime { get; set; }

        public DateTime LiveTime { get; set; }

        public override string ToString()
        {
            return string.Format("{0},{1}", UserName, Password);
        }

        public void SetSuccess(string authority)
        {
            Authority = authority;
            Session = Guid.NewGuid().ToString();
            Result = true;
            LoginTime = DateTime.Now;
            LiveTime= DateTime.Now;
        }

        public LoginInfo()
        {

        }
    }

wcf.dll更新服务引用时会生成想要的类,因为除了webapi接口外,也提供了wcf接口,不如说我现在干的就是从wcf转到webapi。

结果发现类定位放到dll里面,json反序列化时就不行,数据拿不到,而直接在unity中创建相同的类定义,则可以反序列化。

想起了,这个在以前用websocket做webgl时,那时是用xml反序列化的,也是这样的,浪费了手下兄弟2天时间。

现在的处理方式是,把wcf.dllI里面的核心代码,Reference.cs拷贝到unity项目中(注意,还要拷贝System.ServiceModel.dll,而且这个dll不能是c#的,必须是unity的,在unity的editor下能找到)。

前面的WebApiClient里面去掉所有的业务相关的代码,应该说,移动到上层调用中,WebApiClient就是一个底层的通信类。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值