2012-04-02 3 views
1

Я создаю приложение mvc, которое будет связываться со вспышкой через AMF, Кто-нибудь знает, есть ли AMF ActionResult доступен в Интернете?AMF ActionResult для asp.net mvc

EDIT:

используя @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 Я вижу эту ошибку:

Failed to parse data (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 

и вкладка 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    

ответ

2

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

Вы можете увидеть это в Чарльз прокси с другими рабочими примерами (я использовал большой WebORB examples, в частности 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); 
} 

Client боковой код для справки

//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 является плюсом, который я предполагаю.

+0

должен ждать 5 часов, чтобы наградить награду – Omu

+0

не знаю, никогда не использовал ashx, я использовал много asp.net mvc – Omu

+0

@ ЧакНоррис меня тоже. возможно, я отправлю его как вопрос, мне также интересно (производительность/архитектурные преимущества обработчика против полного MVC при использовании двоичного AMF) –

1

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

+0

Знаете ли вы, какой класс это делает? все, что мне нужно, это передать ему объект и вернуть строку, которую я поставлю в выходной поток. – Omu

1

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

Рассмотрим создание проекта с открытым исходным кодом где-нибудь (например, на GitHub)

EDIT 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); 
     } 
    } 
} 
+0

У вас есть пример кода, который показывает, как его использовать. – Omu

+0

Я обновил ответ с помощью примерного кода. –

+0

Я сделал некоторый прогресс, но застрял, я обновил свой вопрос, не могли бы вы взглянуть? – Omu

Смежные вопросы