El famoso error: "System.ServiceModel.FaultException'1
was not handle by user code" cuando trabajamos con WCF.
Introducción:
Si alguna vez has trabajado con WCF estoy
seguro que te debes haber topado con este error, y si no, tuviste demasiada
suerte.
Lo primero que piensas es que algo en tu código
esta mal o que el try-catch no esta capturando la excepción. Y comienzas a
modificar y agregar mas código para poder controlar ese error y terminas con
mas código de manejo de error que de lógica propia del servicio.
Administrar correctamente procesos de manejo
de errores en una aplicación es una pesadilla si quieres hacerlo bien. Yo diría
que no es exactamente la parte mas emocionante, pero es realmente necesario
para prevenir cualquier situación no manejada.
En una aplicación normal basta con colocar tu
código dentro del bloque try-catch con el tipo de excepción, y esta se manejara
como una excepción .net normal que usted puede manejar.
Con servicios WCF esto se maneja un poco
diferente, simplemente porque WCF tiene que garantizar la interoperabilidad con
cualquier aplicación cliente con el fin de que sean capaces de capturar el
error devuelto.
Para eso WCF necesita convertir la “excepción
.net normal” en un mensaje de excepción SOAP que pueda ser comprendido por
cualquier aplicación cliente.
El FaultContract:
Para conseguir convertir la “excepción .net normal”
en un mensaje de excepción SOAP, es necesario especificar un atributo
FaultContract en su servicio, ya sea de forma declarativa o imperativa. Para mi
caso de ejemplo lo he hecho de manera declarativa.
Se debe especificar un atributo FaultContract
por cada método de su servicio que desee controlar.
[OperationContract]
[FaultContract (
typeof
(MyError))]
Boolean myMethod();
MyError es un tipo personalizado que define un mensaje de
error.
Después de haber configurado el atributo FaultContract del servicio, lo siguiente que necesita es
convertir la “excepción .net normal” en un mensaje de excepción
SOAP en el método del servicio del lado del servidor como sigue:
Código del lado del servicio:
catch
(Exception ex)
{
var ErrLog =
new
MyError (“This
is
an error”,”Critical”);
var fe =
new
FaultException<MyError> (ErrLog,
new
FaultReason(ErrLog.Message));
throw
fe;
}
Código del lado del cliente:
Desde el lado de la aplicación cliente
simplemente necesita capturar el tipo de error FaultException como normalmente
recupera un mensaje de el servicio SOAP de la siguiente manera:
catch
(FaultException<MyError> myError)
{
var
msg = myError.Detail.Message;
MessageBox.Show(msg);
wcfclient.Close();
}
A continuación usted debería recibir un
mensaje de error enviado desde su servicio, dentro de su aplicación cliente
pero… esto no esta funcionando exactamente como usted esperaba. Es aquí donde
me pase muchos días verificando mi código y la manera como había implementado
mi manejo de excepción y todo estaba correcto, pero cuando ejecutaba mi aplicación
y mi servicio y enviaba un solicitud a mi servicio esta se detenía cada vez que
lanzaba la excepción (throw fe). El error retornado por el servicio era
muy extraño era como:
“System.ServiceModel.FaultException`1 was unhandled by user code“
Después de mucha investigación pude encontrar
la solución con el Dr. Google, este error era debido a unas opciones marcadas
por defecto en la sección de Debugging del Visual Studio que hace que la ejecución
de mi código se pare cada vez que hay una excepción que no tiene una lógica verdadera
en el mensaje. Esto me genero mucha confusión.
Deshabilitando el error:
Para deshabilitar este comportamiento debemos
desactivar las siguientes 2 opciones del Visual Studio. Para eso vamos al menú Tools
=> Options y en la ventana que nos aparece nos ubicamos en la sección del
lado izquierdo: Debugging => General y desmarcamos las opciones:
Enable the exception assistant
Enable Just My Code (Managed only)
Y damos click en Ok
Ahora vuelvan a ejecutar el servicio y su aplicación
cliente y todo debería funcionar correctamente.
Espero con esto poder ahórrales algunas horas
o días :)
No hay comentarios:
Publicar un comentario