AMF ActionResult для asp.net mvc - PullRequest
       18

AMF ActionResult для asp.net mvc

1 голос
/ 02 апреля 2012

Я создаю приложение MVC, которое будет взаимодействовать с Flash через AMF, кто-нибудь знает, есть ли в сети 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());
        }
    }
}

, но обработчик ответа на стороне флэш-памяти не получил удар.

in Charles на вкладке Response-> Amf. Я вижу эту ошибку:

Не удалось проанализировать данные (com.xk72.amf.AMFException: неподдерживаемый тип пакета AMF3 17 в 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

и вкладка Hex:

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            

Ответы [ 3 ]

2 голосов
/ 14 мая 2012

Хитрость заключается в том, чтобы использовать FluorineFx.IO.AMFMessage с AMFBody в качестве объекта результата и установить свойство Content.

Вы можете увидеть это в прокси Чарльза с другими рабочими примерами (я использовал отличный Примеры WebORB , в частности Flash Remoting Basic Invocation AS3 )

Я обновил AMFFilter для поддержки Response параметра, который необходим AMFBody.Возможно, это может быть решено более элегантно с помощью некоторого текущего кеша контекста, не знаю.

Код следует:

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.

BTWвам действительно нужно это в ASP.NET MVC?Может быть, достаточно простого обработчика ASHX и производительность будет лучше, я не знаю.Я предполагаю, что архитектура MVC - это плюс.

1 голос
/ 03 апреля 2012

AFAIK, нет никакой реализации AMF ActionResult, но вы можете создать свой собственный, используя класс FluorineFx.IO.AMFWriter из источников FluorineFx.NET

Рассмотрите возможность создания проекта с открытым исходным кодом где-нибудь (например,на 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);
        }
    }
}
1 голос
/ 03 апреля 2012

Я не видел ActionResult, реализованного в сети, но есть FluorineFX.NET , который поддерживает AMF.

...