You are on page 1of 8

Gestión de una aplicación completa con .

NET
Servicio de Informática

TEMA 7: ERRORES
1. CONCEPTOS PREVIOS
Durante este tema se van a tratar de 2 tipos de errores: los de ejecución y los lógicos.
Ignoramos los errores de compilación.

De ejecución: Son las excepciones que aparecen en tiempo de ejecución como por
ejemplo la incapacidad de abrir la base de datos.

De compilación: Son errores que Visual Studio nos señala al compilar la página.
Suelen ser faltas semánticas o sintácticas en el código.

Lógicos: Cuando el resultado aparecido no es el esperado. Por ejemplo cuando


cargamos un usuario inexistente. No dará error, pero no aparece el registro esperado.

2. ERRORES EN LAS CLASES INDEPENDIENTES


Siguiendo la guía de programación del Servicio de Informática de la UA tenemos la
obligación de incorporar una propiedad pública llamada “Debug”. Esta propiedad de
solo lectura incorporará los mensajes de error o de atención de los métodos. Será solo
útil para el programador.

ERRORES LÓGICOS
Así, si por ejemplo, si se intenta cargar un usuario vacio Debug recogerá el mensaje
“no se ha encontrado al usuario”. Esto se envía como un aviso (un warning) y será
responsabilidad de la página apsx que haga uso de este método el que gestione el
aviso. La clase no lanzará excepción.

Ejemplo:
Supongamos estas 2 clases:

using System;
public class ClaseAnimal
{
private string _debug;
public int Identificador { get; set; }
public string Nombre { get; set; }
public string Debug { get { return _debug; } }

public ClaseAnimal Carga(int Animal)


{
ClaseAnimal MiAnimal = new ClaseAnimal();
MiAnimal = ClaseAnimales.Todo().Find(
delegate(ClaseAnimal ca)
{
return (ca.Identificador== Animal);
});
//Si encuentra animal devuelvelo
if (MiAnimal != null)
return MiAnimal;
else
{

Tema 4 / Página 1
Gestión de una aplicación completa con .NET
Servicio de Informática

//Si no Debug toma valor y devuelvo un animal sin datos


_debug += "No se ha encontrado el animal";
return new ClaseAnimal {Identificador=0, Nombre="" };
}
}
}

using System.Collections.Generic;
public static class ClaseAnimales
{
public static List<ClaseAnimal> Todo()
{
ClaseAnimal Animal = new ClaseAnimal();
List<ClaseAnimal> Animales = new List<ClaseAnimal> {
new ClaseAnimal {Identificador=1, Nombre="Elefante"},
new ClaseAnimal {Identificador=2, Nombre="Tigre"}
};
return (Animales);
}
}

En este ejemplo un aspx como el que sigue:


<form id="form1" runat="server">
<div>
<asp:Label ID="Label1"
runat="server" Text="Label"></asp:Label>
<asp:TextBox ID="TextBox1" runat="server"
ontextchanged="TextBox1_TextChanged"></asp:TextBox>
</div>
</form>

Con este cs asociado


protected void TextBox1_TextChanged(object sender, EventArgs e)
{
ClaseAnimal MiAnimal = new ClaseAnimal();
string nombre = MiAnimal.Carga(
int.Parse(TextBox1.Text)).Nombre;

//La variable debug me sirve para determinar si todo ha ido ok


if (MiAnimal.Debug != null)
Label1.Text = MiAnimal.Debug;
else
Label1.Text = nombre;
}

Dará como resultado una página html que buscará un animal por su código. En caso
de no encontrarlo pondrá el mensaje que arrastra del cs de animal.

ERRORES DE EJECUCIÓN

Otra posibilidad es que tengamos previsión que en la clase se dé un error. Por ejemplo
que no se encuentre un fichero a leer o que la base de datos esté caída. Si esto no

Tema 4 / Página 2
Gestión de una aplicación completa con .NET
Servicio de Informática

funciona la aplicación no podrá continuar. En este caso el Debug recogerá algo como
“No se ha encontrado el fichero buscado en… “ y después lanzará una excepción con
un texto tal como “fichero no encontrado”. Esta excepción tendrá que ser tratada en la
página aspx.

Para controlar este tipo de errores se usa try-catch-finally

Cuando queramos controlar una parte del código que puede producir un error lo
incluimos dentro del bloque try, si se produce un error, éste lo podemos detectar en el
bloque catch, por último, independientemente de que se produzca o no una excepción,
podemos ejecutar el código que incluyamos en el bloque finally.

Cuando creamos una estructura de control de excepciones no estamos obligados a


usar los tres bloques, aunque sí el primero. Podemos crear un "manejador" de
excepciones usando los tres bloques, usando try y catch o usando try y finally.

Bloque try
En este bloque incluiremos el código en el que queremos comprobar los errores. En el
momento que se produzca el error se usará (si hay) el código del bloque catch.

Bloque catch
Si se produce una excepción, ésta la capturamos en un bloque catch.
En el bloque catch podemos indicar que tipo de excepción queremos capturar, para
ello usaremos una variable de tipo Exception, la cual puede ser del tipo de error
específico que queremos controlar o de un tipo genérico.

try
{
// código para trabajar con ficheros, etc.
}
catch(System.IO.IOException ex)
{
// el código a ejecutar cuando se produzca ese error
}

Si nuestra intención es capturar todos los errores que se produzcan podemos usar la
clase Exception como tipo de excepción a capturar. Es la más genérica de todas las
clases para manejo de excepciones, por tanto capturará todas las excepciones que se
produzcan.

try
{
// código que queremos controlar
}
catch(System.Exception ex)
{
// el código a ejecutar cuando se produzca cualquier error
}

La variable indicada en el bloque catch (ex) la podemos usar para mostrar un mensaje
al usuario o para obtener información extra sobre el error.

Tema 4 / Página 3
Gestión de una aplicación completa con .NET
Servicio de Informática

Pero si no vamos usar la variable indicada en el bloque Catch, pero queremos que no
se detenga la aplicación cuando se produzca un error, podemos hacerlo de esta
forma:

try
{
// código que queremos controlar
}
catch
{
// el código a ejecutar cuando se produzca cualquier error
}

Varias capturas de errores en un mismo bloque try/catch


En un mismo try/catch podemos capturar diferentes tipos de errores, para ello
podemos incluir varios bloques catch, cada uno de ellos con un tipo de excepción
diferente.

Es importante tener en cuenta que cuando se produce un error y usamos varios


bloques catch, el CLR de .NET buscará la captura que mejor se adapte al error que se
ha producido, pero siempre lo hará examinando los diferentes bloques catch que
hayamos indicado empezando por el indicado después del bloque try, por tanto
deberíamos poner las más genéricas al final, de forma que siempre nos aseguremos
de que las capturas de errores más específicas se intercepten antes que las
genéricas.

En el siguiente código capturamos un error específico y también uno genérico, con


idea de que tengamos siempre controlado cualquier error que se produzca:

try
{
// código que queremos controlar
}
catch(FormatException)
{
// captura de error de formato
}
catch(Exception ex)
{
// captura del resto de errores
}

Bloque finally
En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se
produzca o no una excepción. De esta forma nos aseguramos de que siempre se
ejecutará un código, por ejemplo para liberar recursos, se haya producido un error o
no.

Nota:

Tema 4 / Página 4
Gestión de una aplicación completa con .NET
Servicio de Informática

Hay que tener en cuenta de que incluso si usamos return dentro de un bloque de
control de errores, se ejecutará el código indicado en el bloque finally.

Ejemplo:

using System;
public class Util
{
private string _debug;
public string Debug { get {return _debug;}}
public string Lee()
{
const string fic = @"E:\tmp\Prueba.txt";
string texto;

try
{
System.IO.StreamReader sr =
new System.IO.StreamReader(fic);
texto = sr.ReadToEnd();
sr.Close();
}
catch (Exception e)
{
_debug +=
"Fichero " + fic + " no encontrado " + e.Message;
throw new Exception("Fichero no encontrado");
}
finally
{
//Para cuando necesite cerrar algo
}
return texto;

}
}

Y en el cs asociado a nuestro aspx pondremos:

protected void Page_Load(object sender, EventArgs e)


{
Util miUtil = new Util();
try
{
string texto = miUtil.Lee();
Label1.Text = texto;
}
catch
{
throw new Exception ("ERROR " + miUtil.Debug);
}
}

Pero evitaremos que de un error de color amarillo en la pantalla del usuario. Por ello
trataremos al error según se explica en el punto siguiente.

Tema 4 / Página 5
Gestión de una aplicación completa con .NET
Servicio de Informática

3. ERRORES EN CLASES CS ASOCIADOS A ASPX


Para tratar ambos errores (lógicos y de ejecución) vamos a seguir las siguientes
pautas:

1.- Incorporamos la referencia “ClaseErrores.dll” de la carpeta ToolsNet/DLL.

2.- Incorporamos global.aspx y ponemos en la segunda línea:


<%@ Import Namespace="ua" %>

Y en la sección de application_error:

void Application_Error(object sender, EventArgs e)


{
// Código que se ejecuta al producirse un error no controlado
ClaseErrores miError = new ClaseErrores(true);
// Si ponemos false no se ofrecerá información sobre la pila
// Si ponemos ClaseErrores(true, true) obligamos a enviar el
error por correo.
}

3.- Como estamos en un entorno local deberemos crear una carpeta ToolsNet dentro
de nuestro sitio web. Dentro pondremos un fichero “ruta.xml”. Ese fichero contendrá:
<?xml version="1.0" encoding="UTF-8"?>
<ERRORES actualizado="8/24/2009">
<PATH path="~" descripcion="Ejemplo" id="9">
<EMAIL idhijo="5">direccion.correo@ua.es</EMAIL>
</PATH>
</ERRORES>

ERRORES DE EJECUCIÓN
Ahora si se produce un error de ejecución como throw new Exception ("ERROR
" + miUtil.Debug); se pintará en pantalla un mensaje como:

Tema 4 / Página 6
Gestión de una aplicación completa con .NET
Servicio de Informática

En caso de estar en un entorno de producción (o de haber obligado a enviar el error


por correo) ese mensaje se enviará al correo indicado y en pantalla se mostrará el
típico “Error inesperado”.

ERRORES LÓGICOS
Podemos generar errores cuando algo inesperado ocurra, pero que no hace falta que
se corte el flujo del programa.

Por ejemplo, si el usuario que se está buscando no se encuentra se puede indicar con
un mensaje. Y nos puede interesar que ese error se envíe por correo.

using System;
using ua;

public partial class _Default : System.Web.UI.Page


{
ClaseErrores miError = new ClaseErrores();
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
ClaseAnimal MiAnimal = new ClaseAnimal();
string nombre =
MiAnimal.Carga(int.Parse(TextBox1.Text)).Nombre;

//La variable debug me sirve para determinar si todo ha ido ok


if (MiAnimal.Debug != null)
{
//Determina si el error se envia por correo
miError.Envio = true;
//El programa continua y envía error
ControlError.PararEnviaError = false;

//Se envia correo y se para la ejecución del programa


miError.EnviaError(
"El usuario esta buscando " + TextBox1.Text, -1000);
}
else
Label1.Text = nombre;
}

Si añadimos ControlError.PararEnviaError = false; convertimos el error en una aviso,


es decir, que el error no saldrá en la ejecución del programa pero se enviará por
correo al programador.

Tema 4 / Página 7
Gestión de una aplicación completa con .NET
Servicio de Informática

4. ENLACES INTERNET
Sobre manejo de excepciones:
http://www.zonacodigos.com/index.php/c/20-manejo-de-excepciones-

Sobre el componente claseerrores.dll


https://aplicacionesua.cpd.ua.es/programacion/verFicha.asp?ficha=724

5. EJERCICIO
Incorporar la gestión de errores en la aplicación.

Se proponen estos pasos:

1.- Incorporar la librería ClaseErrores.dll de ToolsNet.


2.- Copiar a una carpeta ToolsNet de nuestro sitio web ruta.xml y modificar el correo
electrónico.
3.- Incorporar un global.aspx y arreglar el application_error.

4.- En claseLocalizaciones incorporar una propiedad de solo lectura “Debug”. Controlar


los posibles errores de conexión de base de datos.

5.- En claseUsuario incorporar una propiedad de solo lectura “Debug”. Controlar


posibles errores de conexión de base de datos, de no localización de un usuario, de no
poder insertar un usuario y de no poder borrarlo.

6.- En el cs asociado al aspx mostrar estos errores en


“ContentPlaceHolderNoticias”. Estos errores serán sensibles al idioma.

7.- En claseLocalizaciones incorporar una propiedad de solo lectura “Debug”. Controlar


los posibles errores de conexión de base de datos.

Tema 4 / Página 8

You might also like