Is Response.End() considered harmful?
这篇知识库文章说ASP.NET的
反射镜显示如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public void End() { if (this._context.IsInCancellablePeriod) { InternalSecurityPermissions.ControlThread.Assert(); Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false)); } else if (!this._flushing) { this.Flush(); this._ended = true; if (this._context.ApplicationInstance != null) { this._context.ApplicationInstance.CompleteRequest(); } } } |
这对我来说很严厉。正如知识库文章所说,在
这让我想知道我是否应该总是避免使用
有人能建议我什么时候用
参考:里克·斯特拉尔的博客。
根据我收到的输入,我的回答是,是的,
- 使用
Response.End() 作为不可阻挡的投掷,在特殊情况下立即终止HttpResponse 。也可以在调试期间使用。避免Response.End() 完成常规响应。 - 使用
Response.Close() 立即关闭与客户机的连接。根据此msdn博客文章,此方法不适用于正常的HTTP请求处理。您不太可能有充分的理由调用此方法。 - 使用
CompleteRequest() 结束正常请求。CompleteRequest 导致ASP.NET管道在当前HttpApplication 事件完成后跳转到EndRequest 事件。因此,如果您打电话给CompleteRequest ,然后在响应中再写一些东西,那么写操作将被发送到客户机。
编辑-2011年4月13日
这里可以更清楚地看到:-在msdn博客上发表有用的文章-乔恩·里德的有用分析
DR
Initially I had recommended that you should simply replace all of your calls to
[Response.End] with [...] CompleteRequest() calls, but if you want to avoid
postback processing and html rendering you'll need to add [...] overrides as
well.Jon Reid,"Final Analysis"
根据msdn、jon reid和alain renon:ASP.NET性能-异常管理-编写避免异常的代码
The Server.Transfer, Response.Redirect, Response.End methods all raise
exceptions. Each of these methods internally call Response.End. The call to
Response.End, in turn, causes a ThreadAbortException exception.
三钠硼溶出液
HttpApplication.CompleteRequest() sets a variable that causes the thread to
skip past most of the events in the HttpApplication event pipeline [--] not the
Page event chain but the Application event chain....
create a class level variable that flags if the Page should terminate and then
check the variable prior to processing your events or rendering your page. [...]
I would recommend just overriding the RaisePostBackEvent and Render methods
response.end和response.close不用于正常的请求处理,当性能很重要。反应。结束是一种方便,笨手笨脚的方式以相关的性能惩罚终止请求处理。response.close用于在IIS/套接字处立即终止HTTP响应水平,并导致像keepalive这样的问题。
结束ASP.NET请求的建议方法是httpapplication.completeRequest。请记住,ASP.NET呈现将由于httpapplication.completeRequest跳过了IIS/ASP.NET应用程序管道,而不是ASP.NET页管道(即应用程序管道中的一个阶段)。
代码版权?2001-2007,我能说的最好的C6软件公司。
参考文献httpapplication.completeRequestCauses ASP.NET to bypass all events and filtering in the HTTP pipeline chain of
execution and directly execute the EndRequest event.
响应结束
This method is provided only for compatibility with ASP—that is, for
compatibility with COM-based Web-programming technology that preceded
ASP.NET.preceded ASP.NET. [Emphasis added]
响应关闭
This method terminates the connection to the client in an abrupt manner and is
not intended for normal HTTP request processing. [Emphasis added]
这个问题出现在所有Google搜索的顶部,查找response.end上的信息,因此对于其他搜索,比如我自己,希望发布csv/xml/pdf等,以响应事件而不呈现整个aspx页面,这就是我的方法。(覆盖渲染方法对于如此简单的任务IMO来说过于复杂)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // Add headers for a csv file or whatever Response.ContentType ="text/csv" Response.AddHeader("Content-Disposition","attachment;filename=report.csv") Response.AddHeader("Pragma","no-cache") Response.AddHeader("Cache-Control","no-cache") // Write the data as binary from a unicode string Dim buffer As Byte() buffer = System.Text.Encoding.Unicode.GetBytes(csv) Response.BinaryWrite(buffer) // Sends the response buffer Response.Flush() // Prevents any other content from being sent to the browser Response.SuppressContent = True // Directs the thread to finish, bypassing additional processing HttpContext.Current.ApplicationInstance.CompleteRequest() |
如果你在你的应用程序上使用了异常记录器,那么这些良性的
我只会使用
关于"我仍然不知道response.close和completeRequest()之间的区别",我会说:
不要使用response.close(),请不要使用completeRequest()。
请参阅下面的文章,了解这个案例的一个很好的总结。
请注意,即使在调用completeRequest()之后,一些文本(例如,从ASPX代码中删除的文本)也会附加到响应输出流中。您可以通过重写render和raisePostbackEvent方法来防止它,如下面的文章中所述。
btw:我同意阻止使用response.end(),特别是在向HTTP流写入数据以模拟文件下载时。我们以前使用过response.end(),直到日志文件中充满了threadabortexception。
我不同意"response.end是有害的"的说法。这绝对不是有害的。end按照它所说的做;它结束页面的执行。使用Reflector查看它是如何实现的,应该只被视为具有指导意义。
我的2客户建议
避免使用
如果您需要停止执行请求并注意(通常)*没有代码会超过这一点,请使用
*
ThreadAbortException is a special exception that can be caught, but
it will automatically be raised again at the end of the catch block.
要了解如何编写必须处理ThreadAbortException的代码,请参见@Mehrdad的回复,以便我如何在finally块中检测ThreadAbortException,该块引用RuntimeHelpers.ExecuteDeweWithGuaranteedLeanup方法和受约束的执行区域。
上面提到的Rick Strahl文章很有启发性,请务必阅读评论。请注意,斯特拉尔的问题是具体的。他想把数据送到客户机(一个图像),然后处理hit跟踪数据库更新,这并没有减慢图像的服务速度,这使得他在响应后做一些事情的问题。end被调用了。
我从未考虑过使用response.end()来控制程序流。
但是,response.end()在向用户提供文件时很有用。
您已将文件写入响应,但不希望在响应中添加任何其他内容,因为它可能会损坏您的文件。
我只使用response.end()作为测试/调试机制
1 2 3 4 | <snip> Response.Write("myVariable:" + myVariable.ToString()); Response.End(); <snip> |
从你在研究方面发表的文章来看,如果需要回应的话,我会说这是一个糟糕的设计。
我在.NET和经典ASP中都使用了response.end()来强制结束以前的事情。例如,当有一定数量的登录尝试时,我会使用它。或者当从未经身份验证的登录名访问安全页时(粗略示例):
1 2 3 4 5 6 7 8 | if (userName =="") { Response.Redirect("......"); Response.End(); } else { ..... |
当向用户提供文件时,我会使用flush,这样做会导致问题。
在经典的ASP中,我在一些Ajax调用中有一个3到10秒的TTFB(时间到第一个字节),比在有更多SQL调用的常规页面中的TTFB大得多。
返回的Ajax是要注入页面的HTML段。
TTFB比渲染时间长几秒。
如果在渲染后添加response.end,TTFB会大大减少。
我可以通过发出".
.",获得同样的效果,但当输出json或xml时,这可能不起作用;这里response.end是必需的。