版本2
我更新了原始代码,考虑到write方法以块的形式从页面流式传输HTML。
正如指出的“由于无法保证在write中连续写入“THE_PLACEHOLDER”。你可能会在一次write调用的末尾得到“THE_PLACEH”,并在下一次调用的开头得到“OLDER”。
我通过将流的完整内容放入Stringbuilder中,并在Close方法上执行任何所需的更新来解决了这个问题。
这样做后,我再次提出以下问题....
我正在开发一个CMS,它只是用CMS文本替换占位符。
我有以下代码,它的功能正常。
我已经重写了IHttpModule。
public class CmsFilterHttpModule : IHttpModule {
// In the Init method, register HttpApplication events by adding event handlers.
public void Init( HttpApplication httpApplication ) {
httpApplication.ReleaseRequestState += new EventHandler( this.HttpApplication_OnReleaseRequestState );
}
/// <summary>
/// HttpApplication_OnReleaseRequestState event handler.
///
/// Occurs after ASP.NET finishes executing all request event handlers.
/// This event causes state modules to save the current state data.
/// </summary>
private void HttpApplication_OnReleaseRequestState( Object sender, EventArgs e ) {
HttpResponse httpResponse = HttpContext.Current.Response;
if ( httpResponse.ContentType == "text/html" ) {
httpResponse.Filter = new CmsFilterStream( httpResponse.Filter );
}
}
public void Dispose() {
//Empty
}
}
以及MemoryStream
public class CmsFilterStream : MemoryStream {
private Stream _responseStream;
private StringBuilder _responseHtml;
public CmsFilterStream( Stream inputStream ) {
_responseStream = inputStream;
_responseHtml = new StringBuilder();
}
/// <summary>
/// Writes a block of bytes to the current stream using data read from a buffer.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
/// <param name="count">The maximum number of bytes to write.</param>
public override void Write( Byte[] buffer, Int32 offset, Int32 count ) {
if ( buffer == null ) { throw new ArgumentNullException( "buffer", "ArgumentNull_Buffer" ); }
if ( offset < 0 ) { throw new ArgumentOutOfRangeException( "offset", "ArgumentOutOfRange_NeedNonNegNum" ); }
if ( count < 0 ) { throw new ArgumentOutOfRangeException( "count", "ArgumentOutOfRange_NeedNonNegNum" ); }
if ( buffer.Length - offset < count ) { throw new ArgumentException( "Argument_InvalidOffLen" ); }
String bufferContent = UTF8Encoding.UTF8.GetString( buffer, offset, count );
_responseHtml.Append( bufferContent );
}
public override void Close() {
_responseHtml.Replace( "THE_PLACEHOLDER", "SOME_HTML" );
_responseStream.Write( UTF8Encoding.UTF8.GetBytes( _responseHtml.ToString() ), 0, UTF8Encoding.UTF8.GetByteCount( _responseHtml.ToString() ) );
_responseStream.Dispose();
base.Close();
}
}
并且在 Web.config 文件中添加以下内容
<system.webServer>
<modules>
<remove name="CmsFilterHttpModule" />
<add name="CmsFilterHttpModule" type="{MY_NAMESPACE}.CmsFilterHttpModule" />
</modules>
</system.webServer>
这符合我的要求。
我的问题是,在开始向后工作之前,这是最佳的管道位置吗?
此方法将替换已完成的输出中的文本。
我正在寻找从管道角度最快的替换此文本的方法。
暂时忽略String.Replace / Stringbuilder和其他各种方法的速度优化。我认为优化稍微往后进行。
我尚未完全调试整个管道,但我猜测页面必须由不同的部分(即布局、视图部分等)构建。也许在这些部分替换文本更快。
此外,是否会出现任何问题?
String bufferContent = UTF8Encoding.UTF8.GetString(buffer);
当使用其他语言,如日语、中文等时。
我还必须说明,我正在尝试将此作为一个单独的附加代码来实现,尽可能少地触及用户站点MVC代码。