Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

.Net Собеседник - Новости мира Net, C#, ASP.Net


Информационный Канал Subscribe.Ru

.Net Собеседник #4

Содержание
  1. От автора
  2. Обзор новостей
  3. C# vs Java vs C++
  4. Время кода - Глобальная обработка исключений в приложениях ASP.NET
  5. Форумы .Net на www.sql.ru

От автора

Здравствуйте, коллеги!

Как известно, язык C# является объектно-ориентированным языком, т.е. реализующим программу через некий набор объектов, динамически создаваемых во время работы программы и иерархического дерева классов, имеющих статическую природу. Поэтому мне сегодня хотелось бы поговорить о трёх столпах объектно-ориентированного программирования. Как известно, это – наследование, инкапсуляция и полиморфизм .

В книге Гради Буча 'Объектно-ориентированное проектирование с примерами применения', ставшей уже классикой, дано такое определение наследования: 'Наследование означает такое соотношение между классами, когда один класс использует структурную или функциональную часть одного или нескольких других классов (соответственно простое и множественное наследование)'. В С# множественное наследование реализуется только с участием интерфейсов, пример такого наследования можно увидеть ниже, в статье 'Сравнительный обзор C#'. Простое наследование, или наследование от одного класса можно показать на следующем примере:

using System;
namespace hDrummer.Number4Legacy
{
class Starter
{
[STAThread]
static void Main(string[] args)
{
Lizard l = new Lizard();
Dragon d = new Dragon();
Console.WriteLine("У ящерицы {0} ноги, {1} голова, {2} хвост", l.Legs,l.Heads,l.Tails);
Console.WriteLine("У дракона {0} ноги, {1} головы, {2} хвоста", d.Legs,d.Heads,d.Tails); } }

class Lizard {
int legs;
int heads;
int tails;
//в конструкторе инициализируем поля  
public Lizard() { legs = 4; heads = 1; tails = 1; }
//дальше идут свойства для работы с полями  
public int Legs {
get{return legs;}
set{legs=value;}
}
public int Heads {
get{return heads;}
set{heads=value;}
}
public int Tails {
get {return tails;}
set {tails=value;}
}
}

class Dragon:Lizard {
//в конструкторе инициализируем поля  
public Dragon() {
Legs = 4; Heads = 3; Tails = 3;
}
}}


Здесь у нас есть два класса – Lizard(ящерица) и Dragon(дракон). Класс Lizard имеет три поля – legs, heads, tails (ноги, головы, хвосты) и свойства для работы с этими полями. Класс Dragon, являясь классом-наследником класса Lizard, просто использует наследованные свойства для установки собственных значений соответственных полей в своём конструкторе.

Инкапсуляция – это сокрытие данных от пользователя, с предоставлением ему методов (в классической версии) и свойств (например, в C#) для работы с ними. Проиллюстрируем сказанное на примере:

class PC {

private int numberCPU;
private string nameCPU;

public PC () {
numberCPU = 1;
nameCPU = "Pentium";
}
//использование метода для возврата имени процессора
public string CPUname()
{
return nameCPU.ToString().ToUpper();
}
//использование свойства для установки и чтения количества процессоров
public int CPUnumber {
get {return numberCPU;}
set {numberCPU = value;}
}
}

Неправильным, с классической точки зрения, подходом было бы объявление полей numberCPU и nameCPU как public-полей и, тем самым, предоставление к ним прямого доступа пользователя объекта класса PC. Почему? Потому что в этом случае возможно присваивание полю значения, непредусмотренного поведением класса, что может привести к непредсказуемому поведению объекта класса.

Полиморфизм , согласно Г.Бучу, состоит в том, что имена могут соответствовать различным классам объектов, входящих в один суперкласс. Следовательно, один объект, отмеченный таким именем, может по-разному реагировать на некоторое множество действий. Полиморфизм является самым существенным свойством объектно-ориентированного программирования. Проиллюстрируем сказанное на примере.

using System;
namespace hDrummer.Number4Polymorphism{
class Starter
{
[STAThread]
static void Main(string[] args) {
// создадим три объекта всех трёх классов
OneWordWriter w1 = new OneWordWriter();
TwoWordsWriter w2 = new TwoWordsWriter();
ThreeWordsWriter w3 = new ThreeWordsWriter();
w1.Write();
// вывод One
((OneWordWriter)w3).Write();
// вывод Three words written
((OneWordWriter)w2).Write();
// вывод Two words
}
}
class OneWordWriter {
public virtual void Write()
{
Console.WriteLine("One"); }
}

class TwoWordsWriter:OneWordWriter
{ public override void Write()
{
Console.WriteLine("Two words");
}
}

class ThreeWordsWriter :TwoWordsWriter {
public override void Write() {
Console.WriteLine("Three words written"); }
}
}

В этом примере мы создаём три класса, суперкласс OneWordWriter и подклассы TwoWordsWriter и ThreeWordsWriter, каждый из которых имеет метод Write(). Обратите внимание, что даже после приведения соответствующих объектов в методе Main к суперклассу OneWordWriter, каждый из них выполняет вызов своего метода Write(). Можно дополнить пример такой ситуацией:

ArrayList a = new ArrayList();
a.Add(w1);a.Add(w2);a.Add(w3);
foreach (OneWordWriter x in a) {
x.Write();
// вывод One
// вывод Two words
// вывод Three words written
}

Здесь мы помещаем все три объекта в коллекцию ArrayList и, перебирая её как коллекцию объектов суперкласса OneWordWriter(например, мы не знаем какие объекты и в каком порядке размещены в коллекции), вызываем для каждого из них метод Write() – для каждого объекта вызывается метод того класса, к которому он в действительности принадлежит.

На этом всё, желаю интересного чтения.

{К содержанию}

Обзор новостей

  1. Выпущен DeKlarit 3.0 RC
    Выпущен DeKlarit 3.0 RC (Release Candidate). Как обычно, доступна для скачивания бесплатная 30-дневная версия продукта. DeKlarit 3.0 содержит несколько новых, ключевых особенностей - поддержка Microsoft .NET Compact Framework, Microsoft SQL Server 2000 Windows CE Edition и Microsoft Access. Также отличается улучшенными возможностями контроля исходного кода.
    Дата выпуска: 09.01.2004 г.

  2. deloittes.NET AdServe - управление эдвертайзингом в ASP.NET
    deloittes.NET AdServe – гибкий инструмент для управления эдвертайзингом в среде ASP.NET & SQL Server. Веб-мастера сразу обратят внимание на интуитивно понятный интерфейс, предоставляющий доступ к инструментам создания баннеров, зон, ферм и предоставляющий детальные отчёты о проводимой кампании. Изящный дизайн поспособствует проведению наиболее требовательных и сложных рекламных мероприятий.
    Дата выпуска: 15.01.2004 г.

  3. Выпущен DotNetBar Suite 3.5
    Компания DevComponents LLC объявила о выходе DotNetBar Suite 3.5. В этом релизе добавлен компонент боковой панели инструментов с плоским стилем и 18-ю разными цветовыми схемами. Набор компонент DotNetBar включает меню, панели инструментов, боковые панели, компоненты подсказок и предупреждений, а также многие другие с полной поддержкой тем продуктов Microsoft Office 2003, XP, 2000 и Windows XP. DotNetBar – на 100% .NET компонент, написанный с использованием только управляемого кода.
    Дата выпуска: 15.01.2004 г.

  4. Elementool обновила веб-приложение для отслеживания ошибок
    Elementool, ведущий производитель веб-инструментов для компаний из списка Fortune 500, а также компаний, разрабатывающих ПО и дающих ИТ-консультации, выпустило последнее обновление к своему отладчику, позволяющему командам разработчиков отслеживать ошибки и сохранять целостность процесса разработки всего приложения.
    Дата выпуска: 13.01.2004 г.

  5. Выпущен InstantForum.NET v3.2
    Инструмент, разработанный на ASP.NET и SQL Server, и использующийся для создания онлайн- или внутрикорпоративных сообществ. В число новых особенностей в v3.2 входит список друзей/игнорируемых, сворачиваемые группы форума, навигация с использованием DHTML меню , отправка email, улучшенные профили пользователей и многое другое.
    Дата выпуска: 15.01.2004 г.
  6. Компания Middleware открыла TheServerSide.NET
    Компания Middleware открыла TheServerSide.NET, новый ресурс для разработчиков и архитекторов .NET, веб-ресурс, спонсируемый ведущими игроками рынка, в том числе и Microsoft. TheServerSide.NET, часть сообщества TheServerside.com, #1 независимого сообщества Java-разработчиков, предоставит разработчикам, использующим .NET новости, курсы, уроки, шаблоны дизайна, форум дл обсуждения и т.д.
    Дата выпуска: 12.01.2004 г.

{К содержанию}

C# vs Java vs C++ :: продолжение, начало см. в №3

Сравнительный обзор C#

ЯЗЫК: C#
Автор: Ben Albahari
Компания: Genamics
Дата: 31.07.2000, обновлено 10 Августа 2000.
Благодарности, в алфавитном порядке: Don Box, C.R. Manning, Joe Nalewabau, John Osborn, Thomas Rhode и Daryl Richter за их отзывы и поддержку

ПЕРЕВОД: Чужа В.Ф. ака hDrummer


Содержание

  1. C# и Java
  2. Свойства
  3. Индексаторы
  4. Делегаты
  5. События
  6. Перечисления
  7. Коллекции и Foreach
  8. Структуры
  9. Унификация типов
  10. Перегрузка операторов
  11. Полиморфизм
  12. Интерфейсы
  13. Версионность
  14. Модификаторы параметров
  15. Атрибуты
  16. Конструкции выбора
  17. Предопределённые типы
  18. Модфикаторы полей
  19. Конструкции перехода
  20. Сборки, пространства имён, уровни доступа
  21. Действия с указателями
  22. Прямоугольные массивы
  23. Конструкторы и деструкторы
  24. Управляемая среда выполнения
  25. Библиотеки
  26. Интероперабельность
  27. Выводы

11. Полиморфизм
Виртуальные методы позволяют объектно-ориентированным языкам реализовать полиморфизм. Это означает, что производный класс может содержать метод с той же сигнатурой, что и родительский класс и, будучи приведенным к родительскому классу, будет вызываться метод производного класса (т.е. свой собственный). Все методы в языке Java по умолчанию являются виртуальными. В C#, как и в C++, мы должны использовать ключевое слово virtual для того, чтобы метод был вызван классом-родителем.
В C# также необходимо использовать ключевое слово override для указания того, что метод подменит собой виртуальный метод (или реализует абстрактный метод) родительского класса.

class B {
public virtual void foo () {}
}

class D : B {
public override void foo () {}
}

Попытка перегрузки невиртуального метода приведёт к ошибке компилятора, указывающей, что метод базового класса не является абстрактным, виртуальным или перегруженным.

class N : D {
public new void foo () {}
}
...
N n = new N ();
n.foo(); // вызывает метод foo класса N
((D)n).foo(); // вызывает метод foo класса D
((B)n).foo(); // тоже вызывает метод foo класса D
...

В отличие от языков C++ и Java, необходимость указания ключевого слова override делает код более понятным – можно проще определить, какие методы перегружены при просмотре исходного кода. Однако, необходимость использования виртуальных методов имеет как свои 'за', так и свои 'против'. Первое 'за' - немного увеличенная скорость выполнения по сравнению с неиспользованием виртуальных методов. Второе 'за' - ясное указание на то, какие методы должны быть перегружены. Однако это 'за' могут быть одновременно и 'против'. Сравните, например, опции по умолчанию при выходе из модификатора final языка Java и выходе из модификатора virtual в C++. Опция по умолчанию в Java может сделать вашу программу немного менее эффективной, а в C++ она может воспрепятствовать расширяемости, хоть и непредусмотренной, создателем базового класса.

12. Интерфейсы

Интерфейсы в C# подобны интерфейсам в Java, но могут быть использованы с большей гибкостью. Класс может явно реализовать интерфейс:

public interface ITeller
{
void Next ();
}

public interface IIterator
{
void Next ();
}

public class Clark : ITeller, IIterator
{
void ITeller.Next () {
}
void IIterator.Next () {
}}

Это даёт классам два преимущества. Во-первых, класс может реализовать несколько интерфейсов без необходимости заботиться о конфликте имён. Во-вторых, это позволяет классу 'прятать' метод, если он не нужен обычным пользователям класса. Явный вызов методов происходит только при явном приведении объекта класса к необходимому интерфейсу:

Clark clark = new Clark ();
((ITeller)clark).Next();


13. Версии

Разрешению проблем связанных с разными версиями файлов библиотек с одинаковыми именами было уделено большое внимание в платформе .NET. Большинство решений так или иначе касается сборок (assemblies). С ними связаны некоторые совершенно впечатляющие возможности – например одновременное исполнение нескольких версий одной и той же сборки в одном процессе.

Язык C# предохраняет от отказов программного обеспечения при создании новых версий кода (особенно это касается библиотек .NET). В спецификации языка C# это описано более подробно, здесь же я покажу все аспекты этой проблемы на одном примере.

Предположим, что мы развёртываем класс D, написанный на языке Java, у которого есть класс-предок, распространяемый с VM, называемый B. Класс D имеет метод foo, а класс B на момент развёртывания такого метода не имеет. Позднее было сделано обновление класса B и теперь он тоже имеет метод foo, а также установлена новая виртуальная машина на том компьютере, на котором уже установлена программа, использующая класс D. Программа, использующая класс D, может рухнуть, поскольку новая реализация класса B будет выполнять виртуальный вызов класса D, выполняя действие, непредусмотренное классом B. В C#, метод foo класса В был бы объявлен без модификатора override (указывающего на намерения программиста), поэтому библиотека времени выполнения поняла бы, что метод foo класса D прячет метод foo класса В, а не перегружает его.

Интересное замечание из руководства по языку C#: "C# решает проблему версионности путём требования от разработчика ясно указывать свои намерения". И хотя использование слова override и есть одним из путей проявления намерения, оно могло бы быть автоматически сгенерировано компилятором путём проверки – действительно ли метод выполняет перегрузку (а не только декларирует её) во время компиляции. Это значит, что можно было бы писать на Java-подобных языках (у которых не т ключевых слов virtual и override), корректно справляясь с проблемой версионности.

14. Модификаторы параметров

модификатор параметра "ref"

C# (в отличие от Java) позволяет передавать параметры по ссылке. Наиболее простой и понятный пример, иллюстрирующий преимущества этого подхода, это пример метода обмена значениями . В отличие от C++, вы должны указывать модификатор ref как при вызове, так и при объявлении метода, принимающего параметр по ссылке:

public class Test
{
public static void Main ()
{
int a = 1;
int b = 2;
swap (ref a, ref b);
}

public static void swap (ref int a, ref int b) {
int temp = a;
a = b;
b = temp;
}
}

модификатор "out"

Существует также ключевое слово "out", которое является естественным дополнением к модификатору ref. В то время как модификатор ref требует явного присвоения перед передачей в метод, модификатор out требует того, чтобы метод явно присваивал значение параметру перед возвращением.

модификатор "params"

Модификатор params может быть прибавлен к последнему параметру метода – в этом случае метод принимает любое число параметров этого типа. Например:

public class Test
{
public static void Main () {
Console.WriteLine (add (1, 2, 3, 4).ToString());
}

public static int add (params int[] array) {
int sum = 0;
foreach (int i in array)
sum += i;
return sum;
}
}

Одной из наиболее неожиданных вещей при изучении Java является тот факт, что в этом языке нет возможности передавать переменные по ссылке. Однако, немного попрактиковавшись, вы замечаете, что пишите код, который не нуждается в этом. Когда я первый раз читал спецификацию языка C#, я часто думал "Зачем они придали ту или иную функциональность, ведь я могу писать и без этого". Оглядываясь назад, я понял, что это не аргумент для указания того, что некоторая функциональность бесполезна, скорее это показатель того, что вы были поставлены в такие условия, когда вам приходилось обходиться без этих возможностей.

По сравнению с С++ в языке Java упрощена передача параметров. В C++ параметры метода как в объявлении метода, так и в вызове метода, могут передаваться как по ссылке так и по значению, что, в совокупности с наличием указателей, может привести к ненужной сложности кода. C# требует явного указания передачи по ссылке что при декларации метода, что при вызове метода, снимая всякие сомнения по поводу происходящего, достигая тех же целей, что и с помощью языка Java, но с большей выразительностью. Действительно, языку C# не свойственно ставить препоны программисту, вынуждая последнего искать обходные пути для достижения чего-либо. Помните те наставления по языку Java, которые, чтобы обойти необходимость передачи по ссылке, вынуждали вас передавать одноэлементный массив для хранения вашего значения или создавать дополнительный класс, хранящий это значение?

15. Атрибуты

Как C#, так и Java содержат такую информацию, как уровень доступа к полю в скомпилированном коде. В C# существует более широкий подход, расширяющий эту особенность таким образом, что вы можете компилировать свою, пользовательскую информацию практически о любом элементе кода, таком как класс, метод, поле и т.п. Эта информация доступна во время выполнения программы или сборки. Вот простой пример класса, использующего атрибуты:

[AuthorAttribute ("Чебурашка")]
class A
{
[Localizable(true)]
public String Text {
 get {return text;
}
...
}}

Java использует комбинацию /** */ и комментарии @tag для добавления дополнительной информации о классах и методах, но эта информация (за исключением @deprecated) не встраивается в байт-код. C# использует предопределённые атрибуты - ObsoleteAttribute для того, чтобы компилятор мог предупредить вас об устаревшем коде, (как и @deprecated), и ConditionalAttribute для использования условно-зависимой компиляции. Новые XML-библиотеки Microsoft используют атрибуты для того, чтобы показать как поля могут быть сериализованы в XML, что означает возможность быстрого превращения класса в XML и назад. Ещё одним хорошим примером применения атрибутов является создание действительного мощного браузера классов. В руководстве по языку C# разъясняется как правильно создавать и использовать атрибуты.

16. Оператор switch

C# позволяет управлять конструкцией switch с помощью целочисленных типов, типа char, enum или (в отличие от C++ и Java) string. В Java и C++ если вы не поставите break после каждого опреатора case, вы рискуете получить выполнение следующего оператора case. Не знаю, почему такое сомнительное поведение сделано поведением по умолчанию в Java и C++. В то же время я рад, что C# не позволяет делать такие вещи.

17. Предопределённые типы

Простые типы в C# практически ничем не отличаются от таких же типов в Java. Единственное отличие – наличие беззнаковых типов. В C# есть такие простые типы, как sbyte, byte, short, ushort, int, uint, long, ulong, char, float и double. Единственным сюрпризом можно считать появление 12-байтового типа "decimal" – типа с плавающей точкой, который может использовать преимущества самых современных процессоров и рекомендуется для использования в вычислениях, связанных с деньгами.

18. Модификаторы поля

Модификаторы полей практически такие же как и в Java. Для указания полей, которые не могут быть модифицированы, в C# используются модификаторы const и readonly. Модификатор const подобен модификатору final в языке Java и компилируется так, что его значение фактически является частью IL кода. Модификатор readonly компилируется так, что значение поля с таким модификатором вычисляется во время выполнения. Что даёт возможность обновления, например одной из стандартных библиотек языка C#, без необходимости переделки вашего приложения.

19. Операторы перехода

Здесь немного сюрпризов, может быть кроме некоторыми нелюбимого оператора goto. Однако он имеет весьма дальние родственные связи с тем коварным оператором goto, который мы помним по Бэйсику 20-летней давности. Оператор goto должен указывать на метку или один из вариантов в конструкции switch. Использование перехода на метку похоже на использование конструкции continue : метка в языке Java, разве что с немного более расширенными возможностями. Такой оператор goto может указывать куда угодно в своей области видимости, что ограничивает его методом, где он используется или блоком finally, если такой существует. Он не может перепрыгнуть в тело цикла, если сам не находится в нём, а также не может покинуть конструкцию try до исполнения блока finally. Оператор continue в C# эквивалентен оператору continue в Java, за исключением невозможности перехода к метке.

20. Сборки, пространства имён и уровни доступа

В C# вы можете организовать составные вашего исходного кода (классы, структуры, делегаты, перечисления и т.д.) в файлы, пространства имён и сборки.
Пространства имён – это не более чем способ подсластить использование длинных имён классов. Например, вместо того, чтобы использовать класс Genamics.WinForms.Grid вы можете объявить этот класс как Grid и заключить его в:


namespace Genamics.WinForms {
public class Grid {
....
}
}

В тех классах, где используется класс Grid, вы можете импортировать его с указанием ключевого слова "using", вместо указания полного имени Genamics.WinForms.Grid.

Сборки – это файлы .exe или .dll, сгенерированные из файлов проекта. .NET использует настраиваемые атрибуты и правила версионности, встроенные в сборки, для упрощения развёртывания программы – больше никакого взаимодействия с реестром – просто копируем сборку в каталог и всё. Сборки также способствуют разрешению конфликтов имён типов, вплоть до того, что несколько версий одной сборки сосуществуют в рамках одного процесса. Каждый файл может содержать множество классов и пространств имён. Пространство имён также может существовать в нескольких сборках. Подводя итог, можно сказать, что эта система даёт программисту высокую степень свободы в выборе решения.

В языке C# есть пять уровней доступа - private, internal, protected, internal protected и public. Private и public имеют такое же значение как и в Java, правда в C# уровень доступа по умолчанию это private, а не упаковка. Internal обеспечивает доступ в сборках, а не в пространствах имён, (что несколько похоже на Java). Internal protected аналогичен protected в Java, а protected аналогичен уровню private protected в Java, который некоторое время назад стал считаться устаревшим.

{К содержанию}

Время кода

Глобальная обработка исключений в приложениях ASP.NET

ЯЗЫК: C#
ВЕРСИИ ASP.NET: 1.0 | 1.1
АВТОР: Bipin Joshi,
http://www.dotnetbips.com/
ПЕРЕВОД: Чужа В.Ф ака hDrummer

Проблема
В ответ на ошибку времени выполнения приложения ASP.Net происходит возникновение исключения. Исключения предоставляют сотни преимуществ по отношению к модели обработки ошибок в классическом ASP. Например, ошибки являются объектами, есть возможность отлавливать ошибки в зависимости от их типа, присутствует лёгкость реализации структурированной обработки ошибок.
Однако в каждом приложении присутствуют ситуации, когда исключения не отлавливаются и в результате приводят к выводу на экран уродливой страницы с сообщением об ошибке, принятой в ASP.NET по умолчанию (Я бы назвал её красно-коричневая чума – прим. переводчика).
Отсюда возникает вопрос: каким образом сделать так, чтобы пользователь в любом случае видел вашу страницу с сообщением об ошибке, а не страницу, выводимую в случае возникновения исключения по умолчанию?

Решение
Всё это можно сделать, добавив пару строк кода в нужные места файла Global.asax. Если вы не знакомы с этим файлом, то знайте, что он содержит методы, обрабатывающие события уровня приложения и сессии. Например, такие, как старт приложения (Application_Start), начало пользовательской сессии (Session_Start), и некоторые другие.
Объектом нашего внимания в этой статье будет метод Application_Error, выполняющийся в том случае, если исключение не проходит обработку в коде вашего приложения. Процесс обработки таких исключений выглядит таким образом:
  • создадим веб-форму с названием error.aspx, она и будет вашей страницей с сообщением об ошибке;
  • в Global.asax.cs отловим последнее возникшее исключение;
  • вызовем InnerException из исключения, пойманного выше. Это делается потому, что в случае возникновения необработанного исключения, .Net создаёт для него 'обёртку' из нового исключения типа HttpUnhandledException;
  • поместим несколько значений в объект Session, для того, чтобы получить их на своей странице обработки ошибок;
  • обнулим ошибку на сервере;
  • перенаправим пользователя на свою страницу error.aspx.

Код Global.asax.cs

Следующий листинг демонстрирует код, необходимый для достижения вышесказанного:

protected void Application_Error(Object sender, EventArgs e) {
try {
//установка значений по умолчанию
Session["ErrorMsg"] = "Нет информации об обшибке";
Session["ExceptionType"] = String.Empty;
Session["PageErrorOccured"] = Request.CurrentExecutionFilePath;
Session["StackTrace"] = String.Empty;
//ловим последнее возникшее исключение
Exception lastError = Server.GetLastError();
if (lastError != null)
{
//вытягиваем InnerException
lastError = lastError.InnerException;
//Записываем значения в переменные объекта Session для дальнейшего использования
Session["ErrorMsg"] = lastError.Message;
Session["ExceptionType"] = lastError.GetType().ToString();
Session["StackTrace"] = lastError.StackTrace; }
// Обнуление ошибки на сервере
Server.ClearError();
// Перенаправление на свою страницу отображения ошибки
Response.Redirect("error.aspx");
}
catch (Exception ex) {
// если мы всё же приходим сюда - значит обработка исключения
// сама сгенерировала исключение, в этом случае мы ничего не делаем, чтобы
// не создать бесконечный цикл

Response.Write("К сожалению произошла критическая ошибка. Нажмите кнопку 'Назад' в браузере и попробуйте ещё раз. ");
}
}

Наша страница error.aspx

Вот что мы должны сделать в нашей странице error.aspx:
  • Добавить на неё метку и назвать её lblMessage.
  • Собрать информацию об исключении, которая была помещена в объект Session в Global.asax.cs.
  • Очистить значения для текущей сессии.
  • Отобразить общее сообщение об ошибке пользователю. Можно даже добавить ссылку на страницу, вызвавшую ошибку.
  • Добавить конкретное сообщение об ошибке как HTML-комментарий для использования во время разработки. Этот код должен быть убран при сдаче приложения в эксплуатацию.
В метод Page_Load файла error.aspx.cs, поместим следующее:

private void Page_Load(object sender, System.EventArgs e) {
try {
if (!Page.IsPostBack) {
// соберём информацию об исключении из сессии
string errorMsg = Session["ErrorMsg"].ToString();
string pageErrorOccured = Session["PageErrorOccured"].ToString();
string exceptionType = Session["ExceptionType"].ToString();
string stackTrace = Session["StackTrace"].ToString();
// очистим переменные сессии
Session["ErrorMsg"] = null;
Session["PageErrorOccured"] = null;
Session["ExceptionType"] = null;
Session["StackTrace"] = null;
//отобразим пользователю общее сообщение об ошибке
lblMessage.Text = " К сожалению, произошла ошибка выполнения приложения.";
lblMessage.Text = String.Format("{0} Чтобы попробовать ещё раз, кликните <A href="{1}"> здесь</A>.", lblMessage.Text, pageErrorOccured);
//добавим конкретное сообщение об ошибке для просмотра во время разработки
//здесь же можно добавить запись ошибки в журнал событий Windows
lblMessage.Text = lblMessage.Text + "<!--\n"+
"Error Message: " + errorMsg +"\n"+
"Page Error Occurred: " + pageErrorOccured + "\n"+
"ExceptionType: " + exceptionType +"\n"+
"Stack Trace: " + stackTrace + "\n"+ "-->";
}
}
catch (Exception ex) {
//если исключение вызвано кодом, написанным выше
//выведем сообщение об ошибке и StackTrace

lblMessage.Text = ex.Message+" "+ex.StackTrace;
}
}

Для проверки выше приведённого кода можно добавить в проект страницу и добавить следующую строку в метод Page_Load:

private void Page_Load(object sender, System.EventArgs e) {

   throw new Exception("Что-то не работает...");

}

В результате выполнения этой страницы получим редирект на страницу с сообщением об ошибке и ссылкой на страницу-источник исключения.

Вывод
Плохо, когда пользователь в работе с приложением натыкается на ошибки, но ещё хуже, если пользователь видит непонятное сообщение об ошибке или уродливую страницу, выводимую по умолчанию. Используя приёмы, показанные в этой статье, вы сможете отобразить приличное сообщение на приличной странице, вне зависимости от того, какая ошибка произошла.

{К содержанию}

Форумы .Net - вопросы оставшиеся без ответа

ADO: Fetch u Cancel
Доступ с КПК к MSSQL server 
Сломался .NET
Какие компоненты лутше Infragistic или DevExpress
нужна помощь
Почему HTMLInputFile Control не воспринимает accept
Помогите с ASPError
WinForms: Проблема с DataBinding для двух ComboBox-ов
DataBinding
Ввод мат. формулы
Навигатор

На этом четвертый выпуск .Net Собеседника закончен.
До следующего номера.


Чужа Виталий Ф. aka hDrummer,
hdrummer@mail.ru - жду ваши предложения, вопросы и замечания.


Рассылки Subscribe.Ru
.Net Собеседник - Новости мира Net, C#, ASP.Net


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное