WCF Vídeo - Deployment

by Israel Aece 9. September 2009 07:51
Deployment Deployment

Este vídeo exibe como podemos proceder para efetuar a distribuição de um serviço WCF, de uma forma superficial. Como exemplo, migraremos o hosting de uma aplicação Console para um Windows Service. Além disso, ele ainda aborda algumas práticas para a reutilização do proxy entre aplicações.

Formato: WMV - Duração: 00:38:05 - Tamanho: 50MB

Tags: , , ,

WCF

Compartilhando portas através do protocolo TCP

by Israel Aece 13. March 2009 12:03

Ao criar um serviço WCF, podemos disponibilizá-lo através do protocolo TCP (net.tcp), utilizando uma porta específica. Uma vez que voce publica esse serviço, nenhum outro serviço naquela mesma máquina poderá utilizar aquela porta ao mesmo tempo, e se fizer isso, uma exceção do tipo AddressAlreadyInUseException será disparada exibindo a seguinte mensagem: There is already a listener on IP endpoint [MachineName]:[Port].  Make sure that you are not trying to use this endpoint multiple times in your application and that there are no other applications listening on this endpoint.

Podemos não perceber mas o Windows permite o compartilhamento de uma mesma porta TCP para expor múltiplas aplicações. Um exemplo disso é o HTTP, que permite múltiplas aplicações estarem acessíveis através da porta 80 do protocolo TCP. Isso é possível graças à um listener (HTTP.SYS) que o IIS possue e que, baseando-se no conteúdo da mensagem, encaminha a requisição para a aplicação correspondente processá-la.

Ao instalar o .NET Framework, um serviço chamado Net.Tcp Port Sharing Service é instalado no Windows, dando a possibilidade de múltiplos serviços WCF compartilharem a mesma porta TCP, assim como o HTTP. Esse serviço (hospedado através do processo SMSvcHost.exe (C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation)) tem a finalidade de inspecionar a mensagem, extrair o endereço de destino, e baseando-se nele, encaminhar a requisição para a aplicação que a processará.

Além deste serviço funcionando, ainda é necessário uma pequena configuração no código que expõe serviço WCF. O binding NetTcpBinding possui uma propriedade booleana chamada PortSharingEnabled que, por padrão, é definida como False. Voce deverá definí-la como True para todos os serviços que desejarem compartilhar uma porta TCP específica. Ao fazer isso, o WCF se encarrega de iniciar automaticamente o serviço Net.Tcp Port Sharing Service, mas voce pode fazer isso manualmente, ou ainda alterar a configuração do serviço para ele ser inciado automaticamente quando o sistema operacional entrar no ar. O trecho de código abaixo ilustra como podemos proceder para configurar o endpoint com o binding e habilitando o compartilhamento da porta TCP:

host.AddServiceEndpoint(
    typeof(IContrato),
    new NetTcpBinding() { PortSharingEnabled = true }, 
    new Uri("net.tcp://localhost:7373/NomeDoServico/Cadastro"));

Como os serviços irão compartilhar a mesma porta, a distinção da aplicação é determinada pela URI como um todo, ou seja, o que vem depois da porta na URI do serviço precisa ser diferente entre os serviços, caso contrário voce terá o mesmo problema que antes.

Com esta técnica, vamos permitir múltiplas aplicações coexistirem fisicamente na mesma máquina, mas em processos separados, compartilhando a mesma infraestrutura de rede, melhorando a segurança, já que podemos diminiur a superfície de ataque não exigindo a abertura de portas no firewall de forma aleatória.

Tags: ,

CSD | WCF

ServiceController.ExecuteCommand

by Israel Aece 3. July 2008 12:31

Quando criamos Windows Services sob a plataforma .NET, podemos sobrescrever o método OnCustomCommand fornecido pela classe ServiceBase para que, via ServiceController (classe que permite a interceptação da execução do serviço), possamos disparar esse método customizado e, conseqüentemente, executarmos uma determinada tarefa dentro do mesmo.

protected override void OnCustomCommand(int command) { .... }

Com isso, podemos simplesmente em uma aplicação cliente, instanciarmos a classe ServiceController, especificarmos o serviço e a máquina onde ele reside e, finalmente, invocar o método ExecuteCommand, algo como é mostrado no exemplo abaixo:

new ServiceController("MeuServico", ".").ExecuteCommand(N);

Onde o parametro N representa o número inteiro que será passado para o método OnCustomCommand. A questão é que temos um detalhe a ser considerado aqui: se esse valor inteiro for menor que 128, uma exceção do tipo Win32Exception com a seguinte mensagem é atirada: Access denied. Isso ocorre porque provavelmente valores menores que 128 são reservados para o próprio sistema operacional.

Se não me engano, nas versões 1.x do .NET Framework, a exceção atirada era algo como "parametro incorreto", o que me parece mais significativo para o caso.

Tags:

.NET Framework

Por dentro da Base Classe Library (BCL)

by Israel Aece 23. February 2008 15:21

Bem, a idéia era criar um livro, mas por questões de tempo não consegui dar a atenção merecida ao mesmo. Como recentemente saiu a versão 3.X do .NET Framework, eu acredito que não seria estratégico para alguma editora publicar algo em versão 2.0 se já estamos na versão 3.5. Sim, nós sabemos que o 2.0 é o núcleo, mas...

Sendo assim, eu decidi publicar os capítulos de forma gratuíta no meu site. Como não tive tempo nem ninguém para fazer a correção do conteúdo, peço desculpas antecipadamente e desejo que sejam toleráveis com relação a possíveis erros de portugues (concordancia, acentuação, etc.), e também a possíveis erros técnicos. Além disso, também havia alguns namespaces que estavam no escopo para falar, mas que não consegui, como é o caso do System.Transactions e o System.Threading. Talvez em uma próxima oportunidade. Todos exemplos estão em Visual Basic .NET e Visual C#.

Voce pode acessar o índice através deste endereço. ATENÇÃO: Os arquivos estão em formato XPS. Caso não tenha o visualizador, você poderá baxiá-lo através deste link.

Tags: , , , ,

.NET Framework

Por dentro da Base Class Library

by Israel Aece 23. February 2008 01:00

A Base Classe Library (também conhecida como BCL) é um conjunto de classes que o .NET disponibiliza para todas as linguagens que rodam sob o .NET Framework. Essa base encapsula várias funcionalidades que tornam o trabalho dos desenvolvedores muito mais fácil. As classes contidas dentro da BCL é comum para qualquer tipo de aplicação, ou seja, independentemente de tecnologia (ASP.NET, Windows Forns, WPF, etc.), você poderá consumir essas classes que, representam tarefas que são comumente utilizadas. A imagem abaixo exibe onde a BCL está encaixada dentro da plataforma .NET.

Figura 1 - Base Class Library (BCL).

A versão 2.0 adicionou novas tipos e namespaces, enriquecendo ainda mais esta estrutura. Essas classes vão desde novas coleções (tipadas) até novos namespaces, como é o caso do System.Transactions. Apesar do .NET Framework estar em sua versão 3.5, ele utiliza o .NET 2.0 como seu núcleo. A figura abaixo ilustra perfeitamente a posição do .NET 2.0 dentro do .NET 3.X.

Figura 2 - Gráfico que exibe a posição do .NET 2.0.


A BCL é composta por vários namespaces e, através dos capítulos abaixo, veremos detalhadamente cada um dos principais deles. A idéia é abordar o conteúdo mais útil ao dia-à-dia, mostrando exemplos em Visual Basic .NET e Visual C#. Sendo assim, nem todas as classes/funcionalidades serão cobertas aqui mas, para isso, poderá recorrer ao MSDN Library.

ATENÇÃO: Os arquivos estão em formato XPS. Caso não tenha o visualizador, você poderá baixá-lo aqui.

Conteúdo

  • Capítulo 1 – Tipos de dados e Interfaces Este capítulo abordará a arquitetura de tipos fornecido pelo .NET Framework, onde na primeira parte do capítulo, será abordado os tipos padrões padrões e veremos como identificar se trata-se de um tipo valor ou referência. Além disso, analisaremos um problema grave, deixado de lado por muitos desenvolvedores, que é a questão do boxing e unboxing. Ainda nessa primeira parte, analisaremos alguns novos tipos introduzidos nesta versão do .NET Framework, em principal, os Generics. Na segunda e última parte do mesmo, vamos abordar as várias Interfaces que estão disponíveis para serem implementados em tipos customizados, fornecendo funcionalidades adicionais ao tipo criado.

  • Capítulo 2 – Trabalhando com Coleções As coleções são componentes importantes em qualquer tipo de aplicação e, para isso, esse capítulo abordará extensamente o uso das mesmas, começando pelas coleções primárias, fornecidas desde as primeiras versões do .NET Framework até as novas coleções, introduzidas na versão 2.0 do .NET Framework, quais fazem uso dos Generics. Além das coleções, analisaremos as Interfaces disponíveis para podermos estender as funcionalidades existentes e customizarmos para o nosso cenário.
  • Capítulo 3 – Utilização de Assemblies Um Assembly é a menor unidade de reutilização, segurança e controle de versão. O Assembly é algo importante que deve ser analisado cuidadosamente, pois toda aplicação .NET depois de compilada gerará um Assembly. Este capítulo abordará a sua criação desde um utilitário de linha de comando até o Visual Studio .NET. Além disso, abordaremos também outros assuntos relacionados a Assemblies, como por exemplo, strong names, GAC (Global Assembly Cache), instaladores e arquivos de configuração.
  • Capítulo 4 – Monitoramento e depuração de aplicações Toda e qualquer aplicação necessita de algum tipo de monitoramento de seu código para detectar possíveis problemas que possam acontecer e que devem ser analisados. O .NET Framework fornece várias classes que ajudam nesse monitoramento e, este capítulo, é responsável por apresentar essas classes que vão desde a manipulação do Event Log do Windows até classes que interagem com o WMI - Windows Management Instrumentation.
  • Capítulo 5 – Manipulando o sistema de arquivos Grande parte das aplicações comerciais que temos atualmente manipulam arquivos. Esses arquivos são arquivos de bancos, arquivos de parceiros e fornecedores que servem para troca de informações. Enquanto os XML Web Services ainda não são uma realidade para muitas empresas, a manipulação de arquivos e seus respectivos conteúdos é ainda muito utilizado. Tendo esse cenário, o capítulo em questão abordará as principais classes contidas dentro do namespace System.IO para exemplificar e facilitar a manipulação de arquivos do disco e streams de dados.
  • Capítulo 6 – Serialização A serialização de dados é cada dia mais utilizada em aplicações. Por mais que isso aconteça nos bastidores, esse capítulo abordará desde o seu conceito até como implementá-la; e ainda, em seus diversos formatos, utilizando as classes fornecidas pelo .NET Framework 2.0. Além disso, analisaremos classes e Interfaces que temos disponíveis, que proporcionaram o processo de serialização e deserialização mais flexível, onde podemos customizar e interceptar cada um desses processos de acordo com a nossa necessidade.
  • Capítulo 7 – Globalização de Aplicações Cada vez mais se desenvolve softwares que podem ser acessados por várias pessoas de diferentes idiomas e de diferentes locais do mundo. Tendo esse cenário, é importante que a aplicação que estamos desenvolvendo seja possível ao usuário poder customizar o idioma que deseja visualizar os dados e ainda, poder criar a aplicação independente de qualquer cultura. Essa capítulo tem justamente essa finalidade, ou seja, de exibir o que o .NET Framework é capaz de fazer para atender essa necessidade que, torna-se cada vez mais comum.
  • Capítulo 8 – Criptografia Criptografia de dados é um ponto muito importante nos mais diversos tipos de aplicações. Geralmente, em aplicações onde alguns dos dados são muito sigilosos, como é o caso de aplicações financeiras, quais mantém os dados de seus clientes, é necessário que se mantenha esses dados seguros pois, se esses dados cairem em mãos erradas, essas pessoas com más intenções, não consigam entender e/ou recuperar esses dados em sua forma legível. Esse capítulo abordará extensamente as classes responsáveis por criptografia e hashing que o .NET Framework disponiliza, bem como utilizá-las e como aplicá-las ao dia-à-dia.
  • Capítulo 9 – Utilizando Code Access Security – CAS Toda aplicação que utiliza o Common Language Runtime (CLR) obrigatoriamente deve interagir com o sistema de segurança do mesmo. Quando a aplicação é executada, automaticamente é avaliado se ela tem ou não determinados privilégios. Dependendo das permissões que a aplicação tem, ela poderá rodar perfeitamente ou gerar erros relacionados a segurança. Code Access Security (também conhecido como CAS), é um mecanismo que ajuda limitar/conceder o acesso que o código que está querendo realizar, protegendo recursos e operações. Este capítulo abordará como utilizar o CAS, que é fornecido juntamente com o SDK do .NET Framework e, como configurar devidamente a aplicação para evitar problemas relacionados a segurança.
  • Capítulo 10 – Envio de Mensagens (E-mails) Envio de e-mails é muito comum em qualquer tipo de aplicação, seja ela uma aplicação para internet, uma aplicação para Windows ou até mesmo serviços que rodam sem uma intervenção do usuário. O .NET Framework fornece um namespace contendo classes e muitos outros tipos que podemos utilizar nas aplicação para habilitar o envio de e-mails e, conseqüentemente, torná-las muito mais dinâmicas e inteligentes.
  • Capítulo 11 – Criando Serviços do Windows Os Serviços do Windows (Windows Services), permitem-nos criar aplicações que rodam em “background” no sistema operacional. Estes serviços podem ser automaticamente inicializados quando o sistema operacional inicializar, podendo ainda ser pausado e reinicializado, sem apresentar nenhuma interface com o usuário. Esses serviços são ideais para ser usado em servidores ou em funcionalidades de longa duração que necessitem ser executadas de forma totalmente independente, sem a intervenção de um usuário. O capítulo corrente abordará desde a sua criação, depuração e instalação do mesmo.
  • Capítulo 12 – Interoperabilidade com componentes COM A Microsoft criou a plataforma .NET e, em pouco tempo, essa plataforma foi adotada por muitas e muitas empresas. Algo importante é que muitas dessas empresas, já tinham componentes COM que eram utilizados em massa nas aplicações e que são inviáveis para serem reescritos imediatamente. Felizmente a Microsoft pensou no legado e possibilita a interoperabilidade de componentes COM, interagindo com aplicações baseadas na plataforma .NET e vice-versa. Este capítulo mostrará os passos necessários para efetuar essa interoperabilidade entre as novas aplicações e o que já existe em código legado.
  • Capítulo 13 – Reflection Reflection é a habilidade de extrair informações de metadados de um determinado tipo, ou seja, quais parâmetros, métodos, entre outros membros um determinado tipo possui. Isso torna a aplicação bastante flexível, onde podemos extrair informações necessárias para podermos customizar e automatizar a criação de ferramentas e utilitários que auxiliam os próprios desenvolvedores. Além disso, permite a criação em runtime de Assemblies e como instanciar classes via programação. Esse capítulo propõe-se a explicar como criar esse tipo de funcionalidade dentro da aplicação.
  • Capítulo 14 – Threading A criação de threads permitem aumentar consideravelmente a performance das aplicações. Elas fornecem a habilidade de conseguirmos delegar processamentos em diversas unidades de execução, aumentando a capacidade de processamento de uma aplicação. Mas utilizando isso de forma errada, poderá piorar ao invés de melhorar, consumindo mais recursos do que o necessário, tendo um comportamento inesperado e retornando valores diferentes do esperado. O .NET Framework fornece várias classes que podemos utilizar para criação e gerenciamento de threads, bloqueio de recursos em um ambiente multi-threading e sincronização. Este capítulo irá ajudá-lo a conhecer alguns problemas existentes em aplicações que fazem o uso de threads e como contorná-los.

Referências Bibliográficas

  • Code Complete – Second Edition
    Autor: Steve McConnell
    Editora: Microsoft Press
    ISBN: 0-7356-1967-0
  • Writing Secure Code – Second Edition
    Autores: Michael Howard e David LeBlanc
    Editora: Microsoft Press
    ISBN: 0-7356-1722-8
  • CLR via C# – Second Edition
    Autor: Jeffrey Richter
    Editora: Microsoft Press
    ISBN: 0-7356-2163-2
  • Programming Visual C# 2005: The Language
    Autor: Donis Marshall
    Editora Microsoft Press
    ISBN: 0-7356-2181-0
  • Expressões Regulares – Uma abordagem divertida
    Autor: Aurélio Marinho Jargas
    Editora: Novatec
    ISBN: 85-7522-100-0
  • Collection 5160: Core Development with Microsoft .NET Framework 2.0
    Autor/Editor: Microsoft
  • Collection 5161: Advanced Development with Microsoft .NET Framework 2.0
    Autor/Editor: Microsoft

Tags: , , , , , , , ,

.NET Framework | Async | C# | Security | VB.NET

Vista - Delayed Startup Services

by Israel Aece 25. March 2007 20:13

Apesar de não estar utilizando o novo sistema operacional da Microsoft - Windows Vista - tenho lido algumas coisas a respeito do mesmo, e uma das grandes mudanças que temos em relação aos famosos Windows Services é com a nova forma de inicialização que, agora podemos definir como delayed e, para entender melhor qual o impacto desta mudança, veja essa matéria: http://www.vistanews.org/cms/2005/oct/03/delayed-start.

Como podem notar, não é só os aspectos visuais que mudaram no Vista ;)

Tags: ,

General

WCF - Hosting

by Israel Aece 25. March 2007 15:04

Como já sabemos, WCF - Windows Communication Foundation - é parte integrante do .NET Framework 3.0. Ele fornece um conjunto de classes para a construção e hospedagem de serviços baseando-se na arquitetura SOA (Service Oriented Architecture), podendo expor tais serviços para serem acessados através dos mais diversos tipos de protocolos, como por exemplo: HTTP, TCP, IPC e MSMQ. Atualmente existem três tipos de hosts para serviços construídos em WCF: self-hosting (através da classe ServiceHost), IIS (Internet Information Services) e WAS (Windows Activation Services - Windows Vista) e, é exatamente isso que este artigo abordará, ou seja, como configurar cada um desses hosts para expor os serviços construídos em WCF.

Como o foco do artigo é exclusivamente a configuração do host, vou considerar como conhecimento prévio o procedimento para a criação de serviço básico de WCF, principalmente no que diz respeito aos atributos que devem ser aplicados ao serviço para torná-lo um serviço WCF. Para o exemplo, vamos criar um contrato padrão, chamado de IServiceContract, que será implementado pelos serviços concretos. Esse contrato (uma Interface) terá dois métodos simples, chamados de BoasVindas e HoraAtual. Essa Interface está exibida abaixo:

using System;
using System.ServiceModel;

namespace DevMinds.ComponentCS
{
    [ServiceContract]
    public interface IServiceContract
    {
        [OperationContract]
        string BoasVindas();

        [OperationContract]
        DateTime DataAtual();
    }
}

Self-Hosting

O self-hosting trata de uma aplicação, seja ela Console, Windows Forms, Windows Service, etc., que expõe um ou vários serviços para serem consumidos por seus clientes. Para que seja possível expor o serviço programaticamente, ou seja, sem utilizar o IIS ou o WAS, primeiramente é necessário fazer referência ao arquivo System.ServiceModel.dll. Esse Assembly contém todas as classes necessárias para trabalhar com Windows Communication Foundation - WCF - e fornece também a classe ServiceHost. Essa classe fornece toda a infraestrutura necessária para expor serviços WCF.

Um dos overloads do construtor da classe ServiceHost recebe um objeto do tipo Type, onde devemos apontar qual será o tipo que o host irá expor. Em seguida, é necessário definir o endpoint que indicará em que local e com qual protocolo o serviço será exposto e, para atender essa necessidade, a classe ServiceHost fornece um método chamado AddServiceEndpoint para criar quantos endpoints forem necessários para o serviço. A classe ServiceHost ainda fornece alguns eventos que podem ser úteis para fins de monitoramento. Esses eventos estão descritos na tabela abaixo:

Evento Descrição
Closed

Ocorre quando a comunicação com o objeto é fechada.

Closing

Ocorre quando a comunicação com o objeto estiver sendo fechada.

Faulted

Ocorre quando uma falha acontece.

Opened

Ocorre quando a comunicação com o objeto é aberta.

Opening

Ocorre quando a comunicação com o objeto estiver sendo aberta.

UnknownMessageReceived

Ocorre quando uma mensagem desconhecida é recebida.

Para que os clientes possam extrair as informações (metadados) necessárias a respeito do serviço, precisamos expor a descrição do mesmo (que descreve todas as funcionalidades fornecidas pelo serviço, endpoints e seus comportamentos) para que os desenvolvedores possam referenciá-lo nas aplicações clientes que irão consumí-lo. Você pode expor essas informações através do protocolo HTTP (via método Get) ou utilizar um endpoint dedicado. O Windows Communication Foundation disponibiliza os metadados automaticamente para o serviço através de HTTP-GET e, mais adiante, veremos como disponibilizar o contrato através de outros endpoints, com protocolos diferentes. Tudo o que você precisa fazer é habilitar isso, adicionando explicitamente um service behavior.

Resumindo, o MEX (metadata exchange endpoint) é extremamente necessário, já que o cliente necessita importar para ter localmente a representação do serviço e, conseqüentemente, invocá-lo. Para configurarmos um serviço a ser exposto, podemos fazer via código (Visual C# ou Visual Basic .NET) ou declarativamente, através do arquivo *.Config da aplicação. Como discutimos acima, um serviço WCF fornece, por padrão, a descrição do mesmo através do protocolo HTTP-GET; mas para isso, precisamos apenas habilitá-lo, através do atributo httpGetEnabled do elemento serviceMetadata, se estivermos falando da configuração via arquivo *.Config e se quisermos expor a descrição via HTTP-GET.

Ainda há a possibilidade de expor a descrição do serviço através de um endpoint customizado, podendo acessá-lo através de um outro protocolo, como por exemplo o TCP. Este cenário exige a criação de um endpoint simples, como já fazemos normalmente para um serviço qualquer, mas neste caso, o tipo de contrato a ser exposto será baseado na Interface IMetadataExchange, que está definida dentro do namespace System.ServiceModel.Description, o qual expõe métodos que retornam metadados referentes ao serviço.

Os endpoints (que expõem o serviço e os metadados) podem ser configurados declarativamente ou programaticamente. Iremos analisar essas duas formas. Para fins de exemplo, utilizaremos um projeto do tipo Console Application mas, um pouco adiante, falaremos sobre as diversas aplicações que podem servir como host de serviço WCF. O código abaixo exemplifica como criar via código o endpoint necessário para expor o serviço e um outro endpoint para o MEX, ambos utilizando protocolo TCP:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

using DevMinds.ComponentCS;

static void Main(string[] args)
{
    using (ServiceHost host = new ServiceHost(typeof(DefaultService),
        new Uri("net.tcp://localhost:9000/")))
    {
        host.Description.Behaviors.Add(new ServiceMetadataBehavior());

        host.AddServiceEndpoint(
            typeof(IMetadataExchange),
            MetadataExchangeBindings.CreateMexTcpBinding(),
            "MEX/");

        host.AddServiceEndpoint(
            typeof(IServiceContract),
            new NetTcpBinding(),
            "DefaultService/");

        host.Open();
        Console.ReadLine();
    }
}

Como podemos notar, criamos a instância da classe ServiceHost, informando em seu construtor o tipo que a mesma irá servir e em qual endereço irá disponibilizá-la. Em seguida, adicionamos uma instância da classe ServiceMetadataBehavior dentro de uma coleção chamada Behaviors relacionada ao host recém criado; este passo é necessário porque o host valida o tipo de contrato especificado nos endpoints, ou seja, o contrato do endpoint deve ser compatível com o contrato declarado na criação do ServiceHost. No caso acima, a classe que criamos, DefaultService, implementa a Interface IServiceContract, mas não implementa a Interface IMetadataExchange. Internamente quando o host detecta que os tipos não são compatíveis, ele analisa os behaviors que foram registrados; se ele encontrar uma instância da classe ServiceMetadataBehavior, somente com ela presente será possível adicionar o endpoint de metadados, que já está logo em seguida. Neste momento, entra em cena uma classe estática chamada MetadataExchangeBindings. Essa classe fornece membros estáticos que auxiliam na criação de bindings exclusivos para cada um dos protocolos, que irá depender da forma de comunicação que deseja ter com os clientes para saber qual desses métodos utilizar.

A mesma configuração acima dentro do arquivo *.Config fica da seguinte forma (note que no atributo contract do elemento endpoint é necessário especificar a interface do contrato do serviço, incluindo os namespaces até ela):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="DevMinds.ComponentVB.DefaultService" behaviorConfiguration="MEX">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:9000/"/>
          </baseAddresses>
        </host>
        <endpoint
          contract="IMetadataExchange"          
          binding="mexTcpBinding"
          address="MEX/" />
        <endpoint
          contract="DevMinds.ComponentVB.IServiceContract"
          binding="netTcpBinding"
          address="DefaultService/" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MEX">
          <serviceMetadata />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Nota: É importante dizer que a configuração via arquivo *.Config não dispensa a criação do objeto ServiceHost no código e sua abertura através do método Open. A única diferença neste caso, é que não há a necessidade de informar o baseAddress, behaviors e os endpoints.

Com o host devidamente configurado, independente se foi através de código declarativo (*.Config) ou via código, basta inicializar a aplicação e, através do endereço que foi especificado para criar o serviço, você pode adicionar a referencia na aplicação cliente e, em seguida, já conseguirá consumir o serviço.

Como falamos acima, o self-hosting permite utilizarmos uma aplicação .NET para disponibilizá-lo. Existem três tipos de aplicações que podem atender essa necessidade: Console Application (onde baseamos o nosso teste), Windows Forms e Windows Service. A Console Application é muito útil quando estamos efetuando testes ou mesmo em tempo de desenvolvimento e jamais é indicada para o ambiente de produção, já que necessita de um usuário logado na máquina onde o executável reside e, ainda podemos acidentalmente fechar o host, o que evitaria que requisições subseqüentes sejam processadas.

A outra opção é a utilização de criar o host em uma aplicação Windows Forms. Ela é um pouco melhor em relação a Console Application, mas ainda exige que um usuário acesse o sistema para que possa inicializar o host. Finalmente, temos o Windows Service. Este sim é um dos mais apropriados tipos de aplicações para servir como host de uma serviço WCF, pois não necessita que o usuário esteja logado para que funcione e ainda pode ser configurado para ser inicializado automaticamente quando o computador for ligado. Independente disso, o host já deve estar no ar quando a requisição chegar, o que já não acontece com o IIS, pois ele ativa o objeto assim que a requisição chega ao servidor. Analisaremos o host através do IIS na próxima seção.

IIS - Internet Information Services

Até o lançamento do WCF tínhamos (e ainda temos) à disposição dentro da plataforma .NET, a possibilidade de construirmos os famosos Web Services (ASMX). Os Web Services foram lançados desde a versão 1.0 do .NET Framework e revolucionou a forma de como expor dados e componentes para consumo. Eles, por sua vez, estão fortemente ligados à arquitetura do ASP.NET, onde a dependência do protocolo HTTP e algumas de suas funcionalidades específicas são uma das "piores" partes, já que quebra alguns dos conceitos que a arquitetura SOA impõe.

Os serviços WCF também podem utilizar o IIS como hosting, de forma bem semelhante aos Web Services (ASMX), tirando alguns proveitos do mesmo; um dos principais é a ativação do processo, que é feita quando uma requisição chega até o servidor. Mas, como nem tudo é perfeito, o IIS limita o tipo de transporte, obrigando-nos a utilizar somente o protocolo HTTP.

Para que seja possível fazer o host de um serviço dentro do IIS, é necessário que você tenha um arquivo físico com a extensão *.svc. Esse tipo de arquivo está associado com um serviço do WCF e, quando a requisição para um recurso deste tipo chega no servidor, ele é tratado através de um módulo chamado HttpModule em conjunto com um handler chamado HttpHandler, que estão contidos dentro do namespace System.ServiceModel.Activation (isso pode ser confirmado através do arquivo Web.Config que está dentro do seguinte endereço: %windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG). A forma com que estes objetos trabalham irá depender do modo de compatibilidade com o ASP.NET que pode estar ou não estar habilitado. Analisaremos os dois modos existentes mais adiante, ainda neste artigo.

Os arquivo com extensão *.svc tem uma diretiva ServiceHost, onde informamos a linguagem que estaremos escrevendo o código, o nome do serviço e o caminho até o arquivo de CodeBehind do serviço, que reside dentro da pasta especial App_Code. Isso é bem semelhante à estrutura de uma página ASP.NET. O código abaixo mostra a estrutura, de apenas uma linha, de um arquivo *.svc:

[ C# ]
<%@ ServiceHost Language="C#" 
                   Debug="true" 
                   Service="DefaultService"
                   CodeBehind="~/App_Code/DefaultService.cs" %>

Dentro do arquivo de CodeBehind criamos uma classe e implementamos a Interface IServiceContract (já comentada mais acima). Depois de realizada a devida implementação devida realizada, definindo efetivamente o que os métodos irão fazer, é necessário criarmos o endpoint no arquivo Web.Config para que o IIS consiga identificar e expor o serviço. A configuração é bem semelhante ao arquivo App.Config que vimos acima, que configura o serviço em um self-hosting. Ligeiras mudanças são realizadas, conforme é mostrado abaixo:

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="DefaultService" behaviorConfiguration="returnFaults">
        <endpoint 
          contract="DevMinds.ComponentCS.IServiceContract" 
          binding="wsHttpBinding"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="returnFaults">
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

É importante analisar que na criação do endpoint não é necessário o atributo address, pois o endereço (base address) será determinado a partir do endereço do arquivo *.svc. Outro detalhe importante é com relação ao atributo httpGetEnabled do elemento serviceMetadata que, quando estiver definido como True, é responsável por habilitar que o contrato do serviço seja publicado e, conseqüentemente, acessado pelos clientes. Finalmente, o atributo includeExceptionDetailInFaults, que é utilizado para propósitos de depuração pois, quando é definido como True, propaga qualquer exceção atirada pelo serviço para os clientes, facilitando a depuração quando estamos consumindo o serviço em um ambiente de testes. Claro que essa informação somente deve ser disponibilizada quando o serviço ainda está em processo de desenvolvimento, pois se essas informações chegarem aos clientes finais, você pode estar abrindo brechas para que ele possa explorar as informações de erro, inclusive o stack trace.

Ao invocar o serviço no browser, já conseguimos ter acesso ao mesmo, inclusive ao seu contrato. A imagem abaixo ilustra o serviço sendo apresentado no browser:

Figura 1 - Output do serviço sendo invocado no browser.

Neste momento o serviço já está pronto para ser consumido pelos clientes e, como podemos notar na imagem acima, ela mesma exibe um exemplo de como gerar o proxy no cliente, através do utilitário svcutil.exe ou ainda, se estiver utilizando o Visual Studio .NET 2005 com o .NET Framework 3.0 devidamente instalado, pode ir diretamente no projeto onde deseja consumir o serviço, clicar com o botão direito do mouse em cima do mesmo e, em seguida, clicar na opção "Add Service Reference...", informando o endereço HTTP acima, que automaticamente o proxy será gerado e adicionado à aplicação.

Podemos tranquilamente criar um diretório virtual dentro do IIS para hospedar os serviços WCF. Porém há cenários onde os serviços WCF estão dentro do IIS, mas contidos em uma aplicação ASP.NET ou até mesmo em uma aplicação do tipo Web Services (ASMX). Em todas as ocasiões, muitas vezes é necessário fazer o uso de algumas funcionalidades específicas do protocolo HTTP para atender uma determinada necessidade, como por exemplo, a utilização de variáveis de aplicação (Application), sessão (Session) ou até mesmo informações contidas no contexto HTTP (HttpContext). O WCF, em conjunto com o runtime do ASP.NET, fornece dois modos de execução de um pedido para um serviço, que tratam de forma bem diferente a requisição ao *.svc. Essas formas são: Mixed Transports Mode ou ASP.NET Compatibility Mode, as quais falaremos a seguir.

Na primeira delas, Mixed Transports Mode (modo default), a requisição do serviço não é executada pelo ASP.NET pipeline. Isso permite definir endpoints com diferentes formas de transportes. Uma das características mais importantes deste modo é que ele não permite que serviços WCF façam uso de funcionalidades específicas do ASP.NET, mais precisamente do protocolo HTTP. Entre as funcionalidades desabilitadas em virtude de ter esse modo habilitado temos:

Funcionalidade Desabilitada Descrição
HttpContext.Current

Em uma aplicação tradicional Web, a classe HttpContext encapsula informações específicas a respeito da requisição HTTP, que estão acessíveis através da propriedade estática Current.

Em um serviço WCF, essa propriedade sempre retornará nula, mas existe uma classe chamada OperationContext que, através de uma propriedade estática, também chamada Current, retorna informações a respeito conteúdo atual da requisição.

File e UrlAuthorization

A autorização, que é efetuada a partir da seção authorization no arquivo Web.Config, está também desabilitada. Para autorização, você precisará implementar isso nas mensagens que são enviadas/recebidas pelos serviços WCF.

Impersonation

A capacidade de impersonificação que o ASP.NET fornece através do elemento identity passa a ficar desabilitada neste modo.

Session State

As variáveis de sessões não são suportadas neste modo (lembrem-se que isso difere bastante as Sessões do WCF, que serão abordados em um futuro artigo).

Outras

Outras funcionalidades também estão desabilitadas, como é o exemplo da globalização (acessada através do elemento globalization). Além disso, outras funcionalidades que dependem da classe HttpContext, também podem não funcionar corretamente, como é o caso da seção AppSettings.

Já o ASP.NET Compatibility Mode trata de um modo que habilita todas as restrições impostas pelo modo anterior, mas impõe um grande ponto negativo, ou seja, o serviço fica completamente dependente do protocolo HTTP e, sendo assim, quando o serviço estiver sendo ativado, os endpoints serão verificados para assegurar que protocolos não-HTTP estão habilitados.

Existe um elemento no arquivo Web.Config que permite-nos declarativamente habilitar ou desabilitar esse modo. Trata-se do atributo aspNetCompatibilityEnabled do elemento serviceHostingEnvironment. Quando definido como False (padrão), o modo utilizado é o Mixed Transports Mode e, quando True, o modo ASP.NET Compatibility Mode está habilitado. Mas, para habilitar o modo ASP.NET Compatibility Mode, ainda é preciso de uma configuração adicional, mas desta vez diretamente na classe que representa e implementa o contrato do serviço, que é decorar a classe com o atributo AspNetCompatibilityRequirements, que está contido dentro do namespace System.ServiceModel.Activation e configurá-lo de acordo com a necessidade. Esse atributo recebe, através da propriedade RequirementsMode, um dos três valores contidos no enumerador AspNetCompatibilityRequirementsMode, os quais são explicados abaixo:

Opção Descrição
Allowed

Esta opção indica que o serviço pode rodar no modo ASP.NET Compatibility. Mas, internamente, deverá se comportar bem quando esse recurso não estiver habilitado.

NotAllowed

Não permite que o serviço rode em modo ASP.NET Compatibility. Essa opção é utilizada em cenário onde o serviço não é construído exclusivamente para HTTP.

Required

Indica que o serviço exige o modo ASP.NET Compatibility para rodar e, neste caso, poderá fazer o uso das características acima sem nenhuma preocupação, já que essa opção garantirá que o serviço irá rodar em um ambiente onde as características específicas de HTTP estarão habilitadas.

Os trechos de código abaixo, com algumas partes suprimidas por questões de espaço, ilustram a configuração na classe do serviço e no arquivo Web.Config para habilitar o ASP.NET Compatibility Mode:

using System.ServiceModel.Activation;

[AspNetCompatibilityRequirements(
    RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class DefaultService : IServiceContract
{
    //Restante da implementação
}

 

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <services>
      <service name="DefaultService">
        <!-- Endpoints -->
      </service>
    </services>
    <!-- Outras Configurações -->
  </system.serviceModel>
</configuration>

Um pouco acima falamos sobre o módulo HttpModule e o handler HttpHandler, que fazem parte da execução do processamento de uma requisição para um serviço WCF. A forma de trabalho irá depender exclusivamente do modo que está habilitado. Se o modo Mixed Transports estiver habilitado, o módulo HttpHandler irá interceptar a requisição logo após o evento PostAuthenticateRequest e, neste momento, o objeto HttpContext.Current é definido como nulo. Agora, quando o modo ASP.NET Compatibility estiver habilitado, o módulo HttpModule será um simples filtro, sem fazer nada de mais importante. Depois da execução do módulo, o handler é finalmente executado, para efetivamente fazer o trabalho do serviço WCF.

WAS - Windows Activation Services

O Windows Vista fornece um novo recurso chamado WAS - Windows Activation Services. Trata-se de um processo que é instalado dentro do IIS 7, que desacopla a arquitetura de ativação do IIS, permitindo assim o transporte não somente via HTTP, mas também via named pipes, TCP e MSMQ (message queue).

Um outro ponto importante é que, além de suportar múltiplos protocolos, fornece as funcionalidades dadas pelo IIS, como por exemplo o health monitoring, reciclagem de processo e, conseqüentemente, ferramentas de gerenciamento para tais configurações.

Quando o listener de um determinado protocolo recebe a requisição, o WAS verifica a existência do work process para serví-lo e, antes de processar a requisição, o handler assegura que uma instância da classe ServiceHost tenha sido criada. Assim como vimos no IIS, felizmente o WAS utiliza também o modelo de ativação baseado na mensagem, o que aumenta a escalabilidade para as requisições em qualquer protocolo.

O WAS, por padrão, não vêm instalado por padrão. É necessário fazer alguns ajustes para habilitá-lo e, conseqüentemente, disponibilizar serviços WCF para serem consumidos nos mais diversos protocolos. Deixarei a configuração e utilização do WAS dentro do IIS 7 (com Windows Vista) para um futuro artigo, dedicando-o para explorar completamente esse novo recurso.

Conclusão: Como podemos notar no decorrer deste artigo, todo o host basicamente deverá ser um processo executável, que terá um AppDomain onde o serviço será carregado. Agora, com todas essas alternativas, você deve analisar e ser capaz de escolher qual das soluções é mais viável à sua necessidade, sempre pesando os prós e contras de cada um dos tipos de host.

Tags: , , , ,

CSD | WCF

Console Application vs. Windows Services

by Israel Aece 10. August 2005 23:19

Estamos prestes a automatizar um serviço de envio e recebimento de arquivos para um dos clientes da empresa onde trabalho. Essa automação consistirá em enviar um arquivo contendo uma relação de documentos para serem cadastrados na base de dados interna.

Existe um serviço de terceiro de faz o papel intermediário, ou seja, é um serviço (client (feito em Java)) que fica instalado em uma máquina qualquer e, dentro deste fazemos um agendamento de quanto em quanto tempo queremos que ele corra e assim, ele vai até um servidor, recupera o arquivo com a relação de documentos e deposita em um diretório local na máquina (em nossa empresa) em que o mesmo está instalado/configurado.

Meu papel entra agora, ou seja, teremos que criar algo para também de tempo em tempo ficar verificando se existe ou não um novo arquivo neste diretório e, caso existir, tenho que consistí-lo e consequentemente move-lo para uma outra máquina que irá processar este arquivo e fazer todas as entradas dentro da DB. Bem, não se tem muito segredo em como "ouvir" um determinado diretório do disco, ou seja, podemos, por exemplo, utilizar a classe FileSystemWatcher para alcançarmos isso.

A questão é como "hospedar" isso, ou seja, que tipo de aplicação desenvolver para alcançar essa funcionalidade: Windows Service ou uma Console Application? Com um Windows Service, poderia no evento OnStart deste iniciar o Watcher para "escutar" o diretório. Poderia também criar uma Thread que corra de X em X tempo executar; e quando ela executar, utilizaria o método GetFiles da classe Directory para verificar a existencia de arquivos.

É também perfeitamente possível criar uma Console Application que, também poderia utilizar o FileSystemWatcher para "escutar" o diretório e processar os arquivos.

A guerra entre estes dois tipos de aplicação é qual é melhor usar. Windows Services tem um ponto positivo, onde podemos definir para ele iniciar sozinho quando o sistema operacional "subir", mas requer a instalação através do utilitário installutil.exe e também exige que o desenvolvedor conheça um pouco mais sobre essa tecnologia. Já as Console Applications não necessitam de uma instalação (claro, o .NET Framework deve existir onde vai correr a aplicação), mas seu ponto negativo é que necessitam de uma intervenção humana para inicializá-la.

Podemos de certa forma transformar uma Console Application com as mesmas características de um Windows Services, ou seja, no Iniciar do Windows poderia definí-la para inicializá-la automaticamente e como a mesma ficará "eternamente ouvindo" o diretório pré-definido, conseguiria alcançar o meu ideal. Além disso, ainda poderia utilizar o agendador do Windows para estipular quando e de quanto em quanto tempo quero que ele execute.

Pois bem, como essa automatização ainda estamos iniciando e estudando o processo, vai dar analisada para saber qual deles escolher e, também se alguém tiver alguma solução e/ou comentário, deixe-me saber por favor.

Tags:

.NET Framework

Powered by BlogEngine.NET 1.5.0.0
Theme by Mads Kristensen

Sobre

Meu nome é Israel Aece e sou especialista em tecnologias de desenvolvimento Microsoft, atuando como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. [ Mais ]

Twitter

Host