Revisão do Livro: Silverlight 4.0 Curso Completo

Eu tenho acompanhado a evolução do Silverlight ao longo de sua existência, ainda quando ele se chamava WPF/E. Eu tenho me preocupado em estudar as stacks de comunicação para o consumo de serviços WCF, deixando alguns detalhes interessantes para focar especificamente na área de comunicação.

Para explorar um pouco melhor as capacidades do Silverlight, decidi ler um livro sobre o assunto. Como eu conheço os trabalhos do Luis Abreu, eu optei por utilizar o livro que ele escreveu sobre a versão 4.0 do Silverlight. O livro inicia com uma visão do que é o XAML e detalhes de sua estrutura. Depois dá uma volta pela customização e análise dos controles fornecidos pela tecnologia. DataBinding que também é um recurso extremamente rico em funcionalidades e facilidades, ele aborda com um carinho especial. Além disso, é falado sobre as opções de comunicação com serviços WCF. Há ainda também alguns recursos para aqueles que desejam explorar as possibilidades relacionadas à multimídia e animações. E como se não bastasse, ainda há alguns outros temas interessantes, que são essenciais para a execução e customização deste tipo de aplicação, e que possuem capítulos exclusivos, como é o caso do Out Of Browser e interação com o Javascript.

Mesmo para aqueles que usam WPF, podem tirar proveito deste livro, onde algumas seções são comuns para ambas tecnologias. Um livro curto, fácil de ler e bem ilustrado, que conta com uma didática simples, e que ao mesmo tempo, não deixa de abordar detalhes interessantes de mais baixo nível, para aqueles que gostam de entender como as coisas funcionam nos bastidores. Minha avaliação final é 9/10.

OT: Uso do Twitter

Como vocês já devem ter notado, eu utilizo o Twitter exclusivamente para divulgar meus artigos, e atender a demanda de pessoas que não utilizam mais RSS. Hoje, enquanto estava tweetando sobre o artigo que escrevi, descobri uma opção que listam todos os tweets que mencionam meu nickname, e olha que encontrei até minha namorada falando sobre mim! 😛

O que quero fazer com este post é pedir desculpas, pois percebi que há várias pessoas fazendo perguntas, mas como eu não sei quero utilizar ele, esses tweets que mencionam o meu nome, não são atendidos por mim. Por favor, se tiver alguma dúvida, crítica ou sugestão, por favor, utilize o formulário de contato ou a seção de comentários de cada post, que assim que possível, responderei. Desculpe-me pelo transtorno.

Conteúdo de WCF para estudo

Muitas pessoas me escrevem para indicar algum material sobre WCF para guiar o estudo de alguém que esteja disposto a aprender esta tecnologia. Como eu já tenho bastante conteúdo escrito sobre isso, resolvi criar um post para elencar todos eles, em uma ordem de leitura que você poderia seguir até atingir este objetivo. Só é importante ressaltar que estes artigos foram escritos individualmente, e podem não ser tão intuitivos quanto um livro, mas acredito que ajudará a dar os primeiros passos.

Observação: Nem todos os posts que já escrevi sobre o WCF estão mencionados aqui. Pode haver informações, não menos importantes, que você pode encontrar na seção de busca ou clicando na categoria WCF.

WCF – Usando o MsmqIntegrationBinding

Há algum tempo eu mostrei neste artigo como podemos fazer o uso do Message Queue com WCF, e lá foi discutido todos os benefícios de se envolver uma fila na comunicação entre as duas partes. A exigência daquele modelo de utilização é que ambos os lados precisam utilizar a API do WCF para se comunicar com o Message Queue.

O problema é que as vezes já temos uma solução implementada e operante. Antes do WCF, a única forma que tínhamos para interagir com o Message Queue na plataforma .NET era através das classes contidas no assembly System.Messaging.dll. Além disso há outras soluções que recebem ou enviam mensagens para uma fila, escritas em outras tecnologias.

Para trabalhar com Message Queue no WCF, temos dois bindings: NetMsmqBinding e MsmqIntegrationBinding, onde o primeiro deles já foi esgotado naquele outro artigo. O segundo trata-se de um binding criado exclusivamente para interagir com filas em que as mensagens sejam postadas ou recebidas por outras tecnologias que não o WCF. A finalidade deste artigo é mostrar como proceder para utilizar este binding e interoperar com soluções que já estão em funcionamento.

Para exemplificar vamos interoperar com aplicativos que recebem e postam mensagens utilizando a API System.Messaging.dll, que existe desde a primeira versão do .NET Framework. Abaixo temos dois cenários distintos, separados em duas pastas: WCFNoCliente e WCFNoServidor. No primeiro cenário utilizaremos o WCF para enviar uma mensagem para a fila e o serviço irá extrair a mensagem de lá utilizando as classes contidas no assembly System.Messaging.dll. No segundo cenário, será o inverso, ou seja, utilizaremos as classes contidas no assembly System.Messaging.dll para enviar a mensagem, e utilizaremos o WCF no serviço para extrair a mensagem da fila e processá-la. A imagem abaixo ilustra a estrutura dos projetos de teste:

O primeiro passo é desenhar o contrato do serviço, que irá formalizar a comunicação. A ideia será ter um serviço que processa pedidos de algum comércio eletrônico. Sendo assim teremos duas classes: Pedido e Cliente, que são autoexplicativas. Cada uma delas tem propriedades que as descrevem, que também não precisam ser exibidas aqui. Uma característica de serviços que são expostos através do Message Queue, é que as operações eles devem ser sempre one-way, assim como já foi discutido anteriormente. Abaixo temos a definição do contrato que será utilizado como exemplo:

[ServiceContract]
[ServiceKnownType(typeof(Pedido))]
[ServiceKnownType(typeof(Cliente))]
public interface IComercioEletronico
{
    [OperationContract(IsOneWay = true, Action = “*”)]
    void AdicionarPedido(MsmqMessage<Pedido> mensagem);
}

Infelizmente por se tratar de um cenário específico, a nossa operação deverá ter apenas um único parâmetro, e ele deve ser do tipo MsmqMessage<T>, que está debaixo do namespace System.ServiceModel.MsmqIntegration, e representará o body da mensagem. Caso você precise de mais parâmetros, então o correto é que você inclua isso em uma mesma classe e a defina como o parâmetro genérico T da classe MsmqMessage<T>. É importante dizer que o contrato irá definir a estrutura da mensagem a ser enviada para a fila (WCFNoCliente) ou a mensagem a ser extraída da fila (WCFNoServidor).

um detalhe importante na criação do contrato é o uso do atributo ServiceKnownTypeAttribute, que é exigido para todos os elementos mencionados direta ou indiretamente no contrato. Isso é necessário para que o serializador conheça todos os tipos envolvidos, caso contrário, a mensagem não será recebida pelo WCF, e ao ligar o tracing, vamos nos deparar com a seguinte mensagem de erro:

System.ServiceModel.ProtocolException: An error was encountered while deserializing the message. The message cannot be received. —&gt; System.Runtime.Serialization.SerializationException: An error occurred while deserializing an MSMQ message’s XML body. The message cannot be received. Ensure that the service contract is decorated with appropriate [ServiceKnownType] attributes or the TargetSerializationTypes property is set on the MsmqIntegrationBindingElement.

Utilizando o WCF no Servidor

Como será um serviço WCF que irá extrair as mensagens da fila, o primeiro passo aqui é a implementação do contrato na classe que representará o serviço. Aqui tudo é muito parecido com um serviço WCF tradicional, mas com uma pequena diferença que está na operação. Como a classe MsmqMessage<T> representa a mensagem que está dentro da fila, ela é muito mais do que a instância da classe Pedido, ou seja, temos outras propriedades que estão relacionadas ao protocolo.

Entre as várias propriedades expostas pela classe MsmqMessage<T> temos a propriedade Body, que retorna um object que representa a instância da classe que foi serializada no corpo da mensagem pelo cliente, que no nosso caso é a classe Pedido. Abaixo temos a implementação do serviço com o processamento da mensagem:

public class ServicoDeComercioEletronico : IComercioEletronico
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void AdicionarPedido(MsmqMessage<Pedido> mensagem)
    {
        Pedido pedido = mensagem.Body as Pedido;

        if (pedido != null)
        {
            Console.WriteLine(“—- Processando o Pedido: {0}”, pedido.Codigo);
            Console.WriteLine(“—- Cliente: {0}”, pedido.Cliente);
            Console.WriteLine(“—- Valor: {0:N2}”, pedido.ValorTotal);
            Console.WriteLine(“—- Data: {0:dd/MM/yyyy HH:mm}”, pedido.Data);
            Console.WriteLine();
        }
    }
}

Note que decoramos a operação com o atributo OperationBehaviorAttribute definindo as propriedades TransactionScopeRequired e TransactionAutoComplete para True, pois utilizando o binding MsmqIntegrationBinding não temos o controle explícito das transações, que para isso exige que o binding suporte sessões, e não é o caso do MsmqIntegrationBinding.

Depois da implementação definida, agora chega o momento de configurar o serviço. Como já sabemos, vamos recorrer ao binding MsmqIntegrationBinding. Para uma fácil interoperabilidade, o endereço em que o serviço é exposto deve utilizar o scheme msmq.formatname ao invés do net.msmq, que permite entre vários modelos, o acesso direto a fila (através de format-name), sem a necessidade de contatar o Active Directory (AD). Abaixo temos a configuração declarativa do serviço:

<system.serviceModel>
  <services>
    <service name=”Servico.ServicoDeComercioEletronico”>
      <endpoint address=”msmq.formatname:DIRECT=OS:.private$MinhaFila”
                binding=”msmqIntegrationBinding”
                bindingConfiguration=”bindingConfig”
                contract=”Biblioteca.IComercioEletronico” />
    </service>
  </services>
  <bindings>
    <msmqIntegrationBinding>
      <binding name=”bindingConfig”>
        <security mode=”None” />
      </binding>
    </msmqIntegrationBinding>
  </bindings>
</system.serviceModel>

Com o serviço criado, podemos agora inicializarmos a criação do cliente. Obviamente que não iremos referenciar o serviço, mesmo porque nem criamos o endpoint que expõe o documento WSDL. A ideia aqui será utilizar os tipos que estão dentro do assembly System.Messaging.dll para enviar a instância da classe Pedido para a fila, e utilizar o WCF do outro lado para processar.

Depois do assembly referenciado na aplicação, instanciamos a classe MessageQueue e informamos o caminho para a fila (via path-name). Depois instanciamos a classe Pedido e a configuramos com os dados do Pedido que foi realizado e, finalmente, enviamos a instância para a fila através do método Send. Neste momento, a instância da classe Pedido será serializada como o body da mensagem.

using (MessageQueue queue = new MessageQueue(@”.private$MinhaFila”))
{
    Pedido pedido = new Pedido();
    pedido.Codigo = 123;
    pedido.Data = DateTime.Now;
    pedido.ValorTotal = 1983.81M;
    pedido.Cliente = new Cliente() { Codigo = 39, Nome = “Israel Aece” };

    queue.Send(pedido, MessageQueueTransactionType.Single);
    Console.WriteLine(“Mensagem Enviada com Sucesso.”);
}

Observação: Como a fila é transacionada, precisamos definir o tipo da transação a ser utilizada pelo Message Queue no momento do envio da mensagem. Se o controle da transação está sendo controlada por um elemento externo, como é o caso do TransactionScope, então é necessário definir o MessageQueueTransactionType para Automatic, para que o envio da mensagem possa participar da mesma transação, criada previamente.

Utilizando o WCF no Cliente

Neste cenário inverteremos as tecnologias que utilizamos. Agora no serviço utilizaremos os tipos do assembly System.Messaging.dll e no cliente o WCF. Aqui criaremos a instância da classe MessageQueue com a finalidade de extrair a mensagem que lá foi postada, enviada por um cliente que utiliza o WCF. E para isso utilizaremos o método Receive, que da mesma forma que o método Send, também precisa estar protegido por uma transação.

O método Receive retorna uma instância da classe Message (namespace System.Messaging), que entre várias propriedades, temos a Body, que retorna um object representando a classe que foi serializada, e que no nosso caso é a classe Pedido. O código abaixo ilustra como fazemos para extrair a mensagem:

using (MessageQueue queue = new MessageQueue(@”.private$MinhaFila”))
{
    queue.Formatter = 
        new XmlMessageFormatter(new Type[] { typeof(Pedido), typeof(Cliente) });

    Pedido pedido = queue.Receive(MessageQueueTransactionType.Single).Body as Pedido;

    if (pedido != null)
    {
        Console.WriteLine(“—- Processando o Pedido: {0}”, pedido.Codigo);
        Console.WriteLine(“—- Cliente: {0}”, pedido.Cliente);
        Console.WriteLine(“—- Valor: {0:N2}”, pedido.ValorTotal);
        Console.WriteLine(“—- Data: {0:dd/MM/yyyy HH:mm}”, pedido.Data);
        Console.WriteLine();
    }
}

Da mesma forma que fizemos acima com o contrato do WCF, decorando-o com o atributo ServiceKnownTypeAttribute, temos também que mencionar quais sãos os tipos que compõem o body da mensagem que está na fila, e para isso podemos recorrer a instância da classe XmlMessageFormatter, e em seu contrutor informar um array contendo os tipos envolvidos.

Como não há referência do serviço no cliente, precisamos fazer com que o cliente conheça qual é o contrato do serviço, e justamente por isso que ele foi colocado em uma DLL a parte, chamada de Biblioteca. Utilizamos no cliente a classe ChannelFactory<TChannel> para criar a canal de comunicação entre a aplicação cliente e a fila.

Além do contrato, devemos também informar o binding que irá reger a comunicação, e que como sabemos, será o binding MsmqIntegrationBinding. Em seguida informarmos o endereço (format-name) da fila em que a mensagem será postada. Com a factory criada, agora podemos criar a instância do canal que é efetivamente o proxy:

using (ChannelFactory<IComercioEletronico> factory =
    new ChannelFactory<IComercioEletronico>(
        new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.None),
        @”msmq.formatname:DIRECT=OS:.private$MinhaFila”))
{
    var proxy = factory.CreateChannel();

    Pedido pedido = new Pedido();
    pedido.Codigo = 123;
    pedido.Data = DateTime.Now;
    pedido.ValorTotal = 1983.81M;
    pedido.Cliente = new Cliente() { Codigo = 39, Nome = “Israel Aece” };

    proxy.AdicionarPedido(new MsmqMessage<Pedido>(pedido));
    Console.WriteLine(“Mensagem Enviada com Sucesso.”);
}

Note que depois da instância da classe Pedido criada e configurada, ela não é passada diretamente para o método AdicionarPedido. Como foi comentado acima, o contrato impõe que a classe Pedido seja envolvida por um wrapper (MsmqMessage<T>), que representará a mensagem dentro do fila, e a instância da classe Pedido será armazenada/serializada no body dela.

Assincronismo

Como sabemos, uma das características do uso do Message Queue é garantir o assincronismo, e permitir ao cliente enviar mensagens ao serviço mesmo que ele esteja offline, mascarando assim eventuais problemas que existam na comunicação entre as duas partes envolvidas.

Conclusão: No decorrer deste artigo vimos que podemos substituir a tecnologia que existe de um dos lados para uma tecnologia mais recente, como é o caso do WCF, e com isso tirar todo o proveito de seus recursos, mas tendo em mente que existem algumas poucas limitações e imposições.

UtilizandoMsmqIntegrationBinding.zip (20.48 kb)

Curso de WCF 4.0 em Campinas

wcf 4.0Dia após dia as aplicações estão cada vez mais conectadas. Essa interligação viabiliza novas oportunidades de negócios, agilidade e eficiência no processo de uma empresa, beneficiando assim todos aqueles que estão envolvidos.

Dentro da plataforma .NET da Microsoft, o WCF (Windows Communication Foundation) é o pilar de comunicação, que fornece uma infinidade de funcionalidades para expor, consumir e gerenciar serviços, sejam eles para serem consumidos em uma rede local ou através da internet.

Como essa necessidade está cada vez mais presente no dia a dia de cada desenvolvedor, o WCF possui cada vez mais espaço, já que ele substitui todas as tecnologias de aplicações distribuídas criadas pela Microsoft, incorporando em uma plataforma estensível e consistente, os principais modelos de comunicação que existem atualmente.

Tendo em vista todo esse cenário, eu vou ministrar um curso oficial de WCF 4.0, abordando desde os primeiros passos até cenários mais complexos, como roteamento, estensibilidade, segurança (incluindo claims), performance, etc. Abaixo estão listados os tópicos que serão abordados:

  • Módulo 1: Arquitetura Orientada à Serviços
  • Módulo 2: Introdução ao WCF
  • Módulo 3: Hospedagem de Serviços
  • Módulo 4: Contratos
  • Módulo 5: Endpoints e Behaviors
  • Módulo 6: Teste e Debug
  • Módulo 7: Segurança
  • Módulo 8: Tópicos Avançados (Estensibilidade, Processamento Assíncrono e Roteamento)

Como pré-requisitos para este curso, é necessário possuir familiaridade com a plataforma .NET, com o Visual Studio 2008/2010 e experiência em alguma linguagem .NET (C# ou VB.NET), incluindo conceitos relacionados a orientação à objetos.

O curso será ministrado na People Computação, na cidade de Campinas, em São Paulo, com toda infraestrutura fornecida por eles. A People é um centro oficial autorizado Microsoft, que ministra e aplica cursos e exames oficiais, e é onde eu ministro treinamentos desde meados de 2005.

Com 24 horas de duração, o treinamento será realizado toda terça-feira e quinta-feira, das 18:30 às 22:30 (sendo 4 horas por dia), iniciando em 23 de novembro até 09 de dezembro de 2010. A sala terá capacidade para apenas 12 alunos. Para maiores informações, valores e como se inscrever, entre em contato através do telefone (19) 3739-6400.

Substituindo ASMX por WCF no servidor

Os ASP.NET Web Services (ASMX) são baseados na especificação WS-I Basic Profile, gerando as mensagens na versão 1.1 do SOAP. Eles foram que foram introduzidos desde a primeira versão do .NET Framework, e mais recentemente foram substituídos pelo WCF.

Para manter a interoperabilidade, a Microsoft criou um binding chamado BasicHttpBinding, que possui as mesmas características dos serviços ASMX. Com isso, podemos substituir tanto o serviço quanto o cliente utilizando a API do WCF. Ao optar pela substituição do lado do serviço, precisamos nos preocupar com a SOAPAction.

A SOAPAction é um header que é incluído na requisição HTTP, e determina intenção da requisição SOAP. Esse header é representado por uma URI que não aponta necessariamente para um local válido na internet. O problema reside justamente aqui. Imagine que temos um serviço (ASMX), que disponibiliza apenas uma única operação:

[WebService(Namespace = “http://tempuri.org/&#8221;)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Servico : System.Web.Services.WebService
{
    [WebMethod]
    public string Ping()
    {
        return “ping!”;
    }
}

Os clientes que o consomem devem enviar as requisições da seguinte forma:

POST /Servico.asmx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.4952)
Content-Type: text/xml; charset=utf-8
SOAPAction: “http://tempuri.org/Ping&#8221;
Host: 127.0.0.1:51982
Content-Length: 288
Expect: 100-continue
Connection: Keep-Alive

<?xml version=”1.0″ encoding=”utf-8″?>
    <soap:Envelope …>
        <soap:Body>
            <Ping xmlns=”http://tempuri.org/&#8221; />
        </soap:Body>
</soap:Envelope>

Agora queremos substituir o serviço para o WCF. Optamos então por criar o contrato e, consequentemente, o implementamos em uma classe que representará o serviço. A interface do contrato está definida abaixo:

[ServiceContract]
public interface IContrato
{
    [OperationContract]
    string Ping();
}

O ponto mais importante é expor o serviço através do binding BasicHttpBinding, que não será abordado aqui. Se analisarmos o WSDL gerado pelo serviço, veremos que a SOAPAction gerada é: http://tempuri.org/IContrato/Ping. Como podemos perceber, ela leva o nome do contrato. Com isso, os clientes existentes não conseguirão mais enviar mais mensagens para o serviço, já que o WCF utiliza a SOAPAction para identificar a operação a ser disparada, e como ela é diferente, não a encontrará. Abaixo temos a descrição do erro que ocorre:

Unhandled Exception: System.Web.Services.Protocols.SoapHeaderException: The message with Action ‘http://tempuri.org/Ping&#8217; cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

Para resolvermos este problema, temos que recorrer a propriedade Action que é definida no atributo OperationContractAttribute, e lá colocarmos a mesma SOAPAction que os clientes estão enviando, mantendo assim a compatibilidade e não sendo necessária qualquer mudança por parte daqueles que o consomem.

[ServiceContract]
public interface IContrato
{
    [OperationContract(Action = “http://tempuri.org/Ping&#8221;)]
    string Ping();
}

Tomando este cuidado, podemos tranquilamente substituir serviços construídos em ASMX para WCF, sem afetar qualquer cliente que já consuma o mesmo. É importante dizer também que é possível consumir um serviço escrito em ASMX através da API do WCF do lado cliente, mas isso está fora do escopo deste artigo. E para finalizar, sempre se atente aos namespaces.

Visualizador para JSON

O JSON é um formato que temos para serializar informações, e que possibilita aplicações AJAX consumirem serviços de forma muito mais simples, dispensando todo o “overhead” do XML ou SOAP. É um formato relativamente simples, assim como podemos ver abaixo, onde temos um cliente e seus respectivos pedidos:

{“Codigo”:123,”Email”:”ia@israelaece.com”,”Nome”:”Israel”,”Pedidos”:[{“Codigo”:1,”Data”:”/Date(1282228004105-0300)/”,”Valor”:1000},{“Codigo”:2,”Data”:”/Date(1282228004144-0300)/”,”Valor”:129}]

Para facilitar a vida dos desenvolvedores, principalmente quando lidamos com a construção de serviços, que exigem a exposição de informações mais complexas do que essa mostrada acima, pode ser útil termos um visualizador para mostrar graficamente a estrutura do documento JSON. Para isso, podemos recorrer ao JSONViewer, uma ferramenta que não exige nenhuma instalação, e tudo o que você precisa fazer é rodá-la. Abaixo podemos ver a imagem do documento JSON acima, totalmente formatado e de forma gráfica.

Depois de baixar, com uma configuração simples, que você encontra no site do projeto, verá que podemos incorporá-lo ao Fiddler, para já monitorar serviços que retornam os resultados em formato JSON.