SilverLight企业应用框架设计【五】客户端调用服务端(使用JSON传递数据,自己实现RESTful Web服务)

来个索引

SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)

SilverLight企业应用框架设计【三】服务端设计

SilverLight企业应用框架设计【二】框架画面

SilverLight企业应用框架设计【一】整体说明

 

在上一节中讲到的自动生成的服务代理类核心代码,如下

        public event ServiceEventHandler Completed;
        public void GetAllMenu()
        {
            var si = new ServiceInvoker();
            si.Completed += new ServiceEventHandler(si_Completed);
            si.PrepareInvoke("MenuService", "GetAllMenu", typeof(List<MenuM>));
            si.InvokeService();
        }
        void si_Completed(object sender, ServiceEventArgs e)
        {
            Completed(sender, e);
        }

大家注意到我们是通过ServiceInvoker来调用服务的

实例化ServiceInvoker类之后就注册了ServiceEventHandler事件

此事件是服务调用完成后触发的事件(silverlight 原生的ria service也有一个completed事件)

该事件相关代码如下

    public class ServiceEventArgs : EventArgs
    {
        //服务方法的返回值
        public object Result { get; set; }
    }
    public delegate void ServiceEventHandler(object sender, ServiceEventArgs e);

在si.PrepareInvoke把需要调用的服务类名,方法名,返回值类型(如果有参数,这里还会自动加入参数)

PrepareInvoke方法如下

        public void PrepareInvoke(string ClassName,string MethodName,Type ResultType,params object[] objs)
        {
            className = ClassName;
            methodName = MethodName;
            resultType = ResultType;
            MemoryStream ms = new MemoryStream();
            var sb = new StringBuilder();
            for(int i=0;i<objs.Length;i++)
            {
                var jsonSerializer = new DataContractJsonSerializer(objs[i].GetType());
                jsonSerializer.WriteObject(ms, objs[i]);
                var objStr = Encoding.UTF8.GetString(ms.ToArray(), 0, (int)ms.Length);
                ms.Position = 0;
                sb.AppendFormat("p{0}=", i);
                sb.AppendFormat("{0}", objStr);
                sb.Append("&");
            }
            ms.Close();
            paramStr = sb.ToString();
        }

在此方法中主要是记录下这些信息,

另外把服务需要传入的参数序列化成JSON字符串

紧接着就调用InvokeService方法

代码如下

        public void InvokeService()
        {
            Uri serviceUri = new Uri("http://localhost/RTMDemo.Host/RTMDemo.Host.WCF.MenuService");
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceUri);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            var requestResult = request.BeginGetRequestStream(new AsyncCallback(RequestReady), request);
            return;
        }

明眼人一看就明了了

其实就是使用HTTPWebRequest来调用服务(服务端我们托管了HttpHandler的请求

RequestReady事件如下:

        void RequestReady(IAsyncResult asyncResult)
        {
            HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest;
            Stream stream = request.EndGetRequestStream(asyncResult);
            Deployment.Current.Dispatcher.BeginInvoke(delegate()
            {
                StreamWriter writer = new StreamWriter(stream);
                writer.Write(paramStr);
                writer.Write("MethodKey=RTMDemo.Host.WCF.{0}.{1}&", className,methodName);
                writer.Flush();
                writer.Close();
                request.BeginGetResponse(new AsyncCallback(ResponseReady), request);
            });
        }

在此事件中我们把服务类名方法名和参数写入了请求流

ResponseReady事件如下

        void ResponseReady(IAsyncResult asyncResult)
        {
            HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
            Deployment.Current.Dispatcher.BeginInvoke(delegate()
            {
                Stream responseStream = response.GetResponseStream();
                if (resultType == null)
                {
                    Completed(this, null);
                    return;
                }
                try
                {
                    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(resultType);
                    result = jsonSerializer.ReadObject(responseStream);
                }
                catch
                {
                }
                var se = new ServiceEventArgs();
                se.Result = result;
                Completed(this, se);
            });
        }

这个事件把服务端返回的结果(JSON数据)反序列化成实体类型,并赋值给ServiceEventArgs

然后触发了Completed事件

也就是触发我们服务端代理类的si_Completed事件

至此,调用服务端的类就解释完了

下面我们看看是怎么调用服务端的

        private void InitMenu()
        {
            var ms = new MenuService();
            ms.Completed += new ServiceEventHandler((o, re) =>
            {
                var AllMenu = re.Result as List<MenuM>;
                Common.ViewUtility.AllMenu = AllMenu;
                InitTopMenu();
            });
            ms.GetAllMenu();
        }

看看是不是与ria service调用的方法有点像呢?

…………………………………………………………………………喜欢的话……………请推荐吧………………………………………………………

估计再写一篇就完结了

下一篇公布源码

时间: 2024-08-16 00:09:50

SilverLight企业应用框架设计【五】客户端调用服务端(使用JSON传递数据,自己实现RESTful Web服务)的相关文章

Silverlight企业应用框架设计【六】自定义系统菜单(使用自己的DataForm)

索引 SilverLight企业应用框架设计[五]客户端调用服务端(使用JSON传递数据,自己实现RESTful Web服务) SilverLight企业应用框架设计[四]实体层设计+为客户端动态生成服务代理(自己实现RiaService) SilverLight企业应用框架设计[三]服务端设计 SilverLight企业应用框架设计[二]框架画面 SilverLight企业应用框架设计[一]整体说明   首先我们设计的窗体如下 xaml代码如下: <location:BasePage x:Cl

SilverLight企业应用框架设计【一】整体说明

Silverlight企业应用框架设计[六]自定义系统菜单(使用自己的DataForm) SilverLight企业应用框架设计[五]客户端调用服务端(使用JSON传递数据,自己实现RESTful Web服务) SilverLight企业应用框架设计[四]实体层设计+为客户端动态生成服务代理(自己实现RiaService) SilverLight企业应用框架设计[三]服务端设计 SilverLight企业应用框架设计[二]框架画面 SilverLight企业应用框架设计[一]整体说明 闲言碎语~

SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)

题外话: 对不住各位,本打算年前把这个系列写完,结果由于杂务缠身一直推到年后 我特别痛恨我自己!我觉得不但对不起各位!也对不起自己. 最近烦躁不安,不能专心向学.也不知道如何是好. -- 好吧,言归正传 说个前提条件: 此项目虽然使用了silverlight 4.0 但是服务端只能在dotNet3.5下运行 这也是我们为什么自己实现riaService的原因 实体层设计 由于有这个限制条件,我们设计的实体层也有所区别 如下图为实体层的程序集(只有MenuM实体类,其他实体类未加入.) 下面来看一

SilverLight企业应用框架设计【二】框架画面

框架画面分为上中下三层 由下面一个Grid控件完成布局 <Grid x:Name="LayoutRoot"> <Grid.RowDefinitions> <RowDefinition Height="60"></RowDefinition> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height=

SilverLight企业应用框架设计【三】服务端设计

一:缓存服务类型与方法 客户端请求的时候 为了方便的知道请求的类型与类型所包含的方法 我们把服务类型和方法缓存到静态字典中了 代码如下 public class WCFRouteTable { static Dictionary<string, Type> routeService; static Dictionary<string, MethodInfo> routeMethods; static WCFRouteTable() { routeService = new Dict

WinForm企业应用框架设计【五】系统登录以及身份验证+源码

索引 WinForm企业应用框架设计[一]界限划分与动态创建WCF服务(no svc!no serviceActivations!) WinForm企业应用框架设计[二]团队内部的约定和客户端按约定识别WCF服务 WinForm企业应用框架设计[三]框架窗体设计:动态创建菜单: WinForm企业应用框架设计[四]动态创建业务窗体 WinForm企业应用框架设计[五]系统登录以及身份验证+源码 闲话休提~ 一:登录的画面与客户端逻辑 为了在打开程序的时候先弹出登录窗体 我们修改了主窗体的构造函数

WinForm企业应用框架设计【一】界限划分与动态创建WCF服务(no svc!no serviceActivations!)

WinForm企业应用框架设计[一]界限划分与动态创建WCF服务(no svc!no serviceActivations!) WinForm企业应用框架设计[二]团队内部的约定和客户端按约定识别WCF服务 WinForm企业应用框架设计[三]框架窗体设计:动态创建菜单: WinForm企业应用框架设计[四]动态创建业务窗体 WinForm企业应用框架设计[五]系统登录以及身份验证+源码 先来张图片!我们这个系列就是要做一个这样的框架!    我曾写过几个"系列"的东西,如 PL/SQ

java-关于多个不同的Ip客户端调用同一个webservice方法,服务端进行用户会话数据区分

问题描述 关于多个不同的Ip客户端调用同一个webservice方法,服务端进行用户会话数据区分 目前在写一个webservice供外部进行调用,由于要进行身份的验证,所以我在webservice的服务端加如了拦截器(客户将自己的信息写在soapHead消息中),然后在拦截器中取出soapHead中的消息,进行数据库用户信息的验证,验证通过之后才运行进行相关接口的调用.问题是在拦截器验证通过后,我要在调用的webservice接口方法中,?用到用户的身份信息去取其他相关数据.该怎么做呢? 开始我

分享一个Android和java调用RESTful Web服务的利器Resting

分享一个Android和java调用RESTful Web服务的利器Resting   当我们调用Web服务,往往是最终目标是取HTTP响应,将其转化为将在应用中呈现的值对象.Resting可以用来实现这一功能.Resting,在Java的一个轻量级的REST框架,可用于调用一个RESTful Web服务,并转换成响应来自客户端应用程序定制的Java对象.由于它的简单,resting是适合Android等手持设备.   resting目标•暴露简单的get(),post(),put()和dele