ASP.NET动态数据:如果在Page.Initialized事件上访问FormView.Controls,则在插入数据后不再显示表

最近,我收到了Ninject.Web的错误报告,它与ASP.NET动态数据一起无法正常工作。 问题是在回发时(例如,当插入,删除,编辑记录时)表格不再显示。

一些debuging表明问题是由IHttpModule引起的,它在初始化后递归遍历页面的所有控件。 只要此模块访问Controls属性获取FormView或GridView的访问器,就会出现问题。 如果这种类型的控件滑雪,一切都很好。 以下代码显示了该模块:

public class NinjectHttpModule : DisposableObject, IHttpModule { private HttpApplication httpApplication; public void Init(HttpApplication context) { this.httpApplication = context; this.httpApplication.PreRequestHandlerExecute += this.OnPreRequestHandlerExecute; } private static void InjectUserControls(Control parent) { if (parent == null) { return; } foreach (Control control in parent.Controls) { if (control is UserControl) { // KernelContainer.Inject(control); This is irrelevant for the question. } InjectUserControls(control); } } private void OnPreRequestHandlerExecute(object sender, EventArgs e) { var page = this.httpApplication.Context.CurrentHandler as Page; if (page == null) { return; } KernelContainer.Inject(page); page.InitComplete += (src, args) => InjectUserControls(page); } } 

如果更改此代码,以便通过DataBoundControls的子控件的迭代延迟到DataBound事件,一切都很好。 由下一个代码片段显示:

  private static void InjectUserControls(Control parent, bool skipDataBoundControls) { if (parent == null) { return; } if (skipDataBoundControls) { var dataBoundControl = parent as DataBoundControl; if (dataBoundControl != null) { dataBoundControl.DataBound += InjectDataBoundControl; return; } } foreach (Control control in parent.Controls) { if (control is UserControl) { KernelContainer.Inject(control); } InjectUserControls(control, skipDataBoundControls); } } private static void InjectDataBoundControl(object sender, EventArgs e) { var dataBoundControl = sender as DataBoundControl; if (dataBoundControl != null) { dataBoundControl.DataBound -= InjectDataBoundControl; InjectUserControls(dataBoundControl, false); } } 

因为我对System.Web.DynamicData完全不熟悉,所以我想知道一些事情,以便更好地了解如何解决这个问题:

  • 为什么会出现这个问题? 我的意思是它只是对Controls属性的简单读取访问。
  • 上述变化有哪些副作用?
  • 在数据绑定事件之后注入控件是否仍然足够早?
  • 您认为这是针对此问题的有效错误修复方法吗?

当然,令人费解的行为,有时会发生在具有许多执行阶段的WebForms中。

即使它只是对Controls属性的简单读取访问,该属性实际上可以做很多工作来返回子控件。 特别是,它不能返回子控件,除非它们已经创建,并且创建通常直到页面生命周期的后期才会发生。 因此,通过在InitComplete中访问它,孩子最终会在一些重要的动态数据连接发生之前过早地被创建,导致一些控件丢失。 是的,我意识到最终结果行为似乎毫无意义,这就是为什么有些人赞成MVC的直截了当:)

作为替代可能的解决方法,您可以尝试将注射从InitComplete移动到PreLoad吗? 例如

 page.PreLoad += (src, args) => InjectUserControls(page); 

我很确定这会解决问题,但我不太确定这是否会导致你的KernelContainer.Inject逻辑出现问题。 试一试,因为它比你的解决方法更简单。

如果这不起作用,我认为您的解决方法是可以的,因为它会延迟枚举直到创建子项。 至于“ 在数据绑定事件之后是否仍然足够早地注入控件 ”,我认为这完全取决于KernelContainer.Inject作用,以及它对控件状态的期望。