Ayer por la noche se organizaron diferentes eventos para los participantes del TechEd de cada país. Nosotros, los españolitos, fuimos a cenar a un restaurante del Diagonal Mar.
Yo me pude escapar y bajar a Barcelona para estar con mis compañeros por última vez durante este TechEd.
Vino muchísima gente; los chicos de MS, MVP's, MSP's, estudiantes, profesionales y demás fauna española. Me hizo ilusión ver a mis colegas de BcnDev (Buenas José Luís!), a Alfonso, a Rodrigo Corral, a David y a Miguel.
Como tenía que ser, compartí mesa con mis colegas de los clubes y nos llenamos de comida, de eso sobró cantidad. :) Hubo unas discusiones sobre política... , na, que me lo pase genial, como siempre que estoy con gente como vosotros. :)
Luego nos fuimos a tomar algo a la fiesta que se montó en Catwalk.
Lástima que me tuve que ir pronto, ya que vivo en Sant Cugat, y el último tren salía a las 00:04.
En flickr dejo las fotos de ayer, un bsote a tod@s.
Ojalá pudiera venir con vosotros los dos días que faltan y poder compartir más experiencias y tiempo, pero no va a ser posible. Muchas gracias por estar allí, que disfrutéis mucho y os lo paséis genial.
Muchas gracias a Ethel, Bea & co. por darme la oportunidad de vivir estas experiencias.
Hasta la próxima!
*crossposting desde Geeks.ms
Esta semana, como muchos sabéis, se está celebrando el TechEd en Barcelona. Como MSP tenía la oportunidad de asistir pero no se puede tener todo, así que me voy a tener que aguantar y disfrutar solo de los feedbacks que me dan mis compañeros, algunos vídeos y el material que nos pasarán.
Aunque ayer por la tarde se realizó el evento destinado a los MSP's que no me perdí. Cogí mi cochecito y me acerqué a ver a mis amigos de los clubes de España y a los compañeros MSP que nunca había conocido.
Fue genial; ver a tantos estudiantes motivados con las mismas aficiones e inquietudes que yo y ver la cantidad de 'monstruos de la tecnología' que había impresiona.
Lo primero a lo que fui fue a las charlas dirigidas para los MSP's sobre la comunidad, sobre los MSP's y los diferentes programas y actividades a los que podemos acceder, sobre el programa de los MVP's... aibá la hostia!!, hay un chico de 18 años que ya es MVP!!!. Como algunos sabéis no soy muy bueno con los nombres, vaya que tengo memoria de Dori para estos, por eso no pongo nombres. :P. También hubo un MVP que con cinco minutos de presentación le sobró tiempo para dejarnos impresionados... (Comentario de Ethel: "Y este que se ha comido hoy para estar así!"), fue im-pre-sionante!.
Bueno, luego nos fuimos todos a la bolera del centro comercial Diagonal Mar a "conocernos mejor" y, en mi caso, a "improve" mi inglés - para quien no lo sepa, yo hablo "catanglish", es algo más difícil de entender que el "spanglish". Fue divertido e instructivo hacerme entender con mis nuevos amigos.
Al final en mi equipo éramos todos españoles menos uno, Bojan Vrhovnik de Eslovenia.
La partida empezó... fatal: no me quise cambiar los zapatos y me acerqué demasiado a la pista en mi primer tiro, así que la combinación de la cera de la pista + zapato incorrecto + prisas y risas acabó con una buena caida de culo en la pista, un espectáculo vamos. Al final quedé segundo de mi grupo y el chico de Eslovenia primero. Pero nos divertimos un montón. Una experiencia genial.
Casi al final de la partida vino Brínquez un ratito. Como veis, se "nota" que ha llegado... parece un gran pingüino entre todos nosotros - Un BsoT Jordi!.
Luego nos pillaron a Carlos y a mí para una entrevista para Channel 8... en inglés!, jaja, quien me mandaba a mi meterme en estos líos. Pero estuvo bien, a ver si sale un día de estos publicada y os enlazo el video; seguramente estará en la sección de tomas falsas o humor, ya que dudo que un inglés pueda llegar a entender algo de lo que dije, imaginaos: "catanglish" + nervios de cámara... Pero que creo que, gracias a la aportación de Carlos, el vídeo no va a ser del todo malo.
Unas partidas al futbolín con Ethel, que nos dio a conocer su lado más competitivo, unas cervecitas, conocimos a los nuevos "donetes" de la Universidad de la Salle y luego decidimos ir a tomar algo hacia el centro de Barcelona.
Nos fuimos a un local pequeñito de Plaza Reial a tomar algo donde nos encontramos con una de las personas que más me han motivado a aprender .NET y a meterme en este mundo, mi amigo David Salgado!, cada vez está más fuerte el cabroncete.
Bueno... unas risas, unas copas y para casa, que hoy, como veis, estoy "trabajando", ya que no me queda más remedio.
Todas las fotos que hice ayer las podéis ver en mi galería de flickr.
Hoy toca ir a tomar algo con todos los invitados al TechEd de España, así que, si no pasa nada, mañana o pasado os comento que tal y cuelgo más fotos.
*crossposting desde Geeks.ms
Hace dos semanas pude asistir al TTT en las oficinas de Microsoft una vez más. Volver a ver a mis amigos de los clubes, estudiantes y ex-estudiantes que, como yo, han aportado y aportan mucho valor a nuestra comunidad. He podido ver a viejos amigos como Ricardo Varela, que fue mi mentor en este mundillo y el que me abrió las puertas al mundo de .NET. A personajes geniales como Chema Alonso. A maestros como David Salgado o David Carmona que siempre consiguen que alucines con sus presentaciones.
Hace ya algo más de tres años que fundé mi club en Barcelona junto con mis compañeros de universidad. Muchos ya han acabado y son ingenieros. Otros aun estamos con los codos pelaos. Y también ha aparecido gente nueva, con nuevas energías, ideas e ilusiones que nos alegran y animan a continuar.
Parece mentira como pasa el tiempo. Como me vi sentado en la reunión de clubes que hicimos durante el TTT..., vi a un montón de gente nueva con ilusiones y ideas nuevas. Me gusta ver como estos nuevos chicos tienen la misma ilusión que tenía yo al empezar, las mismas inquietudes. Ojalá hubiera más gente así.
La verdad es que me lo pasé genial en Madrid. Me convertí, como siempre que voy a eventos así, en esponja: absorbiendo todos los conocimientos que pude y conociendo a un montón de personas geniales.
Las presentaciones fueron bastante bien aunque, como siempre, faltó mucho tiempo. Como no, las que más me gustaron fueron la de Silverlight y AJAX de Carmona y la de seguridad de Chema y Ricardo. También nos metieron por el medio una presentación de la XBox 360, con los nuevos juegos de Halo 3 y PGR4.
Lo mejor de las presentaciones... la gente con la que me codeé y las comenté. :)
La cena no estuvo nada mal. Un buen lugar para conocer a los nuevos y hablar de fricadas. Además, como todo el mundo sabe, con dos buenas cervezas, la mente está mucho más clara y se entienden mejor las cosas. Eso si, luego nos dicen que si somos una secta o algo parecido, aunque después de ver el espectáculo de los MVP's...
... sin comentarios.
Por la noche... bueno, los mejores nos fuimos de fiesta... jeje!!
Al día siguiente hicimos un Paintball. Formamos equipos de 8 y nos dispusimos a darnos caña. Yo formé parte del equipo 'Vista', quedamos segundos ya que la final la perdimos contra 'XP'... esperad a que tengamos el Service Pack....
Bueno... así estamos de mal.
*crossposting desde Geeks.ms
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:
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())
'...
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:

*crossposting desde Geeks.ms
En muchos de los ejemplos que podemos ver sobre servicios web las llamadas a los diferentes métodos que proveen son independientes entre ellas. En la vida real es posible que necesitemos mantener el estado entre diferentes llamadas y que, además, éstas tengan que seguir una determinada secuencia.
El Framework 3.0 nos provee de formas muy fáciles para poder controlar estos casos, solo falta añadir unos atributos a los métodos de nuestro servico o al servicio en sí.
Para poder enseñar como hacerlo de una manera fácil de entender he creado un pequeño código de ejemplo.
He creado un servicio web que emula un carrito de compra; un ejemplo básico donde se debe mantener el estado entre diferentes llamadas. No he implementado ningún control de excepciones ya que así nos centramos en lo que toca.
Esta primera parte tratará de mantener el estado y concurrencia, en la otra entrada veremos como definir el orden de ejecución.
Por una parte tendremos la lista de productos; un xml, por otro el servicio web; con su contrato y la clase que lo implementa, una aplicación host; que sirve el servicio usando wsHttpBinding y, por último, el cliente; que consumirá el servicio.
Primero he creado un xml como contenedor de datos, que contiene una lista de productos. Lo he creado serializando un objeto de tipo List<Product>, así luego lo podremos deserializar y trabajar con él de una forma más fácil:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Product>
<Id>0</Id>
<Name>Agua</Name>
<Price>0.5</Price>
</Product>
<Product>
<Id>1</Id>
<Name>Zumo de naranja</Name>
<Price>1.2</Price>
</Product>
<Product>
<Id>2</Id>
<Name>Olivas</Name>
<Price>2.35</Price>
</Product>
<Product>
<Id>3</Id>
<Name>Patatas</Name>
<Price>1.75</Price>
</Product>
<Product>
<Id>4</Id>
<Name>Cerveza</Name>
<Price>0.8</Price>
</Product>
<Product>
<Id>5</Id>
<Name>Refresco</Name>
<Price>0.7</Price>
</Product>
</ArrayOfProduct>
Luego he creado un proyecto tipo librería en Visual Basic y he creado las dos clases que voy a necesitar para tratar los datos: Product y CartItem.
Public Class Product
Private _id As Integer
Public Property Id() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Private _price As Decimal
Public Property Price() As Decimal
Get
Return _price
End Get
Set(ByVal value As Decimal)
_price = value
End Set
End Property
End Class
Public Class CartItem
Private _product As Product
Public Property Product() As Product
Get
Return _product
End Get
Set(ByVal value As Product)
_product = value
End Set
End Property
Private _cuantity As Integer
Public Property Cuantity() As Integer
Get
Return _cuantity
End Get
Set(ByVal value As Integer)
_cuantity = value
End Set
End Property
End Class
Después he definido el contrato: la Interface.
<ServiceContract()> _
Public Interface IShoppingCart
<OperationContract()> _
Function AddItem(ByVal itemId As Integer) As Boolean
<OperationContract()> _
Function RemoveItem(ByVal itemId As Integer) As Boolean
<OperationContract()> _
Function GetShopingCart() As String
<OperationContract()> _
Function Checkout() As Boolean
End Interface
Y la clase que la implementa: el servicio.
Public Class ShoppingCartSrv
Implements IShoppingCart
Private shoppingCart As New List(Of CartItem)
Private Function getProduct(ByVal productId As Integer) As Product
Dim products As New List(Of Product)
Dim filename As String = "products.xml"
If File.Exists(filename) Then
Dim reader As New StreamReader(filename)
Dim serializer As New XmlSerializer(GetType(List(Of Product)))
products = CType(serializer.Deserialize(reader), List(Of Product))
reader.Close()
End If
Dim product As Product = Nothing
For Each p As Product In products
If p.Id = productId Then
Return p
End If
Next
Return product
End Function
Public Function AddItem(ByVal itemId As Integer) As Boolean Implements IShoppingCart.AddItem
For Each item As CartItem In shoppingCart
If item.Product.Id = itemId Then
item.Cuantity += 1
Return True
End If
Next
Dim product As Product = getProduct(itemId)
If Not IsNothing(product) Then
shoppingCart.Add(New CartItem With {.Product = product, .Cuantity = 1}) Return True
End If
Return False
End Function
Public Function GetShopingCart() As String Implements IShoppingCart.GetShopingCart
Dim list As String = ""
Dim total As Double = 0
For Each item As CartItem In shoppingCart
list += String.Format("Id: {0} Name: {1} Price: {2} Cuantity: {3}{4}", _ item.Product.Id, item.Product.Name, item.Product.Price, item.Cuantity, Environment.NewLine)
total += (item.Product.Price * item.Cuantity)
Next
If list.Equals("") Then list = "Empty Cart"
Else
list += String.Format("Total: {0} Euro", total) End If
Return list
End Function
Public Function RemoveItem(ByVal itemId As Integer) As Boolean Implements IShoppingCart.RemoveItem
Dim item As CartItem = Nothing
For Each i As CartItem In shoppingCart
If i.Product.Id = itemId Then
item = i
End If
Next
If Not IsNothing(item) Then
shoppingCart.Remove(item)
Return True
End If
Return False
End Function
Public Function Checkout() As Boolean Implements IShoppingCart.Checkout
shoppingCart.Clear()
Return True
End Function
End Class
Ahora que ya tenemos creado el servicio, he creado una aplicación para que lo sirva. Creo un nuevo proyecto de consola, agrego la dos referencias que necesito: System.ServiceModel y al proyecto de librería que representa mi servicio. Y creo el código que necesito para servir el servicio:
Imports ShoppingCartService
Imports System.ServiceModel
<