10.04.2010

WCF y Excepciones – Parte 2 - FaultContracts

Siguiendo con el post anterior relacionado con el manejo de excepciones en WCF en este post vamos a trabajar con excepciones personalizadas en WCF. Como vimos anteriormente, las excepciones en WCF no se propagan porque WCF no entiende de excepciones. Igualmente, debemos recordar que utilizamos Fault Messages para poder retornar un error más legible al cliente. En este post vamos a atacar el caso en donde queremos propagar la excepción lanzada en .NET desde el servicio al cliente.

Problema: Excepciones Personalizadas

Existen casos en donde por la naturaleza del error, no es posible enviar simplemente un FaultException del lado del cliente para que el mismo la maneje, si no que se requiere enviar más información de vuelta al cliente de forma encapsulada. Este tipo de excepciones es posible llevarlas a cabo en WCF utilizando los FaultContracts.

Para entender mejor la solución al problema vamos a trabajar con un ejemplo. Supongamos que deseamos enviar de vuelta un error al cliente con un código de error interno, el cual tiene un significado relevante para el cliente. Esto por supuesto sumado al código de error y a la descripción del mensaje.

En primer lugar debemos crear un contratopara representar nuestro nuevo tipo de excepción, el cual será una clase etiquetada con el Atributo DataContract para que pueda ser serializada en WCF. El código de esta clase se puede ver en el siguiente listado:

using System.Runtime.Serialization;

namespace WFCErrorManagment
{
[DataContract]
public class InvalidRequestCode
{
[DataMember]
public string InternalCodeError { get; set; }
}
}



El siguiente paso es especificar el tipo de excepción que queremos lanzar en la operación seleccionada.



[ServiceContract]
public interface IAuthenticationService
{
[OperationContract]
[FaultContract(typeof(InvalidRequestCode))]
bool AuthenticateUser(WcfUser user);
}



Con el paso anterior, vamos a tener la posiblidad de tener el tipo de la excepción del lado del cliente, es decir, el contrato de error estará del lado del cliente para su manipulación. Seguidamente procedemos a lanzar la excepción desde la implementación del servicio.



using System.ServiceModel;

namespace WFCErrorManagment
{
public class AuthenticationService : IAuthenticationService
{
public bool AuthenticateUser(WcfUser user)
{
InvalidRequestCode request = new InvalidRequestCode { InternalCodeError = "ERR1002" };
throw new FaultException<InvalidRequestCode>(request);

}
}
}



A diferencia del FaultContract del post anterior, esta vez procedemos a crear una instancia de la clase personalizada con la que vamos a manejar el error y seguidamente procedemos a lanzar una excepción generica del tipo InvalidRequestCode que es el tipo del DataContract definido para manejar el error.



Para probar el funcionamiento del código anterior, vamos a crear un cliente utilizando VB.NET – por aclamación :) – para consumir el error y manejarlo apropiadamente en el cliente. En primera instancia hacemos una referencia la servicio, seguidamente creamos una instancia del proxy y procedemos a escribir el código que nos servirá para procesar el error.



Imports WCF_BlogClient.SRExceptionTest
Imports System.ServiceModel

Module Module1

Sub Main()
Try
Dim
cliente As New AuthenticationServiceClient
cliente.AuthenticateUser(New WcfUser())

Catch ex As FaultException(Of InvalidRequestCode)
Console.WriteLine("Error invocando el servicio. Código del error: {0}", ex.Detail.InternalCodeError)
End Try


End Sub

End Module



Como pueden ver en el código anterior, tenemos acceso a la clase InvalidRequestCode que fue creada en el server, la cual sin embargo, al ser un DataContract y al ser utilizada por el FaultException termina siendo exportada al proxy para que el cliente tenga acceso a ella. Al ejecutar el código anterior con el servicio corriendo obtenemos la siguiente pantalla:



image



Technorati Tags: ,,,,

1 comentario:

Unknown dijo...

Hola,

Felicitaciones por el artículo, muy interesante.

Una pregunta. Hice lo que tienes, pero al cliente me regresa un mensaje "El servidor remoto devolvió un error: NotFound."
Quizá haya algo más que no consideré? Estoy usando con Silverlight

Gracias de antemano