我正在构建一个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());
}
}
}
但闪存方面的响应处理程序没有被击中。
在<{3}}的响应 - &gt; 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
答案 0 :(得分:2)
诀窍是将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就删除它。
BTW,你真的需要在ASP.NET MVC中使用它吗?也许简单的ASHX处理程序就足够了,性能会更好,我不知道。 MVC架构是我认为的优点。
答案 1 :(得分:1)
我没有看到在网络上实施的ActionResult,但有FluorineFX.NET支持AMF。
答案 2 :(得分:1)
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);
}
}
}