您的位置:首页 > 编程语言 > ASP

Scott Mitchell 的ASP.NET 2.0数据教程之十八:: 在ASP.NET页面中处理BLL/DAL层的异常

2006-08-17 20:24 537 查看

导言

在一个使用了分层体系架构的ASP.NET web应用系统里处理数据,一般遵循以下几步:

1. 确定业务逻辑层需要调用哪个方法,并且需要出入哪些参数。这些参数可以通过硬编码设置,程序自动设定,或者由用户输入。

2. 调用此方法。

3. 处理结果。当调用一个返回数据的BLL方法时,这包括绑定数据到Data Web服务器控件。而对于修改数据的BLL方法而言,这包括基于返回值的基础上执行某些动作,或者适当地处理在第二步中引发的异常。

正如我们在前一节里看到的,无论ObjectDataSource控件还是数据Web服务器控件,都为第1和第3步提供了可扩展性。例如GridView控件,触发它的RowUpdating事件之前把它的字段的值赋值到ObjectDataSource的UpdateParameters集合;在ObjectDataSource完成它的操作之后触发RowUpdated事件。

我们已经检测到第1步中触发的事件,并且看过了如何使用它们实现自定义出入参数或者取消操作。这一节我们将把我们的注意力转到操作完成后所触发的事件。通过这些post级的event handler和其它,可以判断在操作过程中是否产生了一个异常,并且适当地处理它,在屏幕中显示友好的错误信息要优于转到ASP.NET的默认错误处理页。

为了举例说明这些post级事件的工作方式,让我们创建一个页面,它在一个可编辑的GridView中列出产品信息。当更新一个产品时,如果引发了一个异常,我们的ASP.NET页面会在GridView控件的上方显示一个简短的信息,说明出现了一个问题。好吧,让我们开始!

第一步: 为产品创建一个可编辑的GridView

这一节里我们创建一个可编辑的GridView,它仅仅包含两个的字段,ProductName和UnitPrice 。这需要为ProductsBLL类的UpdateProduct方法增加一个额外的重载,它仅仅接受3个输入参数(product’s name,unit price,和ID),相对于接受每一个产品的字段的方法。在本节里让我们再一次练习一下这些技巧,创建一个可编辑的GridView,它显示产品的name、quantity per unit、unit price、和units in stock,但仅仅允许name,unit price,和units in stock可编辑。

为了提供这个场景,我们需要对UpdateProduct方法的另一个重载,它接收4个参数: product’s name,unit price,units in stock和ID。在ProductsBLL类中添加下面这个方法:

1[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, false)]
2public bool UpdateProduct(string productName, decimal? unitPrice, short? unitsInStock, int productID)
3

完成了此方法后,我们可以创建一个ASP.NET页面,它允许编辑这四个产品字段。打开EditInsertDelete文件夹里的ErrorHandling.aspx页面,并通过设计器添加一个GridView控件到页面中。绑定这个GridView到一个新的ObjectDataSource控件,映射Select()方法到ProductsBLL类的GetProducts()方法,方法Update()映射到刚刚创建的UpdateProduct重载。

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
2
7

我们的GridView包含一个QuantityPerUnit绑定列,但它仅仅用作显示,不能被用户编辑。为了实现这一点,只需要简单地将该绑定列的ReadOnly属性设置为true。

protected void Page_Load(object sender, EventArgs e)
2

通过这些代码,当第一次访问页面和随后的回传后,ExceptionDetails控件的Visible属性都将被设置为false。当在GridView的RowUpdated事件处理程序中检测到一个DAL/BLL层的异常时,我们将设置ExceptionDetails控件的Visible属性为true。因为页面生命周期里Web服务器控件的事件处理出现在Page_Load事件处理之后,该Label将会显示。不过,下一次回传,Page_Load事件处理将重新将Visible属性设置回false,再次隐藏它。

[b]注意
: 我们也可以不必在Page_Load里设置ExceptionDetails控件的Visible属性,作为另一种选择,可以在声明语法里设置其Visible属性为false并禁用视图状态(设置它的EnableViewState属性为false)。我们将在以后的章节里使用这种方法。

通过添加这个Label控件,我们下一步是为GridView的RowUpdated事件添加一个事件处理程序。在设计视图中选中GridView控件,打开属性窗口,点击黄色闪电状图标,列出GridView的所有事件。在GridView的RowUpdating事件里我们可以看到已经存在一个入口,因为我们在本节较早的时候已经为此事件创建了一个事件处理程序。为RowUpdated事件创建一个事件处理程序。

protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
2

这个事件处理程序的第二个输入参数是一个GridViewUpdatedEventArgs类型的对象,它有三个关于处理异常的属性:

· Exception –获取更新操作过程中引发的异常;如果没有抛出异常,该属性的值为null

· ExceptionHandled –获取或设置一个值,它指示在更新操作过程中所引发的异常是否已在RowUpdated事件处理程序中得到处理;如果设为false(默认值),该异常将被重新引发,漏出到ASP.NET运行时

· KeepInEditMode – 如果设置为true,GridView当前编辑行将维持在编辑模式;如果设置为false(默认值),当前行将恢复到只读模式

那么我们的代码应该检测Exception是否为null,不是null则意味着执行此操作时引发了一个异常。如果是这样,我们则希望:

· 在ExceptionDetails控件中显示一个对用户友好的提示信息

· 指示异常已经被处理

· 让当前行保持编辑模式

下面的代码实现了上述的目的:

1protected void GridView1_RowUpdated(object sender, GridViewUpdatedEventArgs e)
2

在这个事件处理程序中,首先检测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)时的结果。

public bool UpdateProduct(string productName, decimal? unitPrice, short? unitsInStock, int productID)
2

通过这个修改,任何超过现有价格两倍的价格更新都回引发一个ApplicationException异常被抛出。就像DAL中引发的异常一样,这个BLL引发的ApplicationException异常可以在GridView的RowUpdated事件处理程序中被侦测并处理。实际上,我们已有的RowUpdated事件处理程序的代码可以正确地发现到这个异常并显示ApplicationException的Message属性的值。图11显示的是当一个用户试图将产品“Chai”的价格更新为$50.00时的截屏,这超过了它原有价格$19.95的两倍。



图 11: 这个业务规则不接受价格增长超出产品现有价格的两倍[/b]

注意: 理想化地我们的业务规则不应该在UpdateProduct方法重载里而应该在一个公共的方法中。这留作读者练习。

总结

在插入、更新或删除操作的过程中,数据Web控件和ObjectDataSource控件都包含了pre- 和post-级的事件,它们记录着当前的操作。正如我们在本节和前面的一节里所看到的,当使用一个可编辑的GridView时,GridView的RowUpdating事件在ObjectDataSource的Updating事件之后触发,此时update命令发送到ObjectDataSource的隐含对象。完成了此操作,在GridView的RowUpdated事件之后,触发ObjectDataSource的Updated事件。

我们可以为这些发生在操作之前的事件创建事件处理程序,目的是自定义输入参数;为发生在

操作之后的事件创建事件处理,目的是检测和相应操作的结果。Post-level的事件处理程序通常用作侦测在操作过程中是否出现了一个异常。当面对一个异常时,这些post-level的事件处理程序可以随意地处理该异常。在本节里我们看过了如何处理这样的一个异常,显示一个友好的错误提示信息。

在下一节里我们将看看如何降低因数据格式的问题引起异常的可能性(例如在UnitPrice输入一个负数)。特别地,我们将看看如何添加validation控件到编辑和插入界面。

祝编程快乐!

作者简介

Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用微软Web技术。Scott是个独立的技 术咨询顾问,培训师,作家,最近完成了将由Sams出版社出版的新作,24小时内精通ASP.NET 2.0。他的联系电邮为mitchell@4guysfromrolla.com,也可以通过他的博客http://ScottOnWriting.NET与他联系。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐