| Home | Artigos | Busca | Blog | Sobre | Contato |

RSS [ Visitar Blog ]

Criação de projeto "dummy" para cliente WCF
Wed, 20 Aug 2008 07:08:00 GMT

Quando estamos fazendo testes com serviços WCF, a idéia é sempre criar um serviço e consumí-lo em alguma aplicação cliente para testar se tudo corre como esperado. Mas quando o exemplo é simples, onde queremos testar apenas algumas funcionalidades, podemos utilizar uma técnica para criar o host e também, no mesmo projeto, poderíamos consumir o serviço sem a necessidade de criar um projeto dummy para isso.

As primeiras linhas consistem na criação e configuração do host e, depois que ele estiver aberto, então podemos recorrer ao uso da classe genérica ChannelFactory<TChannel> que podemos informar o contrato que estamos utilizando/testando, o ponto de acesso (endpoint) e o binding. O método CreateChannel utiliza o endpoint e o binding especificado no construtor para criar e estabelecer o canal de comunicação.

string address = "http://localhost:9388";

using (ServiceHost host = new ServiceHost(typeof(Servico), new Uri[] { new Uri(address) }))
{
    host.AddServiceEndpoint(typeof(IContrato), new BasicHttpBinding(), string.Empty);
    host.Open();

    using (ChannelFactory<IContrato> srv =
        new ChannelFactory<IContrato>(new BasicHttpBinding(), new EndpointAddress(address)))
    {
        Console.WriteLine(srv.CreateChannel().Metodo("Israel Aece"));
    }
}

Evitando a remoção do Cache
Thu, 14 Aug 2008 07:51:00 GMT

Thomas Marquardt mostra aqui uma nova funcionalidade da API de Caching do ASP.NET 3.5. Basicamente a idéia aqui é interceptar o momento antes do item ser efetivamente removido do cache.

RedirectMode
Thu, 14 Aug 2008 07:36:00 GMT

O Service Pack 1 do .NET Framework 3.5 incluiu um novo recurso, onde voce poderá definir qual será a forma de redirecionamento quando estiver com o customErrors habilitado. Agora temos um atributo chamado RedirectMode, onde voce poderá definir dois valores:

  • ResponseRedirect: exibe a página de erro mundando a Url original da página que foi solicitada.
  • ResponseRewrite: exibe a página de erro sem mudar a Url da página original que foi solicitada.

Abaixo um simples exemplo:

<customErrors mode="On" redirectMode="ResponseRewrite">
    <error statusCode="500" redirect="Erro.aspx"/>
</customErrors>

O atributo Action do WebForm
Thu, 14 Aug 2008 07:25:00 GMT
Alguém havia me solicitado isso em algum momento e agora é possível.
Melhorias no WCF com SP1
Thu, 14 Aug 2008 07:19:00 GMT

O Service Pack 1 do .NET Framework 3.5 e o Serviço Pack 1 do Visual Studio 2008 trouxeram algumas melhorias interessantes no WCF:

  • UriTemplate: agora podemos incluir um valor padrão para algum parametro que será invocado via REST. Algo como: [WebGet(UriTemplate = "RecuperarUsuarios/{quantidade=5}")].
  • Atributo DataContract/DataMember: a partir de agora não precisamos explicitamente definir quais são os objetos e propriedades que serão expostos para serviços quando estamos trabalhando com tipos complexos. Ele entende que tudo será exposto. Temos apenas que nos preocuparmos em marcar o que não queremos que seja serializado.
  • Partial Trust: possibilidade de fazer o uso do Event Log em ambiente parcialmente confiável.
  • Hosting Wizard: basicamente é a mesma funcionalidade do "Publish Web Site", mas para um serviço WCF.
  • WCF Options: quando tem um projeto do tipo Wcf Service Library na solução, nas propriedades deste projeto temos uma aba chamada WCF Options. Dentro da mesma, há uma opção chamada: Start WCF Service Host when debugging another project in the same solution. Ao marcá-la, ao rodar qualquer projeto em modo de depuração, o WCF Test Client irá iniciar para tornar o serviço disponível para que outras aplicações na mesma solução o utilizem.
Novo comportamento do EventValidation
Thu, 14 Aug 2008 04:01:00 GMT

Há algum tempo eu comentei a respeito de alguns cuidados que precisamos ter com o EventValidation. Um outro cenário em que este mesmo erro está propício a acontecer, é quando estamos dentro de uma página muito complexa ou com muitas informações e que a sua renderização demora para acontecer por inteira.

O EventValidation se baseia em um campo oculto chamado __EVENTVALIDATION para validar o controle que gerou o postback. O próprio runtime do ASP.NET embuti este controle no final da página (pouco antes da tag de fechamento do formulário (</form>)), durante o processo de renderização. O grande problema que temos aqui é que as vezes, a renderização pode ocorrer parcialmente e, caso um controle que cause postback apareça para o usuário e ele clicar, um postback será efetuado sem o envio do campo oculto __EVENTVALIDATION, pois ele ainda não foi renderizado.

O Service Pack 1 do .NET Framework 3.5 resolve isso, ou seja, agora a renderização deste campo (e de todos os outros campos ocultos "auto-gerados"), por padrão, passa a ser efetuada no ínicio do formulário, permitindo assim efetuar postbacks sem esperar a página renderizar por inteira.

E, para finalizar, é importante dizer que voce pode controlar isso através do atributo renderAllHiddenFieldsAtTopOfForm do elemento pages, no arquivo Web.config:

<pages renderAllHiddenFieldsAtTopOfForm="true|false" />

Async Handler
Thu, 07 Aug 2008 09:18:00 GMT

Desde a versão 1.x do ASP.NET podemos facilmente criar um handler para permitir a execução de algum código. O idéia por detrás deste handler, é justamente servir como alvo para alguma requisição. Um exemplo muito típico é a extração de arquivos do banco de dados, arquivos do disco, geração automática de imagens, etc..

Havia alguns detalhes necessários na versão 1.x que, se não realizados, não funcionava adequadamente. A partir da versão 2.0, a Microsoft incluiu um novo tipo de arquivo, com extensão ASHX, chamado de Generic Handler. Esse arquivo traz uma classe que, por padrão, implementa a interface IHttpHandler, cabendo aos desenvolvedores implementar o método ProcessRequest para tratar o pedido.

O problema é que o processamento deste handler estará ocupando uma thread do ThreadPool que, por sua vez, serve as requisições para as páginas da aplicação. Caso o código a ser realizado dentro deste handler for um processo custoso, podemos comprometer as outras requisições que nada tem a ver com ele (este artigo explica mais detalhes sobre este comportamento).

Para permitir que o handler também faça o uso do processamento assíncrono, podemos fazer com que o mesmo implemente a interface IHttpAsyncHandler e, ao invés de implementar o método ProcessRequest, devemos implementar os métodos BeginProcessRequest e EndProcessRequest. O exemplo abaixo utiliza os métodos (BeginRead e EndRead) para leitura assíncrona de um arquivo do disco:

public class ImageAsyncHandler : IHttpAsyncHandler
{
    private struct InnerState : IDisposable
    {
        public HttpContext HttpContext;
        public FileStream Stream;

        public void Dispose()
        {
            if (this.Stream != null)
                this.Stream.Dispose();
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    public IAsyncResult BeginProcessRequest(HttpContext context,
        AsyncCallback cb, object extraData)
    {
        string fileName =
            context.Server.MapPath(context.Request.QueryString["FileName"]);

        FileStream fs = new FileStream(fileName, FileMode.Open);
        int length = (int)fs.Length;

        return fs.BeginRead(new byte[length], 0, length, cb,
            new InnerState()
            {
                HttpContext = context
                , Stream = fs
            });
    }

    public void ProcessRequest(HttpContext context) { }

    public void EndProcessRequest(IAsyncResult result)
    {
        using (InnerState state = (InnerState)result.AsyncState)
        {
            int length = state.Stream.EndRead(result);
            state.Stream.Position = 0;
           
            byte[] temp = new byte[length];
            state.Stream.Read(temp, 0, length);

            state.HttpContext.Response.OutputStream.Write(temp, 0, length);
        }
    }
}

Esse processo não mudará nada o resultado final do handler, mas trabalhará de uma forma muito mais otimizada, garantido que threads criadas para servir a aplicação não fiquem ocupadas executando um processamento mais custoso. Caso a imagem ou os dados venham de um banco de dados, podemos combinar essa técnica com os métodos assíncronos do ADO.NET 2.0.

Depurando Host com Client
Wed, 30 Jul 2008 17:19:00 GMT

Durante o desenvolvimento de serviços WCF ou qualquer outra coisa que envolva Host e Client, é comum utilizarmos o recurso de depuração de múltiplos projetos que o Visual Studio fornece. Assim, sempre quando um processo dá problemas (exceções), o outro continua rodando até que, explicitamente, voce o finalize.

Sara Ford dá aqui uma dica interessante para encerrar todos os processos, caso algum deles de problema durante a execução.

Arquivos de Configuração para serviços COM+
Wed, 30 Jul 2008 06:57:00 GMT

Há algum tempo, quando eu ainda fazia curso de COM+, em alguma das minhas noites em claro eu encontrei uma dica interessante (desculpe-me, mas não lembro da referencia) que talvez, utilizaria em algum lugar.

Hoje precisei fazer o uso de uma library em um dos componentes que está rodando dentro do COM+. Até então sem muitos problemas, até que vi que algumas configurações desta library precisavam ser realizadas no arquivo de configuração. Mas onde está o arquivo de configuração de componentes que estão hospedados no COM+? Se a aplicação do COM+ fosse do tipo Library (que é criada dentro do mesmo processo do criador), bastaria eu colocar as configurações no arquivo de configuração da aplicação cliente mas, no meu caso, a aplicação tratava-se de uma aplicação do tipo Server (que é criada em um processo a parte (dllhost.exe)).

Se formos até as propriedades da aplicação COM+, na aba Activation, veremos que há um campo chamado Application Root Directory. Podemos colocar ali o caminho até um diretório no disco exclusivo para esta aplicação e, dentro deste diretório, precisamos também criar 2 arquivos: um é o próprio arquivo tradicional de configuração (application.config); já o segundo, trata-se de um manifesto (application.manifest), que descreve as dependencias que a aplicação requer, mas que neste caso, pode ser simplesmente:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" />

Agora pode-se rodar sem maiores problemas que os dados serão capturados deste arquivo. Como o dllhost.exe está dentro do %Windir%\System32, eu acredito que se seguirmos o padrão do .NET, que é criar um arquivo de configuração dentro do mesmo diretório da aplicação, deve funcionar sem problemas (dllhost.exe.config), mas o problema é que isso pode servir várias aplicações e poderemos ter confusões/complicações aqui.

Postando para um serviço WCF
Mon, 28 Jul 2008 17:41:00 GMT

Uma das coisas mais interessantes que podemos fazer com os serviços RestFul é a possibilidade de postar um conteúdo de um formulário de uma página Web diretamente para um serviço. Isso possibilitará aplicações HTML, PHP, ASP, etc., enviar informações para um serviço WCF, sem a necessidade de conhecer e/ou criar o protocolo SOAP.

O código cliente muda ligeiramente, apenas definindo a URL do serviço como sendo o action do formulário:

<form action="http://localhost:3344/srv/Send" method="post">
    Nome: <input type="text" name="nome" />
    E-mail: <input type="text" name="email" />
    <input type="hidden" name="campoOculto" value="xpto" />

    <input type="submit" value="Enviar" />
</form>

Há alguns detalhes na implementação do serviço para permitir isso. Detalhes que foram abordados aqui.


ASP.NET ©2003-2007 Projetando.NET