原文 | 下载本教程中的编码例子 | 下载本教程的PDF版

导言

在 综叙:在DataList里编辑和删除数据 里,我们创建了一个提供简单编辑和删除功能的DataList。虽然功能上已经完整了,但是对用户来说是不友好的。因为所有在编辑和删除过程中产生的异常都是未处理的。比如,遗漏了输入product的name,或者编辑product时在price里输入“Very affordable!”,都会抛出异常。而由于在代码里未捕捉这些异常,页面会显示ASP.NET运行时的详细错误信息。

如我们在在ASP.NET页面中处理BLL/DAL层的异常里看到的,如果BLL或DAL里发生异常,详细的信息会返回到ObjectDataSource,然后再到GridView。我们已经学习了如何优雅的处理这些异常:为ObjectDataSource或GridView创建Updated或RowUpdated事件处理,检查异常,然后指明异常被处理。

然而在使用DataList时,我们并没有通过ObjectDataSource来更新和删除数据。我们是直接通过BLL来实现的。为了检测到 BLL或DAL的异常,我们需要在ASP.NET页里写异常处理代码。本章我们将学习在使用DataList编辑时如何巧妙的处理异常。

注意:在综叙:在DataList里编辑和删除数据里,我们讨论了几种不同的编辑和删除数据的方法,其中一些会涉及到使用ObjectDataSource来编辑和删除。如果你用这些技术的话,你可以直接通过ObjectDataSource的Updated或Deleted 事件处理中处理这些异常。

第一步: 创建一个可编辑的DataList

首先创建一个可编辑的DataList。打开EditDeleteDataList文件夹下的ErrorHandling.aspx页,添加一个ID为Products的DataList和一个名为ProductsDataSource的ObjectDataSouce。在SELECT标签下选择ProductsBLL类的GetProducts()方法。在INSERT,UPDATE和DELETE标签里选择None.

图 1: 配置ObjectDataSource

完成ObjectDataSouce后,Visual Studio会自动创建一个ItemTemplate。用显示每个product的name和price并包含一个Edit button的ItemTemplate代替它,然后创建一个用TextBox显示name和price,并包含一个Update button和Cancel button的EditItemTemplate。最后将DataList的RepeatColumns属性设为2。

做完这些后,你的声明代码应该和下面的差不多。检查并确保Edit,Cancel和Update button的CommandName属性
分别被设为“Edit”, “Cancel”, 和“Update”。

ASP.NET
12345678910111213141516171819202122232425262728293031323334353637
<asp:DataList ID="Products" runat="server" DataKeyField="ProductID"DataSourceID="ProductsDataSource" RepeatColumns="2"><ItemTemplate><h5><asp:Label runat="server" ID="ProductNameLabel"Text='<%# Eval("ProductName") %>' /></h5>Price:<asp:Label runat="server" ID="Label1"Text='<%# Eval("UnitPrice", "{0:C}") %>' /><br /><asp:Button runat="server" id="EditProduct" CommandName="Edit"Text="Edit" /><br /><br /></ItemTemplate><EditItemTemplate>Product name:<asp:TextBox ID="ProductName" runat="server"Text='<%# Eval("ProductName") %>' /><br />Price:<asp:TextBox ID="UnitPrice" runat="server"Text='<%# Eval("UnitPrice", "{0:C}") %>' /><br /><br /><asp:Button ID="UpdateProduct" runat="server" CommandName="Update"Text="Update" />&nbsp;<asp:Button ID="CancelUpdate" runat="server" CommandName="Cancel"Text="Cancel" /></EditItemTemplate></asp:DataList><asp:ObjectDataSource ID="ProductsDataSource" runat="server"SelectMethod="GetProducts" TypeName="ProductsBLL"OldValuesParameterFormatString="original_{0}"></asp:ObjectDataSource>

注意:本章里DataList的view state必须开启。

浏览一下页面,见图2。

图 2: 每个Product 都包含一个Edit Button

现在Edit button只是引起一个postback —还不能将product变成可编辑的。为了实现编辑功能,我们需要为EditCommand,CancelCommand和UpdateCommand创建事件处理。EditCommand和CancelCommand事件仅仅只需要更新DataList的EditItemIndex属性,并重新绑定数据到DataList。

C#
123456789101112131415161718
protected void Products_EditCommand(object source, DataListCommandEventArgs e){// Set the DataList's EditItemIndex property to the// index of the DataListItem that was clickedProducts.EditItemIndex = e.Item.ItemIndex;// Rebind the data to the DataListProducts.DataBind();}protected void Products_CancelCommand(object source, DataListCommandEventArgs e){// Set the DataList's EditItemIndex property to -1Products.EditItemIndex = -1;// Rebind the data to the DataListProducts.DataBind();}

UpdateCommand事件处理稍微麻烦一点。它需要从DataKey集合里读取被编辑的product的ProductID,和EditItemTemplate里的TextBox里的product的name和price,然后调用ProductsBLL类的UpdateProduct方法,最后返回到DataList编辑前的状态。

我们在这里使用 综叙:在DataList里编辑和删除数据 里的UpdateCommand事件处理代码。

C#
1234567891011121314151617181920212223242526
protected void Products_UpdateCommand(object source, DataListCommandEventArgs e){// Read in the ProductID from the DataKeys collectionint productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);// Read in the product name and price valuesTextBox productName = (TextBox)e.Item.FindControl("ProductName");TextBox unitPrice = (TextBox)e.Item.FindControl("UnitPrice");string productNameValue = null;if (productName.Text.Trim().Length > 0)productNameValue = productName.Text.Trim();decimal unitPriceValue = null;if (unitPrice.Text.Trim().Length > 0)unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(), System.Globalization.NumberStyles.Currency);// Call the ProductsBLL's UpdateProduct method...ProductsBLL productsAPI = new ProductsBLL();productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID);// Revert the DataList back to its pre-editing stateProducts.EditItemIndex = -1;Products.DataBind();}

在有非法输入的时候— 可能是不正确的price格式,比如“-$5.00”,或者忽略了product的name— 就会引起异常。由于UpdateCommand事件处理还没有处理异常,页面会出现ASP.NET运行时错误。见图3。

图 3: 未处理异常发生时,用户会看到这样的错误页面

第二步: 在UpdateCommand Event Handler里处理异常

更新流程中,异常可能发生在UpdateCommand事件处理,或BLL或DAL里。比如,如果用户输入了一个“太贵”的价格,UpdateCommand 事件处理里的Decimal.Parse 会抛出FormatException 异常。如果用户忽略了product的name或者price是一个负数,DAL会抛出异常。

当异常发生时,我们希望显示自己定义的信息。添加一个ID为ExceptionDetails的Label控件到页面上,通过设置CssClass属性为Warning CSS类来将Text设置为红色,特大,加粗的意大利字体。这个类在Styles.css文件里定义。

异常发生时,我们只希望这个 Label显示一次。也就是说,在后面postback的时候,Label的警告信息需要隐藏起来。这个可以通过清除Label的Text属性或者将Visible属性设为False(在Page_Load里)(如我们在在ASP.NET页面中处理BLL/DAL层的异常 里做的那样)或者禁用Label的view state来实现。我们这里用后一种方法。

ASP.NET
12
<asp:Label ID="ExceptionDetails" EnableViewState="False" CssClass="Warning"runat="server" />

异常发生时,我们将异常的信息显示在Label的Text属性上。由于view state被禁用了,后面再postback的话,Text属性会自动的丢失,回到缺省值(空字符串),这样就隐藏了警告信息。

异常发生时将信息显示在页面上,我们需要在UpdateCommand事件处理里添加Try....Catch块。Try的那部分包含可能抛出异常的代码,Catch部分包含当出现异常时需要执行的代码。更多的Try..Catch块信息参考Exception Handling Fundamentals 。

C#
12345678910111213
protected void Products_UpdateCommand(object source, DataListCommandEventArgs e){// Handle any exceptions raised during the editing processtry{// Read in the ProductID from the DataKeys collectionint productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);... Some code omitted for brevity ...}catch (Exception ex){// TODO: Display information about the exception in ExceptionDetails}}

无论Try块里抛出何种类型的异常,Catch块的代码都会执行。抛出异常的类型—DbException, NoNullAllowedException, ArgumentException等 — 取决于第一个错误。如果是数据库级别的问题,会抛出DbException 。如果是UnitPrice, UnitsInStock, UnitsOnOrder, 或ReorderLevel 字段有非法值,会抛出ArgumentException (我们在ProductsDataTable里已经添加过验证字段值的代码,见创建一个业务逻辑层 )

我们可以根据捕捉到的异常的类型来为用户提供更好的帮助。下面的代码— 和在ASP.NET页面中处理BLL/DAL层的异常 中基本上一样— 提供了这个功能:

C#
123456789101112131415
protected void Products_UpdateCommand(object source, DataListCommandEventArgs e){// Handle any exceptions raised during the editing processtry{// Read in the ProductID from the DataKeys collectionint productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);... Some code omitted for brevity ...}catch (Exception ex){// TODO: Display information about the exception in ExceptionDetails}}

最后仅仅只需要调用DisplayExceptionDetails方法。

完成Try..Catch后,用户会看到更有用的错误信息,如图4,5所示。注意在异常出现时,DataList仍然保持在可编辑的模式下。这是因为异常发生时,控制流程马上转到Catch块里,忽略了将DataList转到编辑前状态的代码。

图 4: 用户忽略了必填字段时的错误信息

图 5: 输入非法价格时的错误信息

总结

GridView和ObjectDataSource提供了在更新和删除过程中包含异常信息的事件处理和指明异常是否被处理的属性。而直接使用BLL的DataList没有这些特性,我们需要亲自处理这些异常。

本章我们学习了如何在DataList的更新过程中在UpdateCommand里添加Try...Catch块来处理异常。如果有任何异常发生,Catch块里的代码会执行,将错误信息显示在ExceptionDetails Label上。

现在,DataList并没有在第一时间阻止异常的发生。尽管我们知道一个负的price值会产生异常,我们也没有添加阻止用户输入这样的值的功能。在后面的几章里,我们将学习如何通过在EditItemTemplate里添加验证控件来验证用户的输入从而减少这些异常的发生。

祝编程愉快!

Scott Mitchell 的ASP.NET 2.0数据教程之三十八:: 处理BLL和DAL的异常相关推荐

  1. Scott Mitchell 的ASP.NET 2.0数据教程之三十九:: 在编辑和插入界面里添加验证控件...

    原文 | 下载本教程中的编码例子 | 下载本教程的PDF版 导言 到目前为止的讨论编辑DataList的教程里,没有包含任何验证用户的输入,即使是用户非法输入- 遗漏了product的name或者负的 ...

  2. Scott Mitchell 的ASP.NET 2.0数据教程之四十五::DataList和Repeater数据排序

    Scott Mitchell 的ASP.NET 2.0数据教程之四十五::DataList和Repeater数据排序(一) 原文 | 下载本教程中的编码例子 | 下载本教程的PDF版 (以后比较长的部 ...

  3. [翻译]Scott Mitchell 的ASP.NET 2.0数据教程之十二:在GridView控件中使用TemplateField

    在ASP.NET 2.0中操作数据:在GridView控件中使用TemplateField 英文原版  |   本教程的代码(C#)   |   翻译目录   |   原文目录 导言 GridView ...

  4. Scott Mitchell 的ASP.NET 2.0数据教程之十二:在GridView控件中使用TemplateField

    导言 GridView是由一组字段(Field)组成的,它们都指定的了来自DataSource中的什么属性需要用到自己的输出呈现中.最简单的字段类型是BoundField,它仅将数据简单的显示为文本. ...

  5. Scott Mitchell 的ASP.NET 2.0数据教程之四十四::DataList和Repeater数据分页

    原文 | 下载本教程中的编码例子 | 下载本教程的PDF版 导言 分页和排序是显示数据时经常用到的功能.比如,在一个在线书店里搜索关于ASP.NET 的书的时候,可能结果会是成百上千,而每页只列出十条 ...

  6. Scott Mitchell 的ASP.NET 2.0数据教程之四十五::DataList和Repeater数据排序(三)

    第七步: 在自定义分页的Repeater 里添加排序功能 现在已经完成了自定义分页,我们再来添加排序功能.ProductsBLL类的GetProductsPagedAndSorted方法和GetPro ...

  7. ASP.NET 2.0数据教程之三十六 在DataList里编辑和删除数据

    导言 概述插入.更新和删除数据 里我们已经学习了如何使用GridView等控件来插入,更新删除数据.通过ObjectDataSource和其它数据控件仅仅只需要在智能标签里勾一下checkbox就完成 ...

  8. [翻译]Scott Mitchell 的ASP.NET 2.0数据教程之十三:在DetailsView控件中使用TemplateField...

    导言 比起BoundField.CheckBoxField.HyperLinkField以及其他的那些数据字段控件(data field controls)来说,TemplateField提供了一种高 ...

  9. Scott Mitchell 的ASP.NET 2.0数据教程之一: 创建一个数据访问层

    原文 | 下载本教程中的编码例子 | 下载本教程的英文PDF版 导言 作为web开发人员,我们的生活围绕着数据操作.我们建立数据库来存储数据,写编码来访问和修改数据,设计网页来采集和汇总数据.本文是研 ...

最新文章

  1. 如果CRC等于炒鸡蛋,那么...
  2. python爬取学校题库_pyhton 网络爬取软考题库保持txt
  3. 音视频技术开发周刊 | 152
  4. AIX-vi操作-提示Unknown terminal type的问题解决方法
  5. 前端学习(1029):jquery其他方法
  6. 将 AR 新创公司收入囊中后,Lyft 的自动驾驶脚步要加快了
  7. 局域网管理软件精华集成及下载
  8. android三国2,三国演义安卓单机版
  9. python 工资管理软件_Python:企业微信指量发工资条工具 -消息发送模块
  10. mdx 医学词典_有没有专门医学英语词典app?
  11. 开放式虚拟仿真实验服务器,润尼尔开放式虚拟仿真实验教学及资源共享平台
  12. Windows Server 2008搭建【web服务器】
  13. 从入门到放弃:微信小程序入门个人指南Day 4
  14. 三子棋小游戏(超详细)
  15. 两台不同的型号的路由器桥接
  16. 扫码枪回车键条码_扫描枪怎么设置自动换行 条码扫描枪不自动回车怎么设置...
  17. 三个蛤蜊三块肉才能称得上“老板”
  18. 随处可见的红黑树详解
  19. TerminateThread的缺点
  20. 基于人脸图像的心率心率测量系统

热门文章

  1. 教学思路C#之入门一 认识简单的C#结构
  2. android jar 加密
  3. 远程接入-天翼5系统让ERP穿越时空!
  4. Cannot resolve field [product], input field list:[user, EXPR$0]
  5. java.net.UnknownHostException: dbmtimehadoop
  6. No module named 'pandas.core.internals.managers'; 'pandas.core.internals' is not a package
  7. error: 'syms' undefined near line 1 column 1
  8. 交叉熵(cross entropy)概念整理
  9. secureCrT夜间模式
  10. php进程守护进程,php 多进程实现守护进程的实例代码