【问题标题】:Accessing encoded stream in OpenRasta在 OpenRasta 中访问编码流
【发布时间】:2012-05-01 00:23:33
【问题描述】:

在将编码流发送到客户端之前,我需要访问 OpenRasta 中的编码流。我曾尝试使用 PipelineContributor 并在 KnownStages.IEnd 之前注册它,在 KnownStages.IOperationExecution 之后和 KnownStages.AfterResponseConding 之后尝试过,但在所有情况下 context.Response.Entity 流为空或空。

有人知道我该怎么做吗?

我还想尽早找出请求的编解码器,但当我在 KnowStages.ICodecRequestSelection 之后注册时,它返回 null。我只是觉得我错过了这些管道贡献者的一些东西。

【问题讨论】:

    标签: openrasta


    【解决方案1】:

    如果不编写自己的Codec(顺便说一句,这真的很容易),我不知道有一种方法可以将实际的字节流发送到浏览器。我这样做的方式是在IResponseCoding 已知阶段之前序列化ICommunicationContext.Response.Entity。伪代码:

    class ResponseLogger : IPipelineContributor
    {
        public void Initialize(IPipeline pipelineRunner)
        {            
            pipelineRunner
                .Notify(LogResponse)
                .Before<KnownStages.IResponseCoding>();
        }
    
        PipelineContinuation LogResponse(ICommunicationContext context)
        {
            string content = Serialize(context.Response.Entity);
    
        }
    
        string Serialize(IHttpEntity entity)
        {
            if ((entity == null) || (entity.Instance == null))
                return String.Empty;
    
            try
            {
                using (var writer = new StringWriter())
                {
                    using (var xmlWriter = XmlWriter.Create(writer))
                    {
                        Type entityType = entity.Instance.GetType();
                        XmlSerializer serializer = new XmlSerializer(entityType);
                        serializer.Serialize(xmlWriter, entity.Instance);
                    }
    
                    return writer.ToString();
                }
            }
            catch (Exception exception)
            {
                return exception.ToString();
            }
        }
    }
    

    这个ResponseLogger是按照通常的方式注册的:

    ResourceSpace.Uses.PipelineContributor<ResponseLogger>();
    

    如前所述,这不一定为您提供发送到浏览器的确切字节流,但它足以满足我的需求,因为发送到浏览器的字节流基本上只是相同的序列化实体。

    通过编写自己的编解码器,您可以使用不超过 100 行的代码来利用 IMediaTypeWriter.WriteTo() 方法,我猜这是将字节传输到云端之前的最后一道防线。在其中,您基本上只需执行以下简单操作:

    public void WriteTo(object entity, IHttpEntity response, string[] parameters)
    {
        using (var writer = XmlWriter.Create(response.Stream))
        {
            XmlSerializer serializer = new XmlSerializer(entity.GetType());
            serializer.Serialize(writer, entity);
        }
    }
    

    如果您不是直接写入IHttpEntity.Stream 而是写入StringWriter 并在其上执行ToString(),您将拥有序列化实体,您可以在写入之前记录并执行任何您想做的事情输出流。

    虽然上述所有示例代码均基于 XML 序列化和反序列化,但无论您的应用程序使用何种格式,都应遵循相同的原则。

    【讨论】:

    • 是否可以链接编解码器?我需要在内容被任何合适的编解码器编码后抓取内容,例如RSS 或原子
    • 另外不幸的是,我的实体不可序列化,而且制作它们可能需要做太多的工作。认为我可能不得不使用一个单独的 HTTP 模块 :( 讨厌但会工作
    • 创建一个新的编解码器,为您的媒体类型注册它并从那里调用现有的编解码器,然后拦截http流非常容易。
    猜你喜欢
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    相关资源
    最近更新 更多