在即将发布的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);
}
}
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的简单包装而已,并没有增加其它额外的功能。我目前实在还是想不明白为什么要这样做?