【问题标题】:AMF ActionResult for asp.net mvcasp.net mvc 的 AMF ActionResult
【发布时间】:2012-04-02 10:02:53
【问题描述】:

我正在构建一个 mvc 应用程序,它将通过 AMF 与 flash 通信, 有人知道网络上是否有任何 AMF ActionResult 可用吗?

编辑

使用@mizi_sk 回答(但没有使用 IExternalizable)我做了这个 ActionResult:

public class AmfResult : ActionResult
{
    private readonly object _o;

    public AmfResult(object o)
    {
        _o = o;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "application/x-amf";
        using (var ms = new MemoryStream())
        {
            // write object
            var writer = new AMFWriter(ms);
            writer.WriteData(FluorineFx.ObjectEncoding.AMF3, _o);
            context.HttpContext.Response.BinaryWrite(ms.ToArray());
        }
    }
}

但闪存端的响应处理程序没有被命中。

Charles 的 Response->Amf 选项卡中,我看到了这个错误:

解析数据失败(com.xk72.amf.AMFException: Unsupported AMF3 packet type 17 at 1)

这是原始标签:

 HTTP/1.1 200 OK 
 Server: ASP.NET Development Server/10.0.0.0 
 Date: Mon, 14 May 2012 15:22:58 GMT 
 X-AspNet-Version: 4.0.30319
 X-AspNetMvc-Version: 3.0 
 Cache-Control: private 
 Content-Type:application/x-amf 
 Content-Length: 52 
 Connection: Close

  3/bingo.model.TestRequest param1coins name

和十六进制标签:

00000000  11 0a 33 2f 62 69 6e 67 6f 2e 6d 6f 64 65 6c 2e     3/bingo.model.
00000010  54 65 73 74 52 65 71 75 65 73 74 0d 70 61 72 61   TestRequest para
00000020  6d 31 0b 63 6f 69 6e 73 09 6e 61 6d 65 01 04 00   m1 coins name   
00000030  06 05 6a 6f                                         jo            

【问题讨论】:

    标签: asp.net-mvc flash amf actionresult


    【解决方案1】:

    诀窍是使用 FluorineFx.IO.AMFMessage 和 AMFBody 作为结果对象并设置 Content 属性。

    您可以在 Charles 代理中看到这一点以及其他工作示例(我使用了很棒的 WebORB examples,特别是 Flash remoting Basic Invocation AS3

    我已更新 AMFFilter 以支持 AMFbody 需要的 Response 参数。也许它可以通过一些当前的上下文缓存更优雅地解决,不知道。

    代码如下:

    public class AmfResult : ActionResult
    {
        private readonly object _o;
        private readonly string _response;
    
        public AmfResult(string response, object o)
        {
            _response = response;
            _o = o;
        }
    
        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.ContentType = "application/x-amf";
    
            var serializer = new AMFSerializer(context.HttpContext.Response.OutputStream);
            var amfMessage = new AMFMessage();
            var amfBody = new AMFBody();
            amfBody.Target = _response + "/onResult";
            amfBody.Content = _o;
            amfBody.Response = "";
            amfMessage.AddBody(amfBody);
            serializer.WriteMessage(amfMessage);
        }
    }
    

    为此,您需要使用 AMFFilter 装饰控制器上的方法

    public class AMFFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.ContentType == "application/x-amf")
            {
                var stream = filterContext.HttpContext.Request.InputStream;
    
                var deserializer = new AMFDeserializer(stream);
                var message = deserializer.ReadAMFMessage();
    
                var body = message.Bodies.First();
                filterContext.ActionParameters["target"] = body.Target;
                filterContext.ActionParameters["args"] = body.Content;
                filterContext.ActionParameters["response"] = body.Response;
    
                base.OnActionExecuting(filterContext);
            }
        }
    }
    

    看起来像这样

    [AMFFilter]
    [HttpPost]
    public ActionResult Index(string target, string response, object[] args)
    {
        // assume target == "TestMethod" and args[0] is a String
        var message = Convert.ToString(args[0]);
        return new AmfResult(response, "Echo " + message);
    }
    

    客户端代码供参考

    //Connect the NetConnection object
    var netConnection: NetConnection = new NetConnection();
    netConnection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
    netConnection.connect("http://localhost:27165/Home/Index");
    
    //Invoke a call
    var responder : Responder = new Responder( handleRemoteCallResult, handleRemoteCallFault);
    netConnection.call('TestMethod', responder, "Test");
    
    private function onNetStatus(event:NetStatusEvent):void {
        log(ObjectUtil.toString(event.info));
    }
    
    private function handleRemoteCallFault(...args):void {
        log(ObjectUtil.toString(args));
    }
    
    private function handleRemoteCallResult(message:String):void {
        log(message);
    }
    
    private static function log(s:String):void {
        trace(s);
    }
    

    如果您想返回故障,只需在 AMFResult 中更改此行

    amfBody.Target = _response + "/onFault";
    

    我喜欢 ObjectUtil.toString() 格式,但如果您没有链接 Flex,只需将其删除。

    顺便说一句,在 ASP.NET MVC 中你真的需要这个吗?也许简单的 ASHX 处理程序就足够了,性能会更好,我不知道。我认为 MVC 架构是一个优点。

    【讨论】:

    • 必须等待 5 小时才能获得赏金
    • 不知道,没用过ashx,用了很多asp.net mvc
    • @ChuckNorris 我也不知道。也许我会把它作为一个问题发布,我也很感兴趣(使用二进制 AMF 时处理程序与完整 MVC 的性能/架构优势)
    • 如果您这样做,请在此处发布问题的链接
    【解决方案2】:

    我还没有看到在网络上实现的 ActionResult,但有支持 AMF 的 FluorineFX.NET

    【讨论】:

    • 你知道哪个班会这样吗?我只需要传递一个对象并取回我将放入输出流中的字符串
    【解决方案3】:

    AFAIK 没有 AMF ActionResult 的任何实现,但您可以使用来自 FluorineFx.NET sources 的类 FluorineFx.IO.AMFWriter 创建自己的

    考虑在某处创建一个开源项目(例如在 github 上)

    编辑 1 - 示例

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using FluorineFx.IO;
    using System.IO;
    using FluorineFx.AMF3;
    using System.Diagnostics;
    
    namespace AMF_SerializationTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                var ms = new MemoryStream();
    
                // write object
                var writer = new AMFWriter(ms);
                writer.WriteData(FluorineFx.ObjectEncoding.AMF3, new CustomObject());
    
                Debug.Assert(ms.Length > 0);
    
                // rewind
                ms.Position = 0;
    
                // read object
                var reader = new AMFReader(ms);
                var o = (CustomObject)reader.ReadData();
    
                // test
                Debug.Assert(o.I == 3);
                Debug.Assert(o.S == "Hello");
            }
        }   
    
        public class CustomObject : IExternalizable
        {
            private int i = 3;
    
            public int I
            {
                get { return i; }
            }
    
            private string s = "Hello";
    
            public string S
            {
                get { return s; }
            }
    
            public void ReadExternal(IDataInput input)
            {
                i = input.ReadInt();
                s = input.ReadUTF();
            }
    
            public void WriteExternal(IDataOutput output)
            {
                output.WriteInt(i);
                output.WriteUTF(s);
            }
        }
    }
    

    【讨论】:

    • 我取得了一些进展但卡住了,我已经更新了我的问题,请你看看
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多