How can I perform XSLT transformations in an HttpModule?

不问归期 提交于 2019-12-06 01:43:45

When you are done reading the data into your MemoryStream the position is at the end of the stream. Before sending the stream to the StreamReader/XmlReader you need to reset the position to 0.

stream.Position = 0;
/* or */
stream.Seek(0, SeekOrigin.Begin);

I'm a little surprised this works at all (even after resetting the stream's position). I poked around the HttpApplication code a bit, and though I don't fully understand it, it looks like you may be modifying the output stream too late in the request handling process.

If you still haven't figured this out, try attaching your second handler function to one of the events after PostReleaseRequestState - either UpdateRequestCache or PostUpdateRequestCache. Neither sounds especially suitable, but read on!

For some reason, the MSDN documentation for HttpApplication doesn't include PreSendRequestContent in its list of events, but Reflector shows that its handlers don't get called until HttpResponse.Flush.

If I'm reading the code right, Response.Flush calculates the content length before the handlers are called, so it thinks the response is empty when it gets to this code:

if (contentLength > 0L) {
    byte[] bytes = Encoding.ASCII.GetBytes(Convert.ToString(contentLength, 0x10) + "\r\n");
    this._wr.SendResponseFromMemory(bytes, bytes.Length);
    this._httpWriter.Send(this._wr);
    this._wr.SendResponseFromMemory(s_chunkSuffix, s_chunkSuffix.Length);
}

There are some alternate paths that may get called depending on your entry point and initial conditions, and that might explain why this works some of the time but not others. But at the end of the day you probably shouldn't be modifying the response stream once you're in Flush.

You're doing something a little unusual - you're not really filtering the response stream in the traditional sense (where you pass some bytes along to another stream), so you may have to do something a bit hackish to make your current design work.

An alternative would be to implement this using an IHttpHandler instead of a module - there's a good example here. It deals with transforming output from a database query, but should be easy to adapt to a file system data source.

Even if you don't stick to the msdn example you should implement HttpApplication.EndRequest:

context.EndRequest += (sender, e) => {
    HttpResponse response = HttpContext.Current.Response;
    response.Flush();
};

cleaner

// ...

public void Init(HttpApplication application)
{
    // ...
    application.EndRequest += (new EventHandler(this.Application_EndRequest));
}

private void Application_EndRequest(object sender, EventArgs e)
{
    HttpApplication application = (HttpApplication)source;
    HttpContext context = application.Context;
    context.Current.Response.Flush();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!