<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>Application Pool</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28444.aspx</link><pubDate>Thu, 27 Nov 2008 15:23:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28444.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28444.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28444.aspx#feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28444.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28444</trackback:ping><description>&lt;p align="justify"&gt;A partir do IIS 6.0, temos a capacidade de criar &lt;em&gt;Web Sites&lt;/em&gt;, onde cada um desses &lt;em&gt;Web Sites&lt;/em&gt; poderá conter 1 ou N aplicações e, para cada Web Site, podemos definir um &lt;em&gt;Application Pool&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Dentro do IIS, os &lt;em&gt;worker process&lt;/em&gt; (&lt;strong&gt;w3wp.exe&lt;/strong&gt;) são representados por um objeto denominado &lt;em&gt;Application Pool&lt;/em&gt;, ou seja, um repositório de aplicações que compartilham o mesmo &lt;em&gt;worker process&lt;/em&gt;. Sabendo que um &lt;em&gt;Application Pool&lt;/em&gt; poderá suportar muitas aplicações, já que ele é definido para cada &lt;em&gt;Web Site&lt;/em&gt;, devemos entender algumas características para tirar o melhor proveito deles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Somente uma versão do .NET Framework (CLR) poderá ser carregada para dentro dele. Aplicações que usam versões diferentes do .NET Framework, deverão ser separadas em diferentes &lt;em&gt;pools&lt;/em&gt;.&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
&lt;div align="justify"&gt;Podemos configurar cada &lt;em&gt;worker process&lt;/em&gt; para uma conta diferente que, por padrão, é sempre o usuário &lt;em&gt;Network Service&lt;/em&gt;. Se quiser alterar e usar uma outra conta (falaremos mais abaixo), voce deve colocar esse novo usuário dentro do grupo &lt;em&gt;IIS_WPG&lt;/em&gt; que, garantirá a ele os privilégios necessários para assumir este papel.&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
&lt;div align="justify"&gt;Sabemos que todas as requisições para uma aplicação ASP.NET utilizam &lt;em&gt;threads&lt;/em&gt; oriundas de um &lt;em&gt;thread pool&lt;/em&gt;. O &lt;em&gt;pool&lt;/em&gt; de &lt;em&gt;threads&lt;/em&gt; é único dentro do processo, sendo compartilhado por todas as aplicações que ali estão hospedadas. Isso poderá, em algum momento, causar problemas de escalabilidade. &lt;a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=49"&gt;Páginas assíncronas&lt;/a&gt; ajudam a melhorar isso.&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
&lt;div align="justify"&gt;Quando o &lt;em&gt;worker process&lt;/em&gt; for finalizado (independentemente do motivo), todas as aplicações, serão finalizadas, fazendo com que todos os dados de memória, como variáveis de aplicação, sessão e &lt;em&gt;caching&lt;/em&gt; sejam perdidos.&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
&lt;div align="justify"&gt;Todas as aplicações que estão dentro de um mesmo &lt;em&gt;worker process&lt;/em&gt; compartilham o mesmo contexto de segurança. Se cada aplicação tiver permissões diferentes dentro do sistema operacional, o ideal é isolar cada uma delas em um &lt;em&gt;pool&lt;/em&gt; diferente, configurando a conta daquele &lt;em&gt;pool&lt;/em&gt; com os respectivos privilégios.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">A partir do IIS 6.0, temos a capacidade de criar <em>Web Sites</em>, onde cada um desses <em>Web Sites</em> poderá conter 1 ou N aplicações e, para cada Web Site, podemos definir um <em>Application Pool</em>.<br /><br />Dentro do IIS, os <em>worker process</em> (<strong>w3wp.exe</strong>) são representados por um objeto denominado <em>Application Pool</em>, ou seja, um repositório de aplicações que compartilham o mesmo <em>worker process</em>. Sabendo que um <em>Application Pool</em> poderá suportar muitas aplicações, já que ele é definido para cada <em>Web Site</em>, devemos entender algumas características para tirar o melhor proveito deles:</p>
<ul>
<li>
<div align="justify">Somente uma versão do .NET Framework (CLR) poderá ser carregada para dentro dele. Aplicações que usam versões diferentes do .NET Framework, deverão ser separadas em diferentes <em>pools</em>.</div>
</li><li>
<div align="justify">Podemos configurar cada <em>worker process</em> para uma conta diferente que, por padrão, é sempre o usuário <em>Network Service</em>. Se quiser alterar e usar uma outra conta (falaremos mais abaixo), voce deve colocar esse novo usuário dentro do grupo <em>IIS_WPG</em> que, garantirá a ele os privilégios necessários para assumir este papel.</div>
</li><li>
<div align="justify">Sabemos que todas as requisições para uma aplicação ASP.NET utilizam <em>threads</em> oriundas de um <em>thread pool</em>. O <em>pool</em> de <em>threads</em> é único dentro do processo, sendo compartilhado por todas as aplicações que ali estão hospedadas. Isso poderá, em algum momento, causar problemas de escalabilidade. <a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=49">Páginas assíncronas</a> ajudam a melhorar isso.</div>
</li><li>
<div align="justify">Quando o <em>worker process</em> for finalizado (independentemente do motivo), todas as aplicações, serão finalizadas, fazendo com que todos os dados de memória, como variáveis de aplicação, sessão e <em>caching</em> sejam perdidos.</div>
</li><li>
<div align="justify">Todas as aplicações que estão dentro de um mesmo <em>worker process</em> compartilham o mesmo contexto de segurança. Se cada aplicação tiver permissões diferentes dentro do sistema operacional, o ideal é isolar cada uma delas em um <em>pool</em> diferente, configurando a conta daquele <em>pool</em> com os respectivos privilégios.</div></li></ul></body></item><item><dc:creator>Israel Aéce</dc:creator><title>Testando o envio de e-mails</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28443.aspx</link><pubDate>Thu, 27 Nov 2008 14:58:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28443.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28443.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28443.aspx#feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28443.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28443</trackback:ping><description>&lt;p align="justify"&gt;Eu ministro treinamentos oficiais Microsoft e, em um dos capítulos, falamos sobre o envio de e-mails, mais precisamente, sobre as classes &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.aspx"&gt;MailMessage&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx"&gt;SmtpClient&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Pois bem, para não ter que criar/utilizar uma conta de e-mail &lt;em&gt;dummy&lt;/em&gt; ou ter uma infraestrutura com um servidor de e-mail, podemos ao invés de efetivamente enviar o e-mail ao seu destinatário, salvá-lo localmente e assim visualizar como ficou o mesmo, sem a necessidade de abrí-lo em alguma ferramenta específica ou &lt;em&gt;webmail&lt;/em&gt;. Para essa mudança, voce deve configurar o modo de entrega como sendo &lt;em&gt;specifiedPickupDirectory&lt;/em&gt; ao invés de &lt;em&gt;network&lt;/em&gt;. O exemplo abaixo exibe como efetuar essa mudança através do arquivo de configuração da aplicação:&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;  &amp;lt;system.net&amp;gt;&lt;br /&gt;    &amp;lt;mailSettings&amp;gt;&lt;br /&gt;      &amp;lt;smtp deliveryMethod="&lt;strong&gt;SpecifiedPickupDirectory&lt;/strong&gt;" from="&lt;a href="mailto:automatico@site.com.br"&gt;automatico@site.com.br&lt;/a&gt;"&amp;gt;&lt;br /&gt;        &lt;strong&gt;&amp;lt;specifiedPickupDirectory pickupDirectoryLocation="C:\Temp\"/&amp;gt;&lt;/strong&gt;&lt;br /&gt;      &amp;lt;/smtp&amp;gt;&lt;br /&gt;    &amp;lt;/mailSettings&amp;gt;&lt;br /&gt;  &amp;lt;/system.net&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;Já no ambiente de produção, voce deverá trocar o valor do atributo &lt;em&gt;deliveryMethod&lt;/em&gt; para &lt;em&gt;Network&lt;/em&gt; e, ao invés de utilizar o sub-elemento &lt;em&gt;specifiedPickupDirectory&lt;/em&gt;, configurar o sub-elemento &lt;em&gt;network&lt;/em&gt;, como mostrado abaixo:&lt;br /&gt;&lt;br /&gt;&amp;lt;network host="mail.site.com.br" port="25" /&amp;gt;&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">Eu ministro treinamentos oficiais Microsoft e, em um dos capítulos, falamos sobre o envio de e-mails, mais precisamente, sobre as classes <a href="http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.aspx">MailMessage</a> e <a href="http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx">SmtpClient</a>.<br /><br />Pois bem, para não ter que criar/utilizar uma conta de e-mail <em>dummy</em> ou ter uma infraestrutura com um servidor de e-mail, podemos ao invés de efetivamente enviar o e-mail ao seu destinatário, salvá-lo localmente e assim visualizar como ficou o mesmo, sem a necessidade de abrí-lo em alguma ferramenta específica ou <em>webmail</em>. Para essa mudança, voce deve configurar o modo de entrega como sendo <em>specifiedPickupDirectory</em> ao invés de <em>network</em>. O exemplo abaixo exibe como efetuar essa mudança através do arquivo de configuração da aplicação:<br /><br />&lt;?xml version="1.0" encoding="utf-8" ?&gt;<br />&lt;configuration&gt;<br />  &lt;system.net&gt;<br />    &lt;mailSettings&gt;<br />      &lt;smtp deliveryMethod="<strong>SpecifiedPickupDirectory</strong>" from="<a href="mailto:automatico@site.com.br">automatico@site.com.br</a>"&gt;<br />        <strong>&lt;specifiedPickupDirectory pickupDirectoryLocation="C:\Temp\"/&gt;</strong><br />      &lt;/smtp&gt;<br />    &lt;/mailSettings&gt;<br />  &lt;/system.net&gt;<br />&lt;/configuration&gt;<br /><br />Já no ambiente de produção, voce deverá trocar o valor do atributo <em>deliveryMethod</em> para <em>Network</em> e, ao invés de utilizar o sub-elemento <em>specifiedPickupDirectory</em>, configurar o sub-elemento <em>network</em>, como mostrado abaixo:<br /><br />&lt;network host="mail.site.com.br" port="25" /&gt;</p></body></item><item><dc:creator>Israel Aéce</dc:creator><title>Capturando mensagens genéricas</title><link>http://weblogs.pontonetpt.com/israelaece/posts/28436.aspx</link><pubDate>Mon, 24 Nov 2008 18:05:00 GMT</pubDate><guid>http://weblogs.pontonetpt.com/israelaece/posts/28436.aspx</guid><wfw:comment>http://weblogs.pontonetpt.com/israelaece/comments/28436.aspx</wfw:comment><comments>http://weblogs.pontonetpt.com/israelaece/posts/28436.aspx#feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://weblogs.pontonetpt.com/israelaece/comments/commentRss/28436.aspx</wfw:commentRss><trackback:ping>http://weblogs.pontonetpt.com/israelaece/trackback.aspx?ID=28436</trackback:ping><description>&lt;p align="justify"&gt;A primeira etapa para a construção de um serviço WCF é a definição do contrato do serviço que, durante a escrita do código, é determinado pela criação de uma &lt;em&gt;interface&lt;/em&gt; tradicional. Os métodos que são criados ali são, em tempo de execução, expostos através do WSDL para que os clientes possam consumí-los.&lt;br /&gt;&lt;br /&gt;Se criarmos uma referencia para o serviço a partir da IDE do Visual Studio ou do utilitário &lt;a href="http://msdn.microsoft.com/en-us/library/aa347733.aspx"&gt;svcutil.exe&lt;/a&gt;, automaticamente um &lt;em&gt;proxy&lt;/em&gt; será criado e podemos invocar os métodos a partir dele, com a impressão de que se estivéssemos chamando um método localmente mas que, durante a execução, uma mensagem é criada e enviada ao respectivo método remoto.&lt;br /&gt;&lt;br /&gt;Mas e quando não temos o essa flexibilidade de criar o &lt;em&gt;proxy &lt;/em&gt;(&lt;a href="http://weblogs.pontonetpt.com/israelaece/posts/28269.aspx"&gt;exemplo&lt;/a&gt;)? Como fazemos para invocar o um método disponibilizado pelo serviço? Felizmente podemos recorrer ao &lt;a href="http://www.fiddlertool.com/"&gt;Fiddler&lt;/a&gt; ou até mesmo as classes &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest(VS.71).aspx"&gt;HttpWebRequest&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx"&gt;HttpWebResponse&lt;/a&gt; para efetuar a requisição, montando o cabeçalho e o corpo (SOAP) para invocar um determinado método do serviço. Esse procedimento permite a quem estiver consumindo, colocar o nome errado do método a ser invocado e, consequentemente, o seu serviço irá rejeitar a requisição.&lt;br /&gt;&lt;br /&gt;Felizmente o WCF nos permite lidar com mensagens genéricas, ou seja, podemos criar um método que capturará toda e qualquer mensagem que não for encontrada no contrato do serviço. Para isso, basta definirmos a propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.action.aspx"&gt;Action&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.replyaction.aspx"&gt;ReplyAction&lt;/a&gt; do atributo &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.aspx"&gt;OperationContractAttribute&lt;/a&gt; para "*". Isso fará com que todas as mensagens não encontradas na definição do contrato, sejam encaminhadas para este método, em que podemos efetuar &lt;em&gt;logging&lt;/em&gt;, notificações, etc. Abaixo um exemplo ilustra como proceder:&lt;br /&gt;&lt;br /&gt;[OperationContract(Action="*", ReplyAction="*")]&lt;br /&gt;Message ProcessRequest(Message msg);&lt;br /&gt;&lt;br /&gt;É importante notar que o método recebe e também retorna uma instancia da classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.message.aspx"&gt;Message&lt;/a&gt;. Esta classe representa a mensagem dentro do WCF. Além disso, também podemos usar esta mesma técnica quando utilizamos o &lt;a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=80"&gt;modelo REST&lt;/a&gt;, só que agora, devemos definir a propriedade &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.uritemplate.aspx"&gt;UriTemplate&lt;/a&gt; do o atributo &lt;a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.aspx"&gt;WebGetAttribute&lt;/a&gt; para "*" e, assim como o &lt;em&gt;OperationContractAttribute&lt;/em&gt;, consiga capturar todas mensagens não mapeadas/existentes.&lt;br /&gt;&lt;br /&gt;[OperationContract]&lt;br /&gt;[WebGet(UriTemplate="*")]&lt;br /&gt;Message ProcessRequest(Message msg);&lt;/p&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p align="justify">A primeira etapa para a construção de um serviço WCF é a definição do contrato do serviço que, durante a escrita do código, é determinado pela criação de uma <em>interface</em> tradicional. Os métodos que são criados ali são, em tempo de execução, expostos através do WSDL para que os clientes possam consumí-los.<br /><br />Se criarmos uma referencia para o serviço a partir da IDE do Visual Studio ou do utilitário <a href="http://msdn.microsoft.com/en-us/library/aa347733.aspx">svcutil.exe</a>, automaticamente um <em>proxy</em> será criado e podemos invocar os métodos a partir dele, com a impressão de que se estivéssemos chamando um método localmente mas que, durante a execução, uma mensagem é criada e enviada ao respectivo método remoto.<br /><br />Mas e quando não temos o essa flexibilidade de criar o <em>proxy </em>(<a href="http://weblogs.pontonetpt.com/israelaece/posts/28269.aspx">exemplo</a>)? Como fazemos para invocar o um método disponibilizado pelo serviço? Felizmente podemos recorrer ao <a href="http://www.fiddlertool.com/">Fiddler</a> ou até mesmo as classes <a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest(VS.71).aspx">HttpWebRequest</a> e <a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx">HttpWebResponse</a> para efetuar a requisição, montando o cabeçalho e o corpo (SOAP) para invocar um determinado método do serviço. Esse procedimento permite a quem estiver consumindo, colocar o nome errado do método a ser invocado e, consequentemente, o seu serviço irá rejeitar a requisição.<br /><br />Felizmente o WCF nos permite lidar com mensagens genéricas, ou seja, podemos criar um método que capturará toda e qualquer mensagem que não for encontrada no contrato do serviço. Para isso, basta definirmos a propriedade <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.action.aspx">Action</a> e <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.replyaction.aspx">ReplyAction</a> do atributo <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.aspx">OperationContractAttribute</a> para "*". Isso fará com que todas as mensagens não encontradas na definição do contrato, sejam encaminhadas para este método, em que podemos efetuar <em>logging</em>, notificações, etc. Abaixo um exemplo ilustra como proceder:<br /><br />[OperationContract(Action="*", ReplyAction="*")]<br />Message ProcessRequest(Message msg);<br /><br />É importante notar que o método recebe e também retorna uma instancia da classe <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.message.aspx">Message</a>. Esta classe representa a mensagem dentro do WCF. Além disso, também podemos usar esta mesma técnica quando utilizamos o <a href="http://www.projetando.net/Sections/ViewArticle.aspx?ArticleID=80">modelo REST</a>, só que agora, devemos definir a propriedade <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.uritemplate.aspx">UriTemplate</a> do o atributo <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.aspx">WebGetAttribute</a> para "*" e, assim como o <em>OperationContractAttribute</em>, consiga capturar todas mensagens não mapeadas/existentes.<br /><br />[OperationContract]<br />[WebGet(UriTemplate="*")]<br />Message ProcessRequest(Message msg);</p></body></item><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>2</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>1</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></channel></rss>