通过这些代码,当第一次访问页面和随后的回传后,ExceptionDetails控件的Visible属性都将被设置为false。当在GridView的RowUpdated事件处理程序中检测到一个DAL/BLL层的异常时,我们将设置ExceptionDetails控件的Visible属性为true。因为页面生命周期里Web服务器控件的事件处理出现在Page_Load事件处理之后,该Label将会显示。不过,下一次回传,Page_Load事件处理将重新将Visible属性设置回false,再次隐藏它。
注意: 我们也可以不必在Page_Load里设置ExceptionDetails控件的Visible属性,作为另一种选择,可以在声明语法里设置其Visible属性为false并禁用视图状态(设置它的EnableViewState属性为false)。我们将在以后的章节里使用这种方法。
通过添加这个Label控件,我们下一步是为GridView的RowUpdated事件添加一个事件处理程序。在设计视图中选中GridView控件,打开属性窗口,点击黄色闪电状图标,列出GridView的所有事件。在GridView的RowUpdating事件里我们可以看到已经存在一个入口,因为我们在本节较早的时候已经为此事件创建了一个事件处理程序。为RowUpdated事件创建一个事件处理程序。
图 8: 为GridView的事件创建一个事件处理
注意: 你也可以通过代码隐藏文件顶处的下拉列表创建这个事件处理。从左边的下拉列表中选择这个GridView控件,并从右边的下拉列表中选择RowUpdated事件。
创建这个事件处理将添加下面这些代码到ASP.NET页面的代码隐藏类中:
protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e) { }
这个事件处理程序的第二个输入参数是一个GridViewUpdatedEventArgs类型的对象,它有三个关于处理异常的属性:
·Exception –获取更新操作过程中引发的异常;如果没有抛出异常,该属性的值为null
·ExceptionHandled –获取或设置一个值,它指示在更新操作过程中所引发的异常是否已在RowUpdated事件处理程序中得到处理;如果设为false(默认值),该异常将被重新引发,漏出到ASP.NET运行时
·KeepInEditMode – 如果设置为true,GridView当前编辑行将维持在编辑模式;如果设置为false(默认值),当前行将恢复到只读模式
那么我们的代码应该检测Exception是否为null,不是null则意味着执行此操作时引发了一个异常。如果是这样,我们则希望:
·在ExceptionDetails控件中显示一个对用户友好的提示信息
·指示异常已经被处理
·让当前行保持编辑模式
下面的代码实现了上述的目的:
protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e) { if (e.Exception != null) { // Display a user-friendly message ExceptionDetails.Visible = true; ExceptionDetails.Text = "There was a problem updating the product. "; if (e.Exception.InnerException != null) { Exception inner = e.Exception.InnerException; if (inner is System.Data.Common.DbException) ExceptionDetails.Text += "Our database is currently experiencing problems." + "Please try again later."; else if (inner is NoNullAllowedException) ExceptionDetails.Text += "There are one or more required fields that are missing."; else if (inner is ArgumentException) { string paramName = ((ArgumentException)inner).ParamName; ExceptionDetails.Text += string.Concat("The ", paramName, " value is illegal."); } else if (inner is ApplicationException) ExceptionDetails.Text += inner.Message; } // Indicate that the exception has been handled e.ExceptionHandled = true; // Keep the row in edit mode e.KeepInEditMode = true; } }
在这个事件处理程序中,首先检测e.Exception是否为null。如果不是,设置ExceptionDetails控件的Visible属性为true、设置它的Text属性为“There was a problem updating the product.”。当前抛出的异常详细信息则保存在e.Exception对象的InnerException属性里。检查这个内部异常,如果它是特定的类型,则把一些额外的有用的信息附加到ExceptionDetails标签的Text属性。最后,ExceptionHandled和KeepInEditMode属性都设置为true。
图9展示的是遗漏了产品名称时的页面的截屏;图10则显示输入一个不合法的UnitPrice值(-50)时的结果。
图 9: ProductName绑定列必须包含一个值
图 10: UnitPrice值不接受负数