HttpResponse的Output与OutputStream、Filter关系与区别
在网上经常看见有这样的代码
HttpResponse response = HttpContext.Current.Response;
response.Filter = new PageFilter(response.Filter);
来拦截输出流,自己也做个类似的东东,如asp.net中 js 合并 压缩,现在我也来说说这几个东东是什么吧,需要大家对asp.net的生命周期比较熟悉,如不熟悉的朋友建议先看看ASP.NET 请求处理流程 ASP.NET管线与应用程序生命周期
首先我们来看看这3个属性的源代码吧:
public TextWriter Output { get { return this ._writer; } set { this ._writer = value; } } public Stream OutputStream { get { if (! this .UsingHttpWriter) { throw new HttpException(SR.GetString( "OutputStream_NotAvail" )); } return this ._httpWriter.OutputStream; } } public Stream Filter { get { if ( this .UsingHttpWriter) { return this ._httpWriter.GetCurrentFilter(); } return null ; } set { if (! this .UsingHttpWriter) { throw new HttpException(SR.GetString( "Filtering_not_allowed" )); } this ._httpWriter.InstallFilter(value); IIS7WorkerRequest request = this ._wr as IIS7WorkerRequest; if (request != null ) { request.ResponseFilterInstalled(); } } } |
我们看到Filter和OutputStream都用到了一个属性UsingHttpWriter,那这个属性是怎么定义的了
private bool UsingHttpWriter { get { return (( this ._httpWriter != null ) && ( this ._writer == this ._httpWriter)); } } |
从这个属性我们可以知道_writer 、_httpWriter实际上是同一个东东,它们的类型是HttpWriter ,而HttpWriter 又继承与TextWriter。现在我们可以解释Output就是_httpWriter,而OutputStream是_httpWriter的OutputStream属性。类HttpWriter 主要代码如下
public Stream OutputStream { get { return this ._stream; } } internal HttpWriter(HttpResponse response) : base ( null ) { this ._response = response; this ._stream = new HttpResponseStream( this ); this ._buffers = new ArrayList(); this ._lastBuffer = null ; this ._charBuffer = ( char []) s_Allocator.GetBuffer(); this ._charBufferLength = this ._charBuffer.Length; this ._charBufferFree = this ._charBufferLength; this .UpdateResponseBuffering(); } internal HttpResponseStream(HttpWriter writer) { this ._writer = writer; } |
HttpResponse 在Filter属性设置调用了HttpWriter类的InstallFilter方法,而获取调用了该类的GetCurrentFilter
internal void InstallFilter(Stream filter) { if ( this ._filterSink == null ) { throw new HttpException(SR.GetString( "Invalid_response_filter" )); } this ._installedFilter = filter; } internal Stream GetCurrentFilter() { if ( this ._installedFilter != null ) { return this ._installedFilter; } if ( this ._filterSink == null ) { this ._filterSink = new HttpResponseStreamFilterSink( this ); } return this ._filterSink; } |
由以上代码我们可以得知HttpResponse的输出流就是Filter属性设置的流,即HttpResponse的Output和OutputStream属性的输出流都是来自Filter中的流。我们来看看_writer 、_httpWriter它们是在什么时候初始化的了?在HttpResonse中有一个方法
internal void InitResponseWriter()
{
if (this._httpWriter == null)
{
this._httpWriter = new HttpWriter(this);
this._writer = this._httpWriter;
}
}
该方法是由HttpRuntime的ProcessRequestInternal来调用
private void ProcessRequestInternal(HttpWorkerRequest wr) { HttpContext context; try { context = new HttpContext(wr, false ); } catch { wr.SendStatus(400, "Bad Request" ); wr.SendKnownResponseHeader(12, "text/html; charset=utf-8" ); byte [] bytes = Encoding.ASCII.GetBytes( "<html><body>Bad Request</body></html>" ); wr.SendResponseFromMemory(bytes, bytes.Length); wr.FlushResponse( true ); wr.EndOfRequest(); return ; } wr.SetEndOfSendNotification( this ._asyncEndOfSendCallback, context); Interlocked.Increment( ref this ._activeRequestCount); HostingEnvironment.IncrementBusyCount(); try { try { this .EnsureFirstRequestInit(context); } catch { if (!context.Request.IsDebuggingRequest) { throw ; } } context.Response.InitResponseWriter(); IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); if (applicationInstance == null ) { throw new HttpException(SR.GetString( "Unable_create_app_object" )); } if (EtwTrace.IsTraceEnabled(5, 1)) { EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, applicationInstance.GetType().FullName, "Start" ); } if (applicationInstance is IHttpAsyncHandler) { IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance; context.AsyncAppHandler = handler2; handler2.BeginProcessRequest(context, this ._handlerCompletionCallback, context); } else { applicationInstance.ProcessRequest(context); this .FinishRequest(context.WorkerRequest, context, null ); } } catch (Exception exception) { context.Response.InitResponseWriter(); this .FinishRequest(wr, context, exception); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构