Json HTTP模块流问题

I have an HTTP Module that I use to clean up the JSON returned by my web service (see http://www.codeproject.com/KB/webservices/ASPNET_JSONP.aspx?msg=3400287#xx3400287xx for an example of this.) Basically it relates to calling cross-domain JSON web services from javascript.

There is this JsonHttpModule which uses a JsonResponseFilter Stream class to write out the JSON and the overloaded Write method is supposed to wrap the name of the callback function around the JSON, otherwise the JSON errors out as needing a label. However, if the JSON is really long, the Write method in the Stream class is called multiple times, causing the callback function to incorrectly get inserted midway through the JSON. Is there a way in the Stream class to wrap the callback function around the stream at the end or to specify that it write all of the JSON in 1 Write method instead of in chunks??

Here's where it calls the JsonResponseFilter in the JsonHttpModule:

public void OnReleaseRequestState(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;

            if (!_Apply(app.Context.Request)) return;

            // apply response filter to conform to JSONP
            app.Context.Response.Filter =
                new JsonResponseFilter(app.Context.Response.Filter, app.Context);
        }

Here's the Write method in the JsonResponseFilter Stream class that gets called multiple times:

public override void Write(byte[] buffer, int offset, int count)
        {
            var b1 = Encoding.UTF8.GetBytes(_context.Request.Params["callback"] + "(");
            _responseStream.Write(b1, 0, b1.Length);

            _responseStream.Write(buffer, offset, count);

            var b2 = Encoding.UTF8.GetBytes(");");
            _responseStream.Write(b2, 0, b2.Length);
        }

Thanks for any help! Justin

The reason it fires the method multiple times is because it will buffer the contents and then send it to the output stream. Here is an example which shows how to create ViewState mover HttpModule. You can get some idea from the implementation. Scroll down to the bottom and see the result.

http://www.highoncoding.com/Articles/464_Filtering_Responses_Using_ASP_NET_Response_Filters.aspx

Another solution is to write ResponseStream in Flush method. Like in this example.

I modified JsonHttpModules Flush method and used StringBuilder to store stream in Write method like Justin.

    /// <summary>
    /// Override flush by writing out the cached stream data
    /// </summary>
    public override void Flush()
    {

        if (_sb.Length > 0)
        {
            string message = _context.Request.Params["callback"] + "(" + _sb.ToString() + ");";
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(message);
            _responseStream.Write(buffer, 0, buffer.Length);
        }

        // default flush behavior
        _responseStream.Flush();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        string json = System.Text.Encoding.UTF8.GetString(buffer, offset, count);
        _sb.Append(json);
    }

This way you don't have to try to guess the end of incoming stream.