Manteniendo el estado con WCF (2 de 2)

En el post anterior hemos visto como mantener el estado y controlar las instancias que se crean de nuestro servicio.

Ahora vamos a ver como definir el orden en el que se pueden ejecutar los métodos de nuestro servicio. La idea es que el cliente no debe poder hacer un Checkout sin antes haber agregado algún producto a su carrito.

Hay una serie de propiedades «booleanas» del atributo OperationContract con nos permiten definir justamente esto:

IsInitiating
Si esta variable vale true el cliente puede usar este método como el primero, el que creará el servicio. Por defecto vale true, si la ponemos a false el cliente no va a poder usar este método si no ha ejecutado alguno (que pueda) antes. Al menos una de las propiedades de nuestro servicio tiene que tener esta propiedad a true.

IsTerminating
Si vale true el runtime de WCF terminará la sesión una vez ejecute el método y el cliente deberá crear una nueva conexión con el servicio una vez ejecute este método. El valor por defecto es false.

Para poder usar estas propiedades tenemos que cambiar otra propiedad, la propiedad SessionMode  del atributo ServiceContract de nuestro contracto. Para que funcionen estas propiedades el valor de SessionMode debe ser SessionMode.Required. Esta propiedad especifica si el servicio va a permitir o no sesiones robustas y fiables, pero no voy a entrar más en detalle, al menos en este post.

Para poner un pequeño ejemplo vamos a editar nuestro contrato:



<ServiceContract(SessionMode:=SessionMode.Required)> _
Public Interface IShoppingCart
    <OperationContract(IsInitiating:=True)> _
    Function AddItem(ByVal itemId As Integer) As Boolean
    <OperationContract(IsInitiating:=False)> _
    Function RemoveItem(ByVal itemId As Integer) As Boolean
    <OperationContract(IsInitiating:=False)> _
    Function GetShopingCart() As String
    <OperationContract(IsInitiating:=False, IsTerminating:=True)> _
    Function Checkout() As Boolean
End Interface

Antes de ejecutar el cliente debemos actualizar la referencia web, ya que al hacer esto la definición de la clase proxy que se crea para comunicarse con el servicio va a cambiar un poquito.

Si ahora descomentamos las líneas del cliente que ejecutan la función Checkout e intentan de nuevo acceder al servicio el sistema nos devolverá una excepción:

console


Lo que ha pasado es que al ejecutar la función Checkout, como esta marcada como IsTerminating, el servicio se ha destruido después de que el cliente ejecutara la función Checkout.

Si después de ejecutar al función Checkout volvemos a crear una conexión con el servicio, ya no da ese error:



‘…
Dim proxy As New ShoppingCartClient(«WsHttp_ShoppingCartEndpoint»)
Dim rand As New Random()
Dim result As Boolean = True
result = proxy.AddItem(rand.Next(0, 5))
result = proxy.AddItem(rand.Next(0, 5))
result = proxy.AddItem(rand.Next(0, 5))
result = proxy.AddItem(rand.Next(0, 5))
Console.WriteLine(proxy.GetShopingCart())
result = proxy.Checkout()
‘creamos una nueva conexión con el servicio
proxy = New ShoppingCartClient(«WsHttp_ShoppingCartEndpoint»)
proxy.AddItem(rand.Next(0, 5))
result = proxy.AddItem(rand.Next(0, 5))
Console.WriteLine()
Console.WriteLine(proxy.GetShopingCart())
‘…

console2


Si ahora intentamos ejecutar cualquier método del servicio sin haber ejecutado primero el método marcado como IsInitiating también nos da error; aunque la información de la excepción no es tan bonita como la de antes:


console3

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *