Обработка исключений уровней BLL и DAL (VB)
В этом руководстве описано, как тактично обрабатывать исключения, возникающие во время редактируемого рабочего процесса обновления DataList.
Введение
В учебнике Общие сведения об изменении и удалении данных в DataList мы создали DataList, который предлагает простые возможности редактирования и удаления. Хотя он полностью функциональный, он вряд ли был понятным для пользователя, так как любая ошибка, которая произошла во время процесса редактирования или удаления, приводила к необработанным исключениям. Например, при пропуске названия продукта или при редактировании продукта при вводе значения цены Очень доступно!, создается исключение. Так как это исключение не перехватывалось в коде, оно выполняется в ASP.NET среде выполнения, которая затем отображает сведения об исключении на веб-странице.
Как мы видели в руководстве по обработке исключений BLL и DAL-Level на странице ASP.NET , если исключение возникает из глубин бизнес-логики или уровней доступа к данным, сведения об исключении возвращаются в ObjectDataSource, а затем в GridView. Мы узнали, как корректно обрабатывать эти исключения, создав Updated
обработчики событий или RowUpdated
для ObjectDataSource или GridView, проверив наличие исключения и указав, что исключение было обработано.
Однако в наших руководствах по DataList не используется ObjectDataSource для обновления и удаления данных. Вместо этого мы работаем непосредственно против BLL. Чтобы обнаружить исключения, исходящие из BLL или DAL, необходимо реализовать код обработки исключений в коде программной части страницы ASP.NET. В этом руководстве описано, как более тактично обрабатывать исключения, возникающие во время редактируемого рабочего процесса обновления DataList.
Примечание
В учебнике Общие сведения об изменении и удалении данных в DataList мы рассмотрели различные методы редактирования и удаления данных из DataList, некоторые методы, связанные с использованием ObjectDataSource для обновления и удаления. При использовании этих методов можно обрабатывать исключения из BLL или DAL с помощью обработчиков Updated
событий ObjectDataSource или Deleted
.
Шаг 1. Создание редактируемого списка данных
Прежде чем беспокоиться об обработке исключений, возникающих во время рабочего процесса обновления, сначала создадим редактируемый DataList. Откройте страницу ErrorHandling.aspx
в папкеEditDeleteDataList
, добавьте DataList в Designer, задайте для его ID
свойства Products
значение и добавьте новый объект ObjectDataSource с именем ProductsDataSource
. Настройте ObjectDataSource на использование ProductsBLL
метода класса GetProducts()
для выбора записей; установите для раскрывающихся списков на вкладках INSERT, UPDATE и DELETE значение (Нет).
Рис. 1. Возврат сведений о продукте GetProducts()
с помощью метода (щелкните для просмотра полноразмерного изображения)
После завершения работы мастера ObjectDataSource Visual Studio автоматически создаст ItemTemplate
для DataList. Замените его на , ItemTemplate
который отображает название и цену каждого продукта и включает кнопку Изменить. Затем создайте EditItemTemplate
с веб-элементом управления TextBox для кнопок имя и цена и Обновить и Отмена. Наконец, задайте для свойства DataList RepeatColumns
значение 2.
После этих изменений декларативная разметка страницы должна выглядеть примерно так: Двойные проверка, чтобы убедиться, что для кнопок Изменить, Отмена и Обновить для их CommandName
свойств заданы значения Изменить, Отмена и Обновить соответственно.
<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" />
<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.
Уделите немного времени, чтобы просмотреть наш прогресс в браузере (см. рис. 2).
Рис. 2. Каждый продукт включает кнопку "Изменить" (щелкните для просмотра полноразмерного изображения)
В настоящее время кнопка Изменить вызывает только обратную передачу. Это еще не делает продукт редактируемым. Чтобы включить редактирование, необходимо создать обработчики событий для событий DataList EditCommand
, CancelCommand
и UpdateCommand
. События EditCommand
и CancelCommand
просто обновляют свойство DataList EditItemIndex
и повторно привязывать данные к DataList:
Protected Sub Products_EditCommand(source As Object, e As DataListCommandEventArgs) _
Handles Products.EditCommand
' Set the DataList's EditItemIndex property to the
' index of the DataListItem that was clicked
Products.EditItemIndex = e.Item.ItemIndex
' Rebind the data to the DataList
Products.DataBind()
End Sub
Protected Sub Products_CancelCommand(source As Object, e As DataListCommandEventArgs) _
Handles Products.CancelCommand
' Set the DataList's EditItemIndex property to -1
Products.EditItemIndex = -1
' Rebind the data to the DataList
Products.DataBind()
End Sub
Обработчик UpdateCommand
событий немного более задействован. Он должен считывать измененные продукты ProductID
из DataKeys
коллекции, а также название продукта и цену из TextBoxes в EditItemTemplate
, а затем вызвать ProductsBLL
метод класса s UpdateProduct
, прежде чем возвращать DataList в состояние предварительного редактирования.
Пока давайте просто используем тот же код из UpdateCommand
обработчика событий в руководстве Общие сведения об изменении и удалении данных в DataList . Мы добавим код для корректной обработки исключений на шаге 2.
Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
Handles Products.UpdateCommand
' Read in the ProductID from the DataKeys collection
Dim productID As Integer = Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
' Read in the product name and price values
Dim productName As TextBox = CType(e.Item.FindControl("ProductName"), TextBox)
Dim unitPrice As TextBox = CType(e.Item.FindControl("UnitPrice"), TextBox)
Dim productNameValue As String = Nothing
If productName.Text.Trim().Length > 0 Then
productNameValue = productName.Text.Trim()
End If
Dim unitPriceValue As Nullable(Of Decimal) = Nothing
If unitPrice.Text.Trim().Length > 0 Then
unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(), _
System.Globalization.NumberStyles.Currency)
End If
' Call the ProductsBLL's UpdateProduct method...
Dim productsAPI As New ProductsBLL()
productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID)
' Revert the DataList back to its pre-editing state
Products.EditItemIndex = -1
Products.DataBind()
End Sub
Перед лицом недопустимых входных данных, которые могут быть в виде неправильно отформатированных цен за единицу, незаконной стоимости единицы, такой как -5,00 долл. США, или упущения названия продукта будет возникать исключение. UpdateCommand
Так как на данный момент обработчик событий не содержит код обработки исключений, исключение будет отображаться в ASP.NET среде выполнения, где оно будет отображаться для конечного пользователя (см. рис. 3).
Рис. 3. При возникновении необработанного исключения конечный пользователь видит страницу ошибки
Шаг 2. Корректное обработка исключений в обработчике событий UpdateCommand
Во время рабочего процесса обновления в обработчике UpdateCommand
событий, BLL или DAL могут возникать исключения. Например, если пользователь введет цену Слишком дорого, Decimal.Parse
инструкция в обработчике UpdateCommand
событий вызовет FormatException
исключение. Если пользователь пропускает название продукта или если цена имеет отрицательное значение, DAL вызовет исключение.
При возникновении исключения требуется отобразить информативное сообщение на самой странице. Добавьте веб-элемент управления Метка на страницу, для которой ID
задано значение ExceptionDetails
. Настройте текст Label для отображения красного, очень большого, полужирного и курсивного шрифта, назначив его CssClass
свойство классу Warning
CSS, который определен в Styles.css
файле.
При возникновении ошибки требуется, чтобы метка отображалась только один раз. Это значит, что при последующих обратных операциях предупреждение label должно исчезнуть. Это можно сделать, очистив свойство Labels Text
или задав его Visible
свойству False
значение в Page_Load
обработчике событий (как это было в руководстве по обработке исключений BLL- и DAL-Level в ASP.NET Page ) или отключив поддержку состояния представления Метки. Давайте воспользуемся последним параметром.
<asp:Label ID="ExceptionDetails" EnableViewState="False" CssClass="Warning"
runat="server" />
При возникновении исключения мы назначим сведения об исключении свойству ExceptionDetails
элемента управления Text
Label. Так как состояние представления отключено, при последующих обратных передачах программные изменения свойства будут потеряны Text
, возвращаясь к тексту по умолчанию (пустая строка), тем самым скрывая предупреждающее сообщение.
Чтобы определить, когда возникает ошибка для отображения полезного сообщения на странице, необходимо добавить Try ... Catch
блок в UpdateCommand
обработчик событий. Часть Try
содержит код, который может привести к исключению, а Catch
блок содержит код, который выполняется перед лицом исключения. Дополнительные сведения о блоке см. в разделе Основы обработки исключенийTry ... Catch
в документации по платформа .NET Framework.
Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
Handles Products.UpdateCommand
' Handle any exceptions raised during the editing process
Try
' Read in the ProductID from the DataKeys collection
Dim productID As Integer = _
Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
... Some code omitted for brevity ...
Catch ex As Exception
' TODO: Display information about the exception in ExceptionDetails
End Try
End Sub
Если код Try
блока создает исключение любого типа, Catch
код блока начнет выполняться. Тип исключения, вызываемого DbException
, NoNullAllowedException
, ArgumentException
и т. д., зависит от того, что именно ускорит ошибку в первую очередь. При возникновении проблемы на уровне базы данных будет выдано DbException
исключение . Если введено недопустимое значение для UnitPrice
полей , UnitsInStock
, UnitsOnOrder
или ReorderLevel
, ArgumentException
будет выдано исключение , так как мы добавили код для проверки этих значений полей в ProductsDataTable
классе (см. учебник Создание уровня бизнес-логики ).
Мы можем предоставить пользователю более полезное объяснение, основывая текст сообщения на типе перехвата исключения. Следующий код, который использовался в практически идентичной форме в учебнике Обработка исключений BLL- и DAL-Level в ASP.NET Page , предоставляет такой уровень детализации:
Private Sub DisplayExceptionDetails(ByVal ex As Exception)
' Display a user-friendly message
ExceptionDetails.Text = "There was a problem updating the product. "
If TypeOf ex Is System.Data.Common.DbException Then
ExceptionDetails.Text += "Our database is currently experiencing problems." + _
"Please try again later."
ElseIf TypeOf ex Is System.Data.NoNullAllowedException Then
ExceptionDetails.Text+="There are one or more required fields that are missing."
ElseIf TypeOf ex Is ArgumentException Then
Dim paramName As String = CType(ex, ArgumentException).ParamName
ExceptionDetails.Text+=String.Concat("The ", paramName, " value is illegal.")
ElseIf TypeOf ex Is ApplicationException Then
ExceptionDetails.Text += ex.Message
End If
End Sub
Чтобы завершить работу с этим руководством, просто вызовите DisplayExceptionDetails
метод из Catch
блока, передавая перехватимый Exception
экземпляр (ex
).
При наличии Try ... Catch
блока пользователи получают более информативное сообщение об ошибке, как показано на рисунках 4 и 5. Обратите внимание, что при возникновении исключения DataList остается в режиме редактирования. Это связано с тем, что после возникновения исключения поток управления немедленно перенаправляется в Catch
блок, минуя код, возвращающий DataList в состояние предварительного редактирования.
Рис. 4. Если пользователь пропускает обязательное поле, отображается сообщение об ошибке (щелкните для просмотра полноразмерного изображения)
Рис. 5. При вводе отрицательной цены отображается сообщение об ошибке (щелкните для просмотра полноразмерного изображения)
Сводка
GridView и ObjectDataSource предоставляют обработчики событий постуровневого уровня, которые содержат сведения о любых исключениях, которые были вызваны во время рабочего процесса обновления и удаления, а также свойства, которые можно задать, чтобы указать, было ли обработано исключение. Однако эти функции недоступны при работе с DataList и использовании BLL напрямую. Вместо этого мы отвечаем за реализацию обработки исключений.
В этом руководстве мы узнали, как добавить обработку исключений в редактируемый рабочий процесс обновления DataList, добавив Try ... Catch
блок в UpdateCommand
обработчик событий. Если во время обновления возникает исключение, Catch
код блока выполняется, отображая полезные сведения в метке ExceptionDetails
.
На этом этапе DataList не предпринимает никаких усилий, чтобы предотвратить возникновение исключений. Несмотря на то, что мы знаем, что отрицательная цена приведет к исключению, мы еще не добавили никаких функций, чтобы предотвратить ввод пользователем таких недопустимых входных данных. В следующем руководстве мы посмотрим, как уменьшить количество исключений, вызванных недопустимыми пользовательскими входными данными EditItemTemplate
, добавив элементы управления проверки в .
Счастливого программирования!
Дополнительные материалы
Дополнительные сведения о темах, рассмотренных в этом руководстве, см. в следующих ресурсах:
- Правила разработки исключений
- Модули и обработчики ведения журнала ошибок (ELMAH) (библиотека с открытым кодом для ведения журнала ошибок)
- Корпоративная библиотека для платформа .NET Framework 2.0 (включает блок приложений управления исключениями)
Об авторе
Скотт Митчелл( Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часах. Он может быть доступен в mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.
Особая благодарность
Эта серия учебников была рассмотрена многими полезными рецензентами. Ведущим рецензентом этого руководства был Кен Песписа. Хотите просмотреть предстоящие статьи MSDN? Если да, опустите мне строку на mitchell@4GuysFromRolla.com.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по