在即将发布的Kooboo CMS 2.1.0.0中,将会升级到ASP.NET MVC 2。需要将所有的Module也同步升级到MVC2,在升级过程中发现MVC2一旦进入View输出阶段后,Response.Clear将会不起作用(Controller执行阶段,这个方法仍然正常工作),这将会影响Kooboo CMS Module的正常运行。
在确定是MVC 2引起的问题后,于是就从Response.Clear这个方法着手,它的代码逻辑如下:
public void Clear() { if (this.UsingHttpWriter) { this._httpWriter.ClearBuffers(); } IIS7WorkerRequest wr = this._wr as IIS7WorkerRequest; if (wr != null) { this.ClearNativeResponse(true, false, wr); } } 从这段代码,我们可以发现,ClearBuffer的条件是UsingHttpWriter这个属性的值为True,下面是UsingHttpWriter属性的原型定义:
private bool UsingHttpWriter { get { return ((this._httpWriter != null) && (this._writer == this._httpWriter)); } }
在这里判断,_httpWriter和_writer变量是否相同。于是我就只能从运行时的调试来看看这两个变量的值分别是什么,下面的截图分别是_httpWriter,_writer,UsingHttpWriter运行时的值:
在这里我们会发现UsingHttpWriter的值为fase,并且_writer的对象类型为System.Web.Mvc.ViewPage.SwitchWriter,此时我们就可以断定Response.Clear起作用的原因就是由SwitchWriter这个类为引起的。找到这个类,我们会发现它在ViewPage.RenderView(ViewContext viewContext)方法中被使用:
public virtual void RenderView(ViewContext viewContext) { this.ViewContext = viewContext; this.InitHelpers(); bool flag = false; SwitchWriter output = viewContext.HttpContext.Response.Output as SwitchWriter; if (output == null) { output = new SwitchWriter(); flag = true; } using (output.Scope(viewContext.Writer)) { if (flag) { int num = _nextId; try { _nextId = 0; viewContext.HttpContext.Server.Execute(HttpHandlerUtil.WrapForServerExecute(this), output, true); return; } finally { _nextId = num; } } this.ProcessRequest(HttpContext.Current); } }
而对应的方法在MVC 1.0中,它的实现是这样的:
public virtual void RenderView(ViewContext viewContext) { this.ViewContext = viewContext; this.InitHelpers(); this.ID = Guid.NewGuid().ToString(); this.ProcessRequest(HttpContext.Current); }
于是我们就找到解决这个问题的办法了,我们只要在我们项目的ViewPage中,重新RenderView(ViewContext viewContext)这个方法, 让它回到原来的实现就可以解决这个问题了。
这个问题解决了,但是另一个问题我现在仍在思考当中,为什么在MVC2中,要增加SwitchWriter这个类呢?我仔细了看了好几遍这个类的实现,只是对TextWriter的简单包装而已,并没有增加其它额外的功能。我目前实在还是想不明白为什么要这样做?