`
wyf
  • 浏览: 424685 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

在HTTP协议下使用JSON在flash和C# web程序之间通讯

阅读更多

先把文章中要用到一些扩展程序集贴出来。

C#用到了System.Web.Extensions程序集,包括3个文件:
System.Web.Extensions.dll
System.Web.Extensions.Design.dll
AJAXExtensionsToolbox.dll

Flash用到了adobe的corelib-.90程序集:
corelib.swc

网上现在有很多将flash与C# web 服务程序通讯的资料,不过很多都是用remoting或者web service的方式做的,而且很多高手还做了效率比较,结果是基于TCP协议的remoting效率最好,但是这里对remoting就不多说了,并且基于TCP的remoting因为协议不同效率差别肯定明显。我还是介绍在HTTP协议下的通讯方法吧。

这里使用iis作为服务器,服务程序只要能处理客户端提交的数据,能向客户端返回数据就行(当然push做不到,http协议嘛)。所以处理程序大多直接实现IHttpHandle接口,当然从Page继承是一点也没有问题的,因为Page类也实现了IHttpHandle接口,如何继承Page,如何实现IHttpHandle的接口方法就给个例子吧,这个资料挺多的。

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.SessionState;

namespace com.Flight.Script
{
    /// <summary>
    /// 脚本控制请求,IRequiresSessionState接口没有啥方法,纯粹为了session支持
    /// </summary>
    public class ScriptHandler : IHttpHandler, IRequiresSessionState
    {
        /// <summary>
        /// 处理脚本请求
        /// </summary>
        /// <param name="context">脚本名称</param>
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write("输出内容");
        }

        /// <summary>
        /// 是否允许后续请求处理
        /// </summary>
        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
}

这里提一下web.config配置,下面是一个例子,在这里例子里面我修改了扩展名“.do”,这样的配置要求修改iis服务器设置的,如果没有自己的服务器最好别这样做,比较麻烦,可以使用“ashx”或者“axd”都可以。

<httpHandlers>
  <add verb="*" path="chat.do" type="com.gs.chat.Chat, Game"/>
</httpHandlers>

下面是服务器上将对象进行JSON序列化的程序,其实JSON序列化就是将一个对象转换成有规律的字符串,能够被别人解读出来,但不是所有的对象都能被序列化,一定要实现了ISerializable接口的类才行,可以参考Hashtable类,这个类就实现了ISerializable接口中的GetObjectData方法,因此这个类型的对象进行反序列化是没有问题的。

using ...
using System.Web.Script.Serialization;
using ...

...
/// <summary>
/// 向客户端返回的数据
/// 默认采用json编码格式
/// </summary>
/// <param name="_result">服务器方法的方会对象</param>
/// <returns>返回字符串</returns>
public virtual string JsonResult(object _result)
{
    //返回的字符串
    string resultString = "";
    //采用了微软的序列化方式
    JavaScriptSerializer jss = new JavaScriptSerializer();
    resultString = jss.Serialize(_result);
    return resultString;
}

/// <summary>
/// 反序列化,从JSON字符串转换到对象
/// </summary>
/// <param name="_jsonstring">JSON串</param>
/// <returns>反序列化得到的对象</returns>
public virtual object JsonObject(string _jsonstring)
{
    JavaScriptSerializer jss = new JavaScriptSerializer();
    return jss.DeserializeObject(_jsonstring);
}
...

输出都是一样的,直接Write:

context.Response.Write(_text);

这里对于服务器的开发方法可以很多,比如在同一个IHttpHandle中可以写多个处理程序,分别处理不同的请求,然后有个专门的类负责分析要执行哪个方法。下面是发送和接收聊天消息的方法,供参考:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using com.Flight.Web.Ajax;
using System.Text.RegularExpressions;

namespace com.gs.chat
{
    public class Chat : AjaxController
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            AjaxJsBuilder.RegistType(typeof(Chat));
            StartProcess();
        }

        [SafeMethod("A")]
        [AjaxMethod()]
        public Hashtable SendMessage(string _msg)
        {
            string patternForCmd = @"-\|cmd:[a-zA-z]+\|-";
            Regex rg = new Regex(patternForCmd, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            Match m = rg.Match(_msg);

            if (m.Success)
            {
                string cmd = m.Value;
                if (cmd.ToLower().Equals("-|cmd:clear|-"))
                {
                    MessageContainer.MsgContainer.Clear();
                }
            }
            else
            {
                Message msg = new Message("me", "all", _msg, ToType.ALL);
                MessageContainer.MsgContainer.Add(msg);
            }
            Hashtable rht = new Hashtable();
            rht.Add("stat", "OK");
            rht.Add("msg", "发送成功。");
            return rht;
        }

        [SafeMethod("A")]
        [AjaxMethod()]
        public MessageContainer ReceiveMessage(string _u)
        {
            MessageContainer mc = new MessageContainer();
            foreach (Message msg in MessageContainer.MsgContainer)
            {
                if (msg.From.Equals(_u) || msg.To.Equals(_u))
                {
                    mc.Add(msg);
                }
            }

            return mc;
        }
    }
}

AjaxController这个类是自己写的,从page继承,用来做一些基本处理,比如JSON序列化啊,反序列化啊,安全检查啊,还有分析客户端要调用的方法之类,后面也会提到一些里面的具体设计。

下面看看客户端的开发,首先是向服务器发送请求,这个比较简单,直接贴一个简单例子,应该都明白

import flash.net.URLLoader;
import flash.net.URLRequest;

var request:URLRequest = new URLRequest(url);
var loader:URLLoader = new URLLoader();
var request_data:String = ajax_flag + "&" + method_flag + method + "&" + parameters;
request.data = request_data;
request.method = URLRequestMethod.POST;
loader.load(request);

主要是在loader的complete事件中处理的时候要注意把服务器返回的字符串进行JSON反序列化,转换成对象,代码如下:

import com.adobe.serialization.json.JSON; //导入使用的到类

在load_complete事件里面写如下代码:

//从事件对象想读取服务器返回的数据,反序列化为对象
var receiveMsg:Object = JSON.decode(event.target.data);

获取receiveMsg对象之后就可以通过点操作符访问属性数据了。以一个HashTable为例,其中的Key就是反序列化后对象的属性,Value就是属性值。

在C#中能够被直接序列化的容器对象很多,可以更具需要选择,如果都不能满足你的要求,也可以自己写一个对象,实现ISerializable接口的GetObjectData方法进行数据传输。

按照上面的实现思路,如果一个IHttpHandle只能处理一种请求那么我们就要写出很多很多的IHttpHandle这样就无法和webservice相提并论了,因为我们知道在webservice中一个service可以提供多个方法响应客户端的请求,这个其实只要我们稍作处理就可以了,比如上面的例子里面我们看到请求字符串中包含了一些特殊的参数:

ajax_flag + "&" + method_flag + method

可以很容易看出来,这里就是用来告诉服务器我要调用哪些方法的参数。

注意:服务器方法在响应请求之前还要做安全判断,这个判断很重要,否则随便就能调用服务器程序那岂不太危险?这里给出一个简单的解决方法,可以采用一个HttpModule做前端判断,如果已经登录,请求参数中没有特殊的符号(防止注入),并且有访问这个HttpHandle的权限那么继续,然后在HttpHandle中给指定的方法加个安全特性代码如下:

[SafeMethod("A")]
[AjaxMethod()]
public MessageContainer ReceiveMessage(string _u)
{
    MessageContainer mc = new MessageContainer();
    foreach (Message msg in MessageContainer.MsgContainer)
    {
        if (msg.From.Equals(_u) || msg.To.Equals(_u))
        {
            mc.Add(msg);
        }
    }

    return mc;
}

[AjaxMethod()]和[SafeMethod("A")]这两个特性说明ReceiveMessage方法是允许客户端调用的,并且用户具有特性A的时候才能执行这个方法,否则报错。

原文链接:http://bbs.actionscript3.cn/thread-23446-1-1.html
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics