<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>Israel Aéce</title><link>http://weblogs.pontonetpt.com/israelaece/</link><description>Microsoft MVP, MCP, MCAD, MCTS, MCPD e MCT</description><dc:language>en-US</dc:language><generator>RSS Generated by Dottext 0.94</generator><item><dc:creator>Israel Aéce</dc:creator><title>Customizando o OutputCache</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28421.aspx</link><pubDate>Thu, 20 Nov 2008 02:28:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28421.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28421.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28421.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28421.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28421</trackback:ping><description>&lt;p align="justify"&gt;Um dia desses um colega me perguntou como customizar, ou melhor, como variar o &lt;em&gt;OutputCaching&lt;/em&gt; de uma página para cada usuário da aplicação. Entre as opções que a diretiva &lt;a href="http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx"&gt;@OutputCache&lt;/a&gt; fornece, temos a opção &lt;em&gt;VaryByCustom&lt;/em&gt;,&lt;em&gt; &lt;/em&gt;especificando como valor deste atributo uma &lt;em&gt;string&lt;/em&gt; qualquer, com a finalidade de definirmos uma informação, que indicará como proceder para capturar a "chave" que será utilizada pelo &lt;em&gt;runtime&lt;/em&gt;, para determinar se já existe ou não uma versão do &lt;em&gt;cache&lt;/em&gt;. Abaixo está a configuração desta diretiva:&lt;br /&gt;&lt;br /&gt;&amp;lt;%@ OutputCache Duration="60" VaryByCustom="UserName" VaryByParam="none" %&amp;gt;&lt;br /&gt;&lt;br /&gt;Quando utilizamos esta técnica, devemos sobrescrever o método &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.getvarybycustomstring.aspx"&gt;GetVaryByCustomString&lt;/a&gt; da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.aspx"&gt;HttpApplication&lt;/a&gt; (leia-se &lt;em&gt;Global.asax&lt;/em&gt;) e, lá colocar o código que irá retornar a &lt;em&gt;string&lt;/em&gt; que servirá de "chave", para que o ASP.NET use-a para determinar se já existe ou não uma versão para ela. No nosso caso, a finalidade é criar uma versão de &lt;em&gt;caching&lt;/em&gt; para cada usuário, portanto, temos o seguinte código:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;public override string&lt;/font&gt; GetVaryByCustomString(HttpContext context, &lt;font color="#0000ff"&gt;string&lt;/font&gt; custom)&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;if&lt;/font&gt;(custom == "UserName" &amp;amp;&amp;amp; context.User.Identity.IsAuthenticated)&lt;br /&gt;        &lt;font color="#0000ff"&gt;return&lt;/font&gt; context.User.Identity.Name;&lt;/p&gt;
&lt;p align="justify"&gt;   &lt;font color="#0000ff"&gt; return base&lt;/font&gt;.GetVaryByCustomString(context, custom);&lt;br /&gt;}&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Um dia desses um colega me perguntou como customizar, ou melhor, como variar o <em>OutputCaching</em> de uma página para cada usuário da aplicação. Entre as opções que a diretiva <a href="http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx">@OutputCache</a> fornece, temos a opção <em>VaryByCustom</em>,<em> </em>especificando como valor deste atributo uma <em>string</em> qualquer, com a finalidade de definirmos uma informação, que indicará como proceder para capturar a "chave" que será utilizada pelo <em>runtime</em>, para determinar se já existe ou não uma versão do <em>cache</em>. Abaixo está a configuração desta diretiva:<br /><br />&lt;%@ OutputCache Duration="60" VaryByCustom="UserName" VaryByParam="none" %&gt;<br /><br />Quando utilizamos esta técnica, devemos sobrescrever o método <a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.getvarybycustomstring.aspx">GetVaryByCustomString</a> da classe <a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.aspx">HttpApplication</a> (leia-se <em>Global.asax</em>) e, lá colocar o código que irá retornar a <em>string</em> que servirá de "chave", para que o ASP.NET use-a para determinar se já existe ou não uma versão para ela. No nosso caso, a finalidade é criar uma versão de <em>caching</em> para cada usuário, portanto, temos o seguinte código:<br /><br /><font color="#0000ff">public override string</font> GetVaryByCustomString(HttpContext context, <font color="#0000ff">string</font> custom)<br />{<br />    <font color="#0000ff">if</font>(custom == "UserName" &amp;&amp; context.User.Identity.IsAuthenticated)<br />        <font color="#0000ff">return</font> context.User.Identity.Name;</p>
<p align="justify">   <font color="#0000ff"> return base</font>.GetVaryByCustomString(context, custom);<br />}</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>Transição do Cliente para o Serviço (Debugger)</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28418.aspx</link><pubDate>Wed, 19 Nov 2008 15:14:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28418.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28418.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28418.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28418.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28418</trackback:ping><description>&lt;p align="justify"&gt;O Visual Studio .NET 2008 traz uma funcionalidade que permite aos desenvolvedores de serviços WCF, efetuar a depuração do mesmo através do cliente, ou seja, quando estamos executando o cliente em modo de depuração, ao chamar uma operação através da instancia do &lt;em&gt;proxy&lt;/em&gt; (via &lt;em&gt;F11 - Step Into&lt;/em&gt;), automaticamente seremos redirecionados para o método do serviço, executando-o passo-à-passo.&lt;br /&gt;&lt;br /&gt;Ao pressionar &lt;em&gt;F11&lt;/em&gt;, o &lt;em&gt;debugger&lt;/em&gt; automaticamente irá se vincular ao processo que corresponde efetua o &lt;em&gt;host&lt;/em&gt; do serviço e, ao finalizar a execução do método, o controle voltará ao cliente. O mais importante é que a janela &lt;em&gt;Call Stack&lt;/em&gt; traz informações tanto do cliente como do serviço.&lt;br /&gt;&lt;br /&gt;Caso voce não esteja fazendo uso destas funcionalidades, então provavelmente isso está desabilitado. Para habilitar este recurso, basta recorrer ao utilitário &lt;strong&gt;vsdiag_regwcf.exe&lt;/strong&gt;. Este utilitário está disponível a partir do &lt;em&gt;Prompt&lt;/em&gt; de comando do Visual Studio .NET 2008 (se estiver rodando no Windows Vista, então é necessário rodar como Administrador) e, via os seguintes parametros, voce poderá interagir com ele:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;-i&lt;/strong&gt;: Habilita o recurso.&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;-u&lt;/strong&gt;: Desabilita o recurso.&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;-s&lt;/strong&gt;: Exibe se o recurso está habilitado ou desabilitado.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">O Visual Studio .NET 2008 traz uma funcionalidade que permite aos desenvolvedores de serviços WCF, efetuar a depuração do mesmo através do cliente, ou seja, quando estamos executando o cliente em modo de depuração, ao chamar uma operação através da instancia do <em>proxy</em> (via <em>F11 - Step Into</em>), automaticamente seremos redirecionados para o método do serviço, executando-o passo-à-passo.<br /><br />Ao pressionar <em>F11</em>, o <em>debugger</em> automaticamente irá se vincular ao processo que corresponde efetua o <em>host</em> do serviço e, ao finalizar a execução do método, o controle voltará ao cliente. O mais importante é que a janela <em>Call Stack</em> traz informações tanto do cliente como do serviço.<br /><br />Caso voce não esteja fazendo uso destas funcionalidades, então provavelmente isso está desabilitado. Para habilitar este recurso, basta recorrer ao utilitário <strong>vsdiag_regwcf.exe</strong>. Este utilitário está disponível a partir do <em>Prompt</em> de comando do Visual Studio .NET 2008 (se estiver rodando no Windows Vista, então é necessário rodar como Administrador) e, via os seguintes parametros, voce poderá interagir com ele:</p>
<ul>
<li>
<div align="justify"><strong>-i</strong>: Habilita o recurso.</div>
</li><li>
<div align="justify"><strong>-u</strong>: Desabilita o recurso.</div>
</li><li>
<div align="justify"><strong>-s</strong>: Exibe se o recurso está habilitado ou desabilitado.</div></li></ul></body></item><item><dc:creator>Israel Aéce</dc:creator><title>UserName e Certificados</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28412.aspx</link><pubDate>Tue, 18 Nov 2008 16:24:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28412.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28412.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28412.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28412.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28412</trackback:ping><description>&lt;p align="justify"&gt;Os &lt;em&gt;ASP.NET Web Services&lt;/em&gt; fornecem uma possibilidade de efetuar a autenticação do serviço através de &lt;em&gt;SOAP Headers&lt;/em&gt;. Para isso, bastava criar uma classe que herde da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapheader.aspx"&gt;SoapHeader&lt;/a&gt; e criar as propriedades &lt;em&gt;UserName/Password&lt;/em&gt; e, via &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapheaderattribute.aspx"&gt;SoapHeaderAttribute&lt;/a&gt;, voce vinculava este header aos métodos que exigem a autenticação do usuário para poder funcionar.&lt;br /&gt;&lt;br /&gt;Essa configuração funciona bem, mas é vulnerável. A questão é que o envelope SOAP irá trafegar entre o cliente e o serviço de forma desprotegida e, sendo assim, qualquer um que interceptar a requisição, conseguirá extrair essas informações confidenciais. A autenticação baseada em &lt;em&gt;SOAP Headers&lt;/em&gt; apenas são seguras se o transporte garantir a segurança; em outras palavras, isso quer dizer HTTPS. Outra alternativa ainda utilizando os tradicionais &lt;em&gt;ASP.NET Web Services&lt;/em&gt;, seria a utilização do &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=018a09fd-3a74-43c5-8ec1-8d789091255d&amp;amp;displaylang=en"&gt;WSE&lt;/a&gt; (&lt;em&gt;Web Services Enhancements&lt;/em&gt;), que possibilita a segurança em nível de mensagens.&lt;br /&gt;&lt;br /&gt;O WCF, que é seguro por padrão, tem um comportamento ligeiramente diferente em relação aos &lt;em&gt;ASP.NET Web Services&lt;/em&gt;. Para utilizar a autenticação baseada em &lt;em&gt;UserName/Password&lt;/em&gt; que o WCF fornece sob o protocolo HTTP, será necessário utilizar um certificado. Sem a utilização deste, não seria possível garantir a integridade e confidencialidade da mensagem, comprometendo as informações e, principalmente, permitindo que alguém intercepte a mensagem e capture os dados sigilosos. Assim como os &lt;em&gt;ASP.NET Web Services&lt;/em&gt;, se o serviço WCF for exposto via HTTPS, isso não é necessário, mas utilizar segurança baseada em transporte tem seu ponto negativo: a segurança é apenas garantida ponto-a-ponto e, caso haja intermediários entre o cliente e o serviço, não temos a garantia de que a mensagem chegará segura até o destino.&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Os <em>ASP.NET Web Services</em> fornecem uma possibilidade de efetuar a autenticação do serviço através de <em>SOAP Headers</em>. Para isso, bastava criar uma classe que herde da classe <a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapheader.aspx">SoapHeader</a> e criar as propriedades <em>UserName/Password</em> e, via <a href="http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapheaderattribute.aspx">SoapHeaderAttribute</a>, voce vinculava este header aos métodos que exigem a autenticação do usuário para poder funcionar.<br /><br />Essa configuração funciona bem, mas é vulnerável. A questão é que o envelope SOAP irá trafegar entre o cliente e o serviço de forma desprotegida e, sendo assim, qualquer um que interceptar a requisição, conseguirá extrair essas informações confidenciais. A autenticação baseada em <em>SOAP Headers</em> apenas são seguras se o transporte garantir a segurança; em outras palavras, isso quer dizer HTTPS. Outra alternativa ainda utilizando os tradicionais <em>ASP.NET Web Services</em>, seria a utilização do <a href="http://www.microsoft.com/downloads/details.aspx?familyid=018a09fd-3a74-43c5-8ec1-8d789091255d&amp;displaylang=en">WSE</a> (<em>Web Services Enhancements</em>), que possibilita a segurança em nível de mensagens.<br /><br />O WCF, que é seguro por padrão, tem um comportamento ligeiramente diferente em relação aos <em>ASP.NET Web Services</em>. Para utilizar a autenticação baseada em <em>UserName/Password</em> que o WCF fornece sob o protocolo HTTP, será necessário utilizar um certificado. Sem a utilização deste, não seria possível garantir a integridade e confidencialidade da mensagem, comprometendo as informações e, principalmente, permitindo que alguém intercepte a mensagem e capture os dados sigilosos. Assim como os <em>ASP.NET Web Services</em>, se o serviço WCF for exposto via HTTPS, isso não é necessário, mas utilizar segurança baseada em transporte tem seu ponto negativo: a segurança é apenas garantida ponto-a-ponto e, caso haja intermediários entre o cliente e o serviço, não temos a garantia de que a mensagem chegará segura até o destino.</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>Customizando o Health Monitoring</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28403.aspx</link><pubDate>Wed, 12 Nov 2008 15:39:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28403.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28403.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28403.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28403.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28403</trackback:ping><description>&lt;p align="justify"&gt;Estou trabalhando em um projeto que utiliza o &lt;a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=60"&gt;Health Monitoring&lt;/a&gt; para notificações de que alguma falha ocorreu na aplicação. Essa configuração faz com que qualquer exceção não tratada, seja capturada pelo &lt;em&gt;Health Monitoring&lt;/em&gt; e a seção &lt;a href="http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx"&gt;customErrors&lt;/a&gt; garante uma página amigável para o usuário final.&lt;br /&gt;&lt;br /&gt;A maioria dos erros não tratados são ocasionados por certos valores que são passados através de algum campo no formulário e, muito raramente, através de  &lt;em&gt;query strings &lt;/em&gt;(no caso deste projeto). A configuração padrão do &lt;em&gt;Health Monitoring&lt;/em&gt; traz a &lt;em&gt;stack trace&lt;/em&gt; do erro que ocorreu e outras informações relevantes ao problema, como o usuário, tipo da exceção, servidor, processo, etc. O problema é que, para simular o erro em um ambiente de teste ou até mesmo em produção, é necessário termos os mesmos valores especificados pelo usuário, para assim tornar essa simulação o mais próximo do que ocorreu. Para isso, podemos criar um evento customizado e fazer uso dele quando uma exceção for disparada.&lt;br /&gt;&lt;br /&gt;Essa classe que representará o evento customizado herda diretamente da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.management.webrequesterrorevent.aspx"&gt;WebRequestErrorEvent&lt;/a&gt; e tem o nome de &lt;em&gt;WebParametersRequestErrorEvent&lt;/em&gt;. Ao contrário dos eventos padrões que já estão embutidos no ASP.NET, os eventos customizados devem ser explicitamente disparados e, para poupar código, podemos criar um módulo. O módulo fornece a instancia da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.aspx"&gt;HttpApplication&lt;/a&gt; que nos permite interceptar o evento &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.error.aspx"&gt;Error&lt;/a&gt; que, por sua vez, é disparado sempre quando um erro não tratado ocorre na aplicação. Com isso, basta simplesmente instanciar e invocar o método &lt;a href="http://msdn.microsoft.com/en-us/library/8t5cy7a9.aspx"&gt;Raise&lt;/a&gt; do evento customizado.&lt;br /&gt;&lt;br /&gt;Finalmente, apenas o que precisamos é configurar devidamente o &lt;em&gt;Health Monitoring&lt;/em&gt; no arquivo &lt;em&gt;Web.Config&lt;/em&gt; da aplicação, fazendo o mapeamento entre o &lt;em&gt;eventMapping&lt;/em&gt;, &lt;em&gt;rules&lt;/em&gt; e &lt;em&gt;providers&lt;/em&gt;, como é mostrado detalhadamente através do código abaixo:&lt;br /&gt;&lt;br /&gt;&amp;lt;system.web&amp;gt;&lt;br /&gt;    &amp;lt;healthMonitoring enabled="true" heartbeatInterval="0"&amp;gt;&lt;br /&gt;        &amp;lt;providers&amp;gt;&lt;br /&gt;            &amp;lt;add &lt;br /&gt;                name="SimpleMailWebEventProvider" &lt;br /&gt;                type="System.Web.Management.SimpleMailWebEventProvider" &lt;br /&gt;                from="&lt;a href="mailto:suporte@site.com.br"&gt;suporte@site.com.br&lt;/a&gt;" &lt;br /&gt;                to="&lt;a href="mailto:israel@site.com.br"&gt;israel@site.com.br&lt;/a&gt;" &lt;br /&gt;                buffer="false" /&amp;gt;&lt;br /&gt;        &amp;lt;/providers&amp;gt;&lt;br /&gt;        &amp;lt;rules&amp;gt;&lt;br /&gt;            &amp;lt;add &lt;br /&gt;                name="WebParametersRequestErrorEventModule Mail" &lt;br /&gt;                eventName="WebParametersRequestErrorEvent" &lt;br /&gt;                provider="SimpleMailWebEventProvider" &lt;br /&gt;                profile="Default" &lt;br /&gt;                minInstances="1" &lt;br /&gt;                maxLimit="Infinite" &lt;br /&gt;                minInterval="00:00:00"/&amp;gt;&lt;br /&gt;        &amp;lt;/rules&amp;gt;&lt;br /&gt;        &amp;lt;eventMappings&amp;gt;&lt;br /&gt;            &amp;lt;add &lt;br /&gt;                name="WebParametersRequestErrorEvent" &lt;br /&gt;                type="Logger.WebParametersRequestErrorEvent, Logger"/&amp;gt;&lt;br /&gt;        &amp;lt;/eventMappings&amp;gt;&lt;br /&gt;    &amp;lt;/healthMonitoring&amp;gt;&lt;br /&gt;    &amp;lt;httpModules&amp;gt;&lt;br /&gt;        &amp;lt;add &lt;br /&gt;            name="WebParametersRequestErrorEventModule" &lt;br /&gt;            type="Logger.WebParametersRequestErrorEventModule, Logger"/&amp;gt;&lt;br /&gt;    &amp;lt;/httpModules&amp;gt;&lt;br /&gt;&amp;lt;system.net&amp;gt;&lt;br /&gt;&lt;br /&gt;Ao receber o e-mail, tenho todos os detalhes do erro que já era fornecido pelo evento &lt;em&gt;WebRequestErrorEvent&lt;/em&gt;, e mais os dados contextuais da requisição:&lt;br /&gt;&lt;br /&gt;Custom event details: &lt;br /&gt;    Request - QueryStrings&lt;br /&gt;            ID: 123&lt;br /&gt;            Nome: Israel Aece&lt;br /&gt;            E-mail: &lt;a href="mailto:israel@projetando.net"&gt;israel@projetando.net&lt;/a&gt;&lt;br /&gt;    Request - Forms&lt;br /&gt;            __VIEWSTATE: /wEPDwUJOTQ4N...m+ks3yA==&lt;br /&gt;            __EVENTVALIDATION: /wEWBALs0J+...ewcwK+BGBh&lt;br /&gt;            txtValor: 123,45&lt;br /&gt;            txtNome: Jack Bauer&lt;br /&gt;            Button1: Button&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Download:&lt;/strong&gt; &lt;a href="http://www.projetando.net/Temp/Posts/WebParametersRequestErrorEvent.cs.txt"&gt;WebParametersRequestErrorEvent&lt;/a&gt; e &lt;a href="http://www.projetando.net/Temp/Posts/WebParametersRequestErrorEventModule.cs.txt"&gt;WebParametersRequestErrorEventModule&lt;/a&gt;.&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Estou trabalhando em um projeto que utiliza o <a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=60">Health Monitoring</a> para notificações de que alguma falha ocorreu na aplicação. Essa configuração faz com que qualquer exceção não tratada, seja capturada pelo <em>Health Monitoring</em> e a seção <a href="http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx">customErrors</a> garante uma página amigável para o usuário final.<br /><br />A maioria dos erros não tratados são ocasionados por certos valores que são passados através de algum campo no formulário e, muito raramente, através de  <em>query strings </em>(no caso deste projeto). A configuração padrão do <em>Health Monitoring</em> traz a <em>stack trace</em> do erro que ocorreu e outras informações relevantes ao problema, como o usuário, tipo da exceção, servidor, processo, etc. O problema é que, para simular o erro em um ambiente de teste ou até mesmo em produção, é necessário termos os mesmos valores especificados pelo usuário, para assim tornar essa simulação o mais próximo do que ocorreu. Para isso, podemos criar um evento customizado e fazer uso dele quando uma exceção for disparada.<br /><br />Essa classe que representará o evento customizado herda diretamente da classe <a href="http://msdn.microsoft.com/en-us/library/system.web.management.webrequesterrorevent.aspx">WebRequestErrorEvent</a> e tem o nome de <em>WebParametersRequestErrorEvent</em>. Ao contrário dos eventos padrões que já estão embutidos no ASP.NET, os eventos customizados devem ser explicitamente disparados e, para poupar código, podemos criar um módulo. O módulo fornece a instancia da classe <a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.aspx">HttpApplication</a> que nos permite interceptar o evento <a href="http://msdn.microsoft.com/en-us/library/system.web.httpapplication.error.aspx">Error</a> que, por sua vez, é disparado sempre quando um erro não tratado ocorre na aplicação. Com isso, basta simplesmente instanciar e invocar o método <a href="http://msdn.microsoft.com/en-us/library/8t5cy7a9.aspx">Raise</a> do evento customizado.<br /><br />Finalmente, apenas o que precisamos é configurar devidamente o <em>Health Monitoring</em> no arquivo <em>Web.Config</em> da aplicação, fazendo o mapeamento entre o <em>eventMapping</em>, <em>rules</em> e <em>providers</em>, como é mostrado detalhadamente através do código abaixo:<br /><br />&lt;system.web&gt;<br />    &lt;healthMonitoring enabled="true" heartbeatInterval="0"&gt;<br />        &lt;providers&gt;<br />            &lt;add <br />                name="SimpleMailWebEventProvider" <br />                type="System.Web.Management.SimpleMailWebEventProvider" <br />                from="<a href="mailto:suporte@site.com.br">suporte@site.com.br</a>" <br />                to="<a href="mailto:israel@site.com.br">israel@site.com.br</a>" <br />                buffer="false" /&gt;<br />        &lt;/providers&gt;<br />        &lt;rules&gt;<br />            &lt;add <br />                name="WebParametersRequestErrorEventModule Mail" <br />                eventName="WebParametersRequestErrorEvent" <br />                provider="SimpleMailWebEventProvider" <br />                profile="Default" <br />                minInstances="1" <br />                maxLimit="Infinite" <br />                minInterval="00:00:00"/&gt;<br />        &lt;/rules&gt;<br />        &lt;eventMappings&gt;<br />            &lt;add <br />                name="WebParametersRequestErrorEvent" <br />                type="Logger.WebParametersRequestErrorEvent, Logger"/&gt;<br />        &lt;/eventMappings&gt;<br />    &lt;/healthMonitoring&gt;<br />    &lt;httpModules&gt;<br />        &lt;add <br />            name="WebParametersRequestErrorEventModule" <br />            type="Logger.WebParametersRequestErrorEventModule, Logger"/&gt;<br />    &lt;/httpModules&gt;<br />&lt;system.net&gt;<br /><br />Ao receber o e-mail, tenho todos os detalhes do erro que já era fornecido pelo evento <em>WebRequestErrorEvent</em>, e mais os dados contextuais da requisição:<br /><br />Custom event details: <br />    Request - QueryStrings<br />            ID: 123<br />            Nome: Israel Aece<br />            E-mail: <a href="mailto:israel@projetando.net">israel@projetando.net</a><br />    Request - Forms<br />            __VIEWSTATE: /wEPDwUJOTQ4N...m+ks3yA==<br />            __EVENTVALIDATION: /wEWBALs0J+...ewcwK+BGBh<br />            txtValor: 123,45<br />            txtNome: Jack Bauer<br />            Button1: Button<br /><br /><strong>Download:</strong> <a href="http://www.projetando.net/Temp/Posts/WebParametersRequestErrorEvent.cs.txt">WebParametersRequestErrorEvent</a> e <a href="http://www.projetando.net/Temp/Posts/WebParametersRequestErrorEventModule.cs.txt">WebParametersRequestErrorEventModule</a>.</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>encodedValue</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28393.aspx</link><pubDate>Fri, 07 Nov 2008 23:11:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28393.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28393.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28393.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28393.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28393</trackback:ping><description>&lt;p align="justify"&gt;Quando fazemos uma referencia a um serviço WCF, e ele possuir um certificado definido para assegurar a troca de informações entre o cliente o e serviço, a IDE do Visual Studio ou o utilitário &lt;em&gt;svcutil.exe&lt;/em&gt;, adicionanão um elemento chamado &lt;em&gt;identity/certificate&lt;/em&gt; com o atributo &lt;em&gt;encodedValue&lt;/em&gt;. O valor deste atributo é uma série de letras e números mas, o que isso representa?&lt;br /&gt;&lt;br /&gt;Essa informação trata-se da chave pública do certificado, codificada no padrão &lt;em&gt;Base64&lt;/em&gt;. Ela será utilizada pelo &lt;em&gt;runtime&lt;/em&gt; do WCF para criptografar as informações que serão trocadas, mais precisamente, as credenciais. Quando essa informação não existir no cliente, a configuração do serviço deverá permitir a negociação ou informar a referencia para o certificado que, geralmente, esta armazenado em um dos repositórios do cliente.&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Quando fazemos uma referencia a um serviço WCF, e ele possuir um certificado definido para assegurar a troca de informações entre o cliente o e serviço, a IDE do Visual Studio ou o utilitário <em>svcutil.exe</em>, adicionanão um elemento chamado <em>identity/certificate</em> com o atributo <em>encodedValue</em>. O valor deste atributo é uma série de letras e números mas, o que isso representa?<br /><br />Essa informação trata-se da chave pública do certificado, codificada no padrão <em>Base64</em>. Ela será utilizada pelo <em>runtime</em> do WCF para criptografar as informações que serão trocadas, mais precisamente, as credenciais. Quando essa informação não existir no cliente, a configuração do serviço deverá permitir a negociação ou informar a referencia para o certificado que, geralmente, esta armazenado em um dos repositórios do cliente.</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>Bloco "using" no cliente</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28379.aspx</link><pubDate>Mon, 03 Nov 2008 15:41:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28379.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28379.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28379.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28379.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28379</trackback:ping><description>&lt;p align="justify"&gt;É muito comum envolvermos objetos que utilizam recursos custosos dentro de um bloco &lt;em&gt;using&lt;/em&gt;, fazendo com que o método &lt;em&gt;Dispose&lt;/em&gt; do mesmo seja disparado independemente de exceções que sejam disparadas durante a execução. Vale lembrar que somente podemos envolver objetos que implementam a &lt;em&gt;interface&lt;/em&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx"&gt;IDisposable&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Quando fazemos a referencia para algum serviço WCF em uma aplicação cliente, automaticamente a IDE do Visual Studio (ou através do utilitário &lt;a href="http://msdn.microsoft.com/en-us/library/aa347733.aspx"&gt;svcutil.exe&lt;/a&gt;), se encarregará de criar uma classe que herda diretamente da classe abstrata, chamada &lt;a href="http://msdn.microsoft.com/en-us/library/ms576141.aspx"&gt;ClientBase&amp;lt;TChannel&amp;gt;&lt;/a&gt;. Essa classe implementa tudo o que é necessário para possibilitar a comunicação entre cliente e o serviço (em outras palavras, trata-se do &lt;em&gt;proxy&lt;/em&gt;) e, que por sua vez, faz uso de objetos caros (&lt;em&gt;channels, etc.&lt;/em&gt;) e que precisam ser brevemente liberados. Como a classe &lt;em&gt;ClientBase&amp;lt;TChannel&amp;gt;&lt;/em&gt; implementa a &lt;em&gt;interface IDisposable&lt;/em&gt;, isso quer dizer que podemos envolver a instancia do &lt;em&gt;proxy&lt;/em&gt; em um bloco &lt;em&gt;using&lt;/em&gt;, para que o método &lt;em&gt;Dispose&lt;/em&gt; seja automaticamente disparado.&lt;br /&gt;&lt;br /&gt;Se envolvermos o &lt;em&gt;proxy&lt;/em&gt; em um bloco &lt;em&gt;using&lt;/em&gt; (lembre-se de que ele será transformado em &lt;em&gt;try/finally&lt;/em&gt;), é necessário tomarmos um certo cuidado. Não porque o método &lt;em&gt;Dispose&lt;/em&gt; não será chamado, mas sim onde que a execução deste método afetará a aplicação cliente. Vamos supor que algum erro ocorra durante a execução da operação e, como já era de se esperar, o bloco &lt;em&gt;finally&lt;/em&gt; será disparado, chamando o método &lt;em&gt;Dispose&lt;/em&gt; do &lt;em&gt;proxy&lt;/em&gt;. Neste caso, o método &lt;em&gt;Dispose&lt;/em&gt; não faz mais nada a não ser invocar o método &lt;em&gt;Close&lt;/em&gt;. O problema aqui é que o método &lt;em&gt;Close&lt;/em&gt; poderá exigir algumas atividades extras, necessitando fazer alguma outra comunicação com o serviço e, se neste momento algum erro ocorrer, a exceção que chegará ao cliente será:&lt;br /&gt;&lt;br /&gt;&lt;font color="#ff0000"&gt;System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;..., mascarando assim, o real problema. Finalmente, a opção para contornar esse possível problema, é a chamada do método &lt;a href="http://msdn.microsoft.com/en-us/library/ms575270.aspx"&gt;Abort&lt;/a&gt;, que encerra imediatamente a comunicação entre o cliente o serviço, assim como é demonstrado &lt;a href="http://msdn.microsoft.com/en-us/library/aa355056.aspx"&gt;neste link&lt;/a&gt;.&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">É muito comum envolvermos objetos que utilizam recursos custosos dentro de um bloco <em>using</em>, fazendo com que o método <em>Dispose</em> do mesmo seja disparado independemente de exceções que sejam disparadas durante a execução. Vale lembrar que somente podemos envolver objetos que implementam a <em>interface</em> <a href="http://msdn.microsoft.com/en-us/library/system.idisposable.aspx">IDisposable</a>.<br /><br />Quando fazemos a referencia para algum serviço WCF em uma aplicação cliente, automaticamente a IDE do Visual Studio (ou através do utilitário <a href="http://msdn.microsoft.com/en-us/library/aa347733.aspx">svcutil.exe</a>), se encarregará de criar uma classe que herda diretamente da classe abstrata, chamada <a href="http://msdn.microsoft.com/en-us/library/ms576141.aspx">ClientBase&lt;TChannel&gt;</a>. Essa classe implementa tudo o que é necessário para possibilitar a comunicação entre cliente e o serviço (em outras palavras, trata-se do <em>proxy</em>) e, que por sua vez, faz uso de objetos caros (<em>channels, etc.</em>) e que precisam ser brevemente liberados. Como a classe <em>ClientBase&lt;TChannel&gt;</em> implementa a <em>interface IDisposable</em>, isso quer dizer que podemos envolver a instancia do <em>proxy</em> em um bloco <em>using</em>, para que o método <em>Dispose</em> seja automaticamente disparado.<br /><br />Se envolvermos o <em>proxy</em> em um bloco <em>using</em> (lembre-se de que ele será transformado em <em>try/finally</em>), é necessário tomarmos um certo cuidado. Não porque o método <em>Dispose</em> não será chamado, mas sim onde que a execução deste método afetará a aplicação cliente. Vamos supor que algum erro ocorra durante a execução da operação e, como já era de se esperar, o bloco <em>finally</em> será disparado, chamando o método <em>Dispose</em> do <em>proxy</em>. Neste caso, o método <em>Dispose</em> não faz mais nada a não ser invocar o método <em>Close</em>. O problema aqui é que o método <em>Close</em> poderá exigir algumas atividades extras, necessitando fazer alguma outra comunicação com o serviço e, se neste momento algum erro ocorrer, a exceção que chegará ao cliente será:<br /><br /><font color="#ff0000">System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.</font><br /><br />..., mascarando assim, o real problema. Finalmente, a opção para contornar esse possível problema, é a chamada do método <a href="http://msdn.microsoft.com/en-us/library/ms575270.aspx">Abort</a>, que encerra imediatamente a comunicação entre o cliente o serviço, assim como é demonstrado <a href="http://msdn.microsoft.com/en-us/library/aa355056.aspx">neste link</a>.</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>WSHttpBinding vs. WS2007HttpBinding</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28377.aspx</link><pubDate>Sun, 02 Nov 2008 20:00:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28377.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28377.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28377.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28377.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28377</trackback:ping><description>&lt;p align="justify"&gt;A Microsoft criou o WCF e implementou nele os protocolos de segurança, transações e sessões confiáveis baseando-se nas primeiras versões destes padrões, que são gerenciados pela OASIS.&lt;br /&gt;&lt;br /&gt;Com o .NET Framework 3.5, a Microsoft atualizou o WCF, disponibilizando agora a implementação mais atualizada destes protocolos através de dois novos &lt;em&gt;bindings&lt;/em&gt;: &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.ws2007httpbinding.aspx"&gt;WS2007HttpBinding&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.ws2007federationhttpbinding.aspx"&gt;WS2007FederationBinding&lt;/a&gt;.&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">A Microsoft criou o WCF e implementou nele os protocolos de segurança, transações e sessões confiáveis baseando-se nas primeiras versões destes padrões, que são gerenciados pela OASIS.<br /><br />Com o .NET Framework 3.5, a Microsoft atualizou o WCF, disponibilizando agora a implementação mais atualizada destes protocolos através de dois novos <em>bindings</em>: <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.ws2007httpbinding.aspx">WS2007HttpBinding</a> e <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.ws2007federationhttpbinding.aspx">WS2007FederationBinding</a>.</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>Load Balancing em serviços WCF</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28370.aspx</link><pubDate>Fri, 31 Oct 2008 20:01:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28370.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28370.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28370.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28370.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28370</trackback:ping><description>&lt;p align="justify"&gt;Quando precisamos de escalabilidade em nossas aplicações, é muito comum recorrermos a técnicas de &lt;em&gt;cluster&lt;/em&gt;, &lt;em&gt;failover&lt;/em&gt; ou &lt;em&gt;load balancing &lt;/em&gt;para que seja possível atender as muitas requisições que chegam para a mesma.&lt;br /&gt;&lt;br /&gt;Serviços WCF não são diferentes. Serviços que estão disponíveis através do protocolo HTTP, se comportam como aplicações ASP.NET. Uma vez que eles são expostos, podem ser acessados por milhares de clientes, afetando a sua performance. Para habilitar a técnica de &lt;em&gt;load balancing&lt;/em&gt; para serviços WCF (HTTP), é importante que voce se atente a que funcionalidades que o seu serviço WCF utiliza e, principalmente, qual a &lt;a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=84"&gt;forma de gerenciamento de instancia&lt;/a&gt; configurada.&lt;br /&gt;&lt;br /&gt;Quando o serviço é configurado no modo &lt;em&gt;PerCall&lt;/em&gt;, cada requisição criará uma instancia do serviço, executará a operação e, quando finalizar, a instancia criada será descartada; uma nova requisição, recria um novo objeto, executa a operação e o descarta e, assim sucessivamente. Já quando o modo é definido como &lt;em&gt;PerSession&lt;/em&gt;, a idéia é manter uma instancia do serviço dedicada para cada &lt;em&gt;proxy&lt;/em&gt;, atendendo a todas as operações oriundas daquele cliente.&lt;br /&gt;&lt;br /&gt;Caso o serviço esteja em um ambiente de &lt;em&gt;load balancing&lt;/em&gt; com o modo &lt;em&gt;PerSession&lt;/em&gt; definido, podemos ter alguns problemas e, entre eles, a garantia de que a requisição será sempre atendida por um determinado servidor. Neste caso, perdemos o estado do serviço, trazendo resultados inesperados para este modo. O &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpbinding.aspx"&gt;BasicHttpBinding&lt;/a&gt; não suporta sessão, ao contrário do &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.wshttpbinding.aspx"&gt;WSHttpBinding&lt;/a&gt; que, por sua vez, emula o suporte a sessão mas que, é ineficaz neste ambiente, já que o WCF não traz suporte de gerenciamento de estado/sessão &lt;em&gt;"cross-machine"&lt;/em&gt; como é o caso do ASP.NET.  Finalmente, o modo &lt;em&gt;Single&lt;/em&gt; também necessita um cuidado especial, já que apenas haverá uma única instancia para atender a todas as requisições. Onde será armazenada a instancia da classe que representa o serviço?&lt;br /&gt;&lt;br /&gt;Sempre que possível, em um ambiente de alta escalabilidade, opte pela opção &lt;em&gt;PerCall&lt;/em&gt;. Mas quando houver a necessidade de armazenar informações entre as requisições do cliente, uma alternativa para serviços &lt;em&gt;PerCall&lt;/em&gt;, é incluir um identificador no contrato (ou extraí-lo das informações contextuais) para salvar e/ou carregar o estado e, como repositório, deve ser utilizado um recurso compartilhado, como uma base de dados.&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Quando precisamos de escalabilidade em nossas aplicações, é muito comum recorrermos a técnicas de <em>cluster</em>, <em>failover</em> ou <em>load balancing </em>para que seja possível atender as muitas requisições que chegam para a mesma.<br /><br />Serviços WCF não são diferentes. Serviços que estão disponíveis através do protocolo HTTP, se comportam como aplicações ASP.NET. Uma vez que eles são expostos, podem ser acessados por milhares de clientes, afetando a sua performance. Para habilitar a técnica de <em>load balancing</em> para serviços WCF (HTTP), é importante que voce se atente a que funcionalidades que o seu serviço WCF utiliza e, principalmente, qual a <a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=84">forma de gerenciamento de instancia</a> configurada.<br /><br />Quando o serviço é configurado no modo <em>PerCall</em>, cada requisição criará uma instancia do serviço, executará a operação e, quando finalizar, a instancia criada será descartada; uma nova requisição, recria um novo objeto, executa a operação e o descarta e, assim sucessivamente. Já quando o modo é definido como <em>PerSession</em>, a idéia é manter uma instancia do serviço dedicada para cada <em>proxy</em>, atendendo a todas as operações oriundas daquele cliente.<br /><br />Caso o serviço esteja em um ambiente de <em>load balancing</em> com o modo <em>PerSession</em> definido, podemos ter alguns problemas e, entre eles, a garantia de que a requisição será sempre atendida por um determinado servidor. Neste caso, perdemos o estado do serviço, trazendo resultados inesperados para este modo. O <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpbinding.aspx">BasicHttpBinding</a> não suporta sessão, ao contrário do <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.wshttpbinding.aspx">WSHttpBinding</a> que, por sua vez, emula o suporte a sessão mas que, é ineficaz neste ambiente, já que o WCF não traz suporte de gerenciamento de estado/sessão <em>"cross-machine"</em> como é o caso do ASP.NET.  Finalmente, o modo <em>Single</em> também necessita um cuidado especial, já que apenas haverá uma única instancia para atender a todas as requisições. Onde será armazenada a instancia da classe que representa o serviço?<br /><br />Sempre que possível, em um ambiente de alta escalabilidade, opte pela opção <em>PerCall</em>. Mas quando houver a necessidade de armazenar informações entre as requisições do cliente, uma alternativa para serviços <em>PerCall</em>, é incluir um identificador no contrato (ou extraí-lo das informações contextuais) para salvar e/ou carregar o estado e, como repositório, deve ser utilizado um recurso compartilhado, como uma base de dados.</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>MemoryMappedFile</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28365.aspx</link><pubDate>Thu, 30 Oct 2008 04:56:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28365.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28365.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28365.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28365.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28365</trackback:ping><description>&lt;p align="justify"&gt;Por curiosidade, abri o &lt;a href="http://www.red-gate.com/products/reflector/"&gt;.NET Reflector&lt;/a&gt; com o .NET Framework 4.0 e comecei a explorar as classes que ele disponibiliza e, logo percebi um novo &lt;em&gt;namespace&lt;/em&gt;: &lt;em&gt;System.IO.MemoryMappedFiles&lt;/em&gt;. Dentro deste &lt;em&gt;namespace&lt;/em&gt;, entre as poucas classes, temos a classe &lt;em&gt;MemoryMappedFile&lt;/em&gt;. &lt;em&gt;É importante dizer que é uma versão CTP, sem a garantia de que isso prevalecerá na versão final.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;A finalidade dela é mapear um espaço da memória para o conteúdo de um determinado arquivo (ou algum outro recurso), criando um objeto que servirá de "ponte" entre a aplicação e o arquivo físico, criandos &lt;em&gt;"views"&lt;/em&gt; deste arquivo e, &lt;a href="http://en.wikipedia.org/wiki/Memory-mapped_file"&gt;como principal benefício&lt;/a&gt;, permitirá acessar "seções" do arquivo, sem carregá-lo completamente para a memória. Abaixo um exemplo simples que faz a utilização desta classe:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;System.IO;&lt;br /&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;System.IO.MemoryMappedFiles&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;using &lt;/font&gt;(MemoryMappedFile mmf = &lt;br /&gt;    MemoryMappedFile.CreateFromFile(&lt;font color="#0000ff"&gt;new&lt;/font&gt; FileStream("C:\Teste.txt", FileMode.Open)))&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;byte&lt;/font&gt;[] buffer = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#0000ff"&gt;byte&lt;/font&gt;[5];&lt;br /&gt;    mmf.CreateViewStream(120, 5).Read(buffer, 0, 5);&lt;br /&gt;    Console.WriteLine(Encoding.Default.GetString(buffer));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;O primeiro parametro do método &lt;em&gt;CreateViewStream&lt;/em&gt; é a posição inicial dentro do arquivo e, o segundo, a quantidade de caracteres que voce quer extrair.&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Por curiosidade, abri o <a href="http://www.red-gate.com/products/reflector/">.NET Reflector</a> com o .NET Framework 4.0 e comecei a explorar as classes que ele disponibiliza e, logo percebi um novo <em>namespace</em>: <em>System.IO.MemoryMappedFiles</em>. Dentro deste <em>namespace</em>, entre as poucas classes, temos a classe <em>MemoryMappedFile</em>. <em>É importante dizer que é uma versão CTP, sem a garantia de que isso prevalecerá na versão final.</em><br /><br />A finalidade dela é mapear um espaço da memória para o conteúdo de um determinado arquivo (ou algum outro recurso), criando um objeto que servirá de "ponte" entre a aplicação e o arquivo físico, criandos <em>"views"</em> deste arquivo e, <a href="http://en.wikipedia.org/wiki/Memory-mapped_file">como principal benefício</a>, permitirá acessar "seções" do arquivo, sem carregá-lo completamente para a memória. Abaixo um exemplo simples que faz a utilização desta classe:<br /><br /><font color="#0000ff">using </font>System.IO;<br /><font color="#0000ff">using </font>System.IO.MemoryMappedFiles<br /><br /><font color="#0000ff">using </font>(MemoryMappedFile mmf = <br />    MemoryMappedFile.CreateFromFile(<font color="#0000ff">new</font> FileStream("C:\Teste.txt", FileMode.Open)))<br />{<br />    <font color="#0000ff">byte</font>[] buffer = <font color="#0000ff">new</font> <font color="#0000ff">byte</font>[5];<br />    mmf.CreateViewStream(120, 5).Read(buffer, 0, 5);<br />    Console.WriteLine(Encoding.Default.GetString(buffer));<br />}<br /><br />O primeiro parametro do método <em>CreateViewStream</em> é a posição inicial dentro do arquivo e, o segundo, a quantidade de caracteres que voce quer extrair.</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>WCF REST Starter Kit</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28363.aspx</link><pubDate>Thu, 30 Oct 2008 02:35:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28363.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28363.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28363.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28363.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28363</trackback:ping><description>&lt;p align="justify"&gt;Há algum tempo &lt;a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=80"&gt;eu escrevi&lt;/a&gt; sobre a possibilidade de criar serviços REST em WCF. Visando incrementar esses tipos de serviços, a Microsoft disponibilizou recentemente o &lt;a href="http://msdn.microsoft.com/en-us/netframework/cc950529.aspx"&gt;Windows Communication Foundation REST Stater Kit&lt;/a&gt;. Este &lt;em&gt;kit&lt;/em&gt; fornece &lt;em&gt;templates&lt;/em&gt; de projeto e diversas funcionalidades para serviços REST criados sob WCF. As funcionalidades fornecidas pelo &lt;em&gt;kit&lt;/em&gt; facilita o uso do protocolo HTTP dentro do serviço e encapsula algumas funcionalidades expostas pelo ASP.NET. Entre as principais funcionalidades, temos &lt;em&gt;caching&lt;/em&gt;, tratamento/manipulador de erros, página de suporte, estensibilidade, etc.&lt;br /&gt;&lt;br /&gt;Todas as funcionalidades estão contidas no &lt;em&gt;assembly Microsoft.ServiceModel.Web.dll&lt;/em&gt;. O &lt;em&gt;caching&lt;/em&gt; funciona de forma muito parecida com o &lt;em&gt;caching&lt;/em&gt; do &lt;em&gt;ASP.NET/ASP.NET Web Services&lt;/em&gt;, pois foi criado um atributo chamado &lt;em&gt;WebCacheAttribute&lt;/em&gt; que, podemos aplicar em algum método de nosso serviço. Exemplo:&lt;br /&gt;&lt;br /&gt;[WebGet(UriTemplate = "")]&lt;br /&gt;[WebCache(Duration = 30)]&lt;br /&gt;[OperationContract]&lt;br /&gt;&lt;font color="#0000ff"&gt;string&lt;/font&gt; RecuperarAlgumaInformacao();&lt;br /&gt;&lt;br /&gt;Outra possibilidade que temos, é a criação de uma página de suporte, que traz informações relacionadas aos métodos que o serviço disponibiliza. Para acessá-la, basta colocar &lt;em&gt;"/help"&lt;/em&gt; no final da URL do serviço que, automaticamente, uma "página amigável" será exibida com essas informações. Vale lembrar que voce poderá customizar a descrição de um determinado método, através do atributo  &lt;em&gt;WebHelpAttribute&lt;/em&gt;, como é mostrado abaixo:&lt;br /&gt;&lt;br /&gt;[WebGet(UriTemplate = "")]&lt;br /&gt;[WebHelp(Comment = "Retorna uma informação qualquer.")]&lt;br /&gt;[OperationContract]&lt;br /&gt;&lt;font color="#0000ff"&gt;string &lt;/font&gt;RecuperarAlgumaInformacao();&lt;br /&gt;&lt;br /&gt;Alguns novos tipos também foram estendidos para suportar essas novas funcionalidades. Entre esses tipos, temos as classes &lt;em&gt;WebServiceHost2&lt;/em&gt;, &lt;em&gt;WebServiceHost2Factory&lt;/em&gt; e &lt;em&gt;WebHttpBehavior2&lt;/em&gt;. Esses tipos são semelhantes aos existentes no .NET Framework 3.5, mais precisamente, dentro do &lt;em&gt;Assembly System.ServiceModel.Web.dll&lt;/em&gt;. O &lt;em&gt;WebServiceHost2&lt;/em&gt; possui uma propriedade chamada &lt;em&gt;Interceptors&lt;/em&gt; que, como o próprio nome diz, permite-nos acoplar um "interceptador" e colocar ali algum código que desejamos executar durante a requisição.  Para criar um interceptador, tudo o que precisamos fazer é herdar da classe abstrata &lt;em&gt;RequestInterceptor&lt;/em&gt; e sobrescrever o método &lt;em&gt;ProcessRequest&lt;/em&gt;, como é mostrado abaixo:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;public class&lt;/font&gt; MeuInterceptador : RequestInterceptor&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;public&lt;/font&gt; MeuInterceptador() : &lt;font color="#0000ff"&gt;base&lt;/font&gt;(&lt;font color="#0000ff"&gt;true&lt;/font&gt;) { }&lt;/p&gt;
&lt;p align="justify"&gt;    &lt;font color="#0000ff"&gt;public override void&lt;/font&gt; ProcessRequest(&lt;font color="#0000ff"&gt;ref&lt;/font&gt; RequestContext requestContext)&lt;br /&gt;    {&lt;br /&gt;        Message msg = requestContext.RequestMessage;&lt;br /&gt;        &lt;font color="#006400"&gt;//faz algo customizado aqui&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;E, depois de criado, precisamos adicioná-lo na coleção de &lt;em&gt;interceptors&lt;/em&gt; do &lt;em&gt;WebServiceHost2&lt;/em&gt;, o que nos obriga a criar uma &lt;em&gt;service factory&lt;/em&gt; customizada (atente-se a sua &lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28243.aspx"&gt;configuração&lt;/a&gt;), conforme é mostrado abaixo:&lt;br /&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;internal class &lt;/font&gt;AppServiceHostFactory : ServiceHostFactory&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#0000ff"&gt;protected override&lt;/font&gt; ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)&lt;br /&gt;    {&lt;br /&gt;        WebServiceHost2 w = &lt;font color="#0000ff"&gt;new&lt;/font&gt; WebServiceHost2(serviceType, &lt;font color="#0000ff"&gt;true&lt;/font&gt;, baseAddresses);&lt;br /&gt;        w.Interceptors.Add(&lt;font color="#0000ff"&gt;new&lt;/font&gt; MeuInterceptador());&lt;br /&gt;        &lt;font color="#0000ff"&gt;return&lt;/font&gt; w;&lt;br /&gt;    }&lt;br /&gt;}&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Há algum tempo <a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=80">eu escrevi</a> sobre a possibilidade de criar serviços REST em WCF. Visando incrementar esses tipos de serviços, a Microsoft disponibilizou recentemente o <a href="http://msdn.microsoft.com/en-us/netframework/cc950529.aspx">Windows Communication Foundation REST Stater Kit</a>. Este <em>kit</em> fornece <em>templates</em> de projeto e diversas funcionalidades para serviços REST criados sob WCF. As funcionalidades fornecidas pelo <em>kit</em> facilita o uso do protocolo HTTP dentro do serviço e encapsula algumas funcionalidades expostas pelo ASP.NET. Entre as principais funcionalidades, temos <em>caching</em>, tratamento/manipulador de erros, página de suporte, estensibilidade, etc.<br /><br />Todas as funcionalidades estão contidas no <em>assembly Microsoft.ServiceModel.Web.dll</em>. O <em>caching</em> funciona de forma muito parecida com o <em>caching</em> do <em>ASP.NET/ASP.NET Web Services</em>, pois foi criado um atributo chamado <em>WebCacheAttribute</em> que, podemos aplicar em algum método de nosso serviço. Exemplo:<br /><br />[WebGet(UriTemplate = "")]<br />[WebCache(Duration = 30)]<br />[OperationContract]<br /><font color="#0000ff">string</font> RecuperarAlgumaInformacao();<br /><br />Outra possibilidade que temos, é a criação de uma página de suporte, que traz informações relacionadas aos métodos que o serviço disponibiliza. Para acessá-la, basta colocar <em>"/help"</em> no final da URL do serviço que, automaticamente, uma "página amigável" será exibida com essas informações. Vale lembrar que voce poderá customizar a descrição de um determinado método, através do atributo  <em>WebHelpAttribute</em>, como é mostrado abaixo:<br /><br />[WebGet(UriTemplate = "")]<br />[WebHelp(Comment = "Retorna uma informação qualquer.")]<br />[OperationContract]<br /><font color="#0000ff">string </font>RecuperarAlgumaInformacao();<br /><br />Alguns novos tipos também foram estendidos para suportar essas novas funcionalidades. Entre esses tipos, temos as classes <em>WebServiceHost2</em>, <em>WebServiceHost2Factory</em> e <em>WebHttpBehavior2</em>. Esses tipos são semelhantes aos existentes no .NET Framework 3.5, mais precisamente, dentro do <em>Assembly System.ServiceModel.Web.dll</em>. O <em>WebServiceHost2</em> possui uma propriedade chamada <em>Interceptors</em> que, como o próprio nome diz, permite-nos acoplar um "interceptador" e colocar ali algum código que desejamos executar durante a requisição.  Para criar um interceptador, tudo o que precisamos fazer é herdar da classe abstrata <em>RequestInterceptor</em> e sobrescrever o método <em>ProcessRequest</em>, como é mostrado abaixo:<br /><br /><font color="#0000ff">public class</font> MeuInterceptador : RequestInterceptor<br />{<br />    <font color="#0000ff">public</font> MeuInterceptador() : <font color="#0000ff">base</font>(<font color="#0000ff">true</font>) { }</p>
<p align="justify">    <font color="#0000ff">public override void</font> ProcessRequest(<font color="#0000ff">ref</font> RequestContext requestContext)<br />    {<br />        Message msg = requestContext.RequestMessage;<br />        <font color="#006400">//faz algo customizado aqui</font><br />    }<br />}<br /><br />E, depois de criado, precisamos adicioná-lo na coleção de <em>interceptors</em> do <em>WebServiceHost2</em>, o que nos obriga a criar uma <em>service factory</em> customizada (atente-se a sua <a href="http://weblogs.pontonetpt.com/israelaece/posts/28243.aspx">configuração</a>), conforme é mostrado abaixo:<br /><br /><font color="#0000ff">internal class </font>AppServiceHostFactory : ServiceHostFactory<br />{<br />    <font color="#0000ff">protected override</font> ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)<br />    {<br />        WebServiceHost2 w = <font color="#0000ff">new</font> WebServiceHost2(serviceType, <font color="#0000ff">true</font>, baseAddresses);<br />        w.Interceptors.Add(<font color="#0000ff">new</font> MeuInterceptador());<br />        <font color="#0000ff">return</font> w;<br />    }<br />}</p></body></item></channel></rss>