<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>NeoMatrix Tech</title>
	
	<link>http://leonelfraga.com/neomatrixtech</link>
	<description>C#, ASP.NET, Programação em Geral, Análises, Hardware, Software, Opinião, Gadgets e muito mais.</description>
	<lastBuildDate>Tue, 01 May 2012 14:09:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/neomatrixtech" /><feedburner:info uri="neomatrixtech" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>neomatrixtech</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Capturando a imagem de uma WebCam em páginas ASP.NET – Salvando o cadastro em Banco de Dados</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/4OHBVaiR8JU/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net-salvando-o-cadastro-em-banco-de-dados/#comments</comments>
		<pubDate>Tue, 01 May 2012 01:11:27 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[POG]]></category>
		<category><![CDATA[ASP.NET com Plugins no Cliente]]></category>
		<category><![CDATA[Banco de Dados]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[WebCam]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=822</guid>
		<description><![CDATA[Olá meu(minha) querido(a).
Vocês gostaram do artigo que trata de capturar uma imagem através da WebCam em uma página ASP.NET, não é? E se eu me lembro bem, fiquei “devendo” um artigo que ensina como gravar esta imagem em uma base de dados, não é? Pois bem, aí vamos nós!!!
Mas antes, caso você ainda  [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2012/05/image.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top: 0px; border-right: 0px; padding-top: 0px" title="WebCam" border="0" alt="WebCam" align="left" src="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2012/05/image_thumb.png" width="239" height="211" /></a>Olá meu(minha) querido(a).</p>
<p>Vocês gostaram do artigo que trata de <strong><font color="#ff0000">capturar uma imagem através da WebCam</font></strong> em uma página ASP.NET, não é? E se eu me lembro bem, fiquei “devendo” um artigo que ensina como gravar esta imagem em uma base de dados, não é? Pois bem, aí vamos nós!!!</p>
<p>Mas antes, caso você ainda não teve a oportunidade de ver o artigo anterior, sugiro que o leia antes de adentrar à fundo neste: <a href="http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net/" target="_blank">Capturando a imagem de uma WebCam em páginas ASP.NET</a>.</p>
<p>No artigo anterior, ao clicarmos no botão que faz a captura da imagem, o applet Flash que interage com a WebCam “posta” um <em>stream</em> com a foto em uma página chamada “<strong>Upload.aspx</strong>”, onde processamos este <em>stream</em> e gravamos em um <strong>arquivo físico</strong> no servidor. O que iremos fazer agora é pegar esta mesma <em>InputStream</em> da página Upload.aspx e gravá-la em um campo do tipo <em>Image</em> (ou outro que armazene dados binários) no Banco de Dados.</p>
<p>Faremos uma pequena modificação na página Upload.aspx à saber:</p>
<pre class="brush:csharp">protected void Page_Load(object sender, EventArgs e)
{
	if (!IsPostBack)
	{
		try
		{
			//Não usaremos mais a saída em uma URL, e sim guardaremos o stream de entrada em variável de sessão
			byte[] buffer = new byte[Request.InputStream.Length];
			Request.InputStream.Read(buffer, 0, (int)Request.InputStream.Length);
			SessionFacade.FotoArmazenada = buffer;
		}
		catch
		{
			Response.Clear();
			Response.Write(&quot;ERROR: Erro ao salvar imagem\n&quot;);
		}
		Response.End();
	}
}</pre>
<p>Em vez de gravar em um arquivo físico no servidor Web, pegaremos a <em>InputStream</em> e salvaremos em uma <strong>variável de sessão</strong>. Esta variável está encapsulada na propriedade <strong><font color="#ff0000">SessionFacade.FotoArmazenada</font></strong>. Abaixo temos o código da classe <em>SessionFacade</em> (um <em>Facade</em> que encapsula variáveis de sessão) e da propriedade <em>FotoArmazenada</em>, do tipo <em>byte[]</em>.</p>
<pre class="brush:csharp">public class SessionFacade
{
	public static byte[] FotoArmazenada
	{
		get
		{
			if (HttpContext.Current.Session[&quot;img&quot;] == null)
			{
				return null;
			}
			else
			{
				return (byte[])HttpContext.Current.Session[&quot;img&quot;];
			}
		}
		set
		{
			if (HttpContext.Current.Session[&quot;img&quot;] == null)
			{
				HttpContext.Current.Session.Add(&quot;img&quot;, value);
			}
			else
			{
				HttpContext.Current.Session[&quot;img&quot;] = value;
			}
		}
	}
}</pre>
<p>Vamos agora às alterações em Default.aspx:</p>
<pre class="brush:xhtml">&lt;%@ Page Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;Default.aspx.cs&quot; Inherits=&quot;CapturaWebcamASPNET.Default&quot; %&gt;

&lt;%@ Register Assembly=&quot;AjaxControlToolkit&quot; Namespace=&quot;AjaxControlToolkit&quot; TagPrefix=&quot;asp&quot; %&gt;

&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;Exemplo de captura de imagem da WebCam usando ASP.NET e gravando em BD&lt;/title&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;camutils/webcam.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
	    &lt;asp:ScriptManager runat=&quot;server&quot; ID=&quot;sc1&quot;&gt;&lt;/asp:ScriptManager&gt;

        &lt;!-- Configura algumas opções da webcam --&gt;
	    &lt;script type=&quot;text/javascript&quot; language=&quot;JavaScript&quot;&gt;
	        webcam.set_api_url('Upload.aspx');//Página de destino do arquivo capturado
	        webcam.set_quality(90); // Qualidade do JPG (1 - 100)
	        webcam.set_shutter_sound(true); // Toca o som de câmera (o arquivo shutter.mp3, que vem com os &quot;utilitários&quot; da câmera, deve estar no diretório raíz do site)
	    &lt;/script&gt;

        &lt;!--Corpo da página--&gt;
        &lt;asp:UpdatePanel runat=&quot;server&quot; ID=&quot;upd1&quot;&gt;
            &lt;ContentTemplate&gt;
                &lt;asp:HiddenField runat=&quot;server&quot; ID=&quot;hdfContador&quot; Value=&quot;0&quot; /&gt; &lt;!--Este &quot;contador&quot; serve para gerar uma URL da foto diferente a cada captura, para atualizar o controle que a exibe.--&gt;
                &lt;asp:MultiView runat=&quot;server&quot; ID=&quot;mv1&quot; ActiveViewIndex=&quot;0&quot;&gt;
                    &lt;asp:View runat=&quot;server&quot; ID=&quot;vwPesquisa&quot;&gt;
                        &lt;table style=&quot;width:100%;&quot;&gt;
                            &lt;tr&gt;
                                &lt;td style=&quot;text-align:center;&quot;&gt;
                                    &lt;span&gt;Pesquisa de Pessoas&lt;/span&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                            &lt;tr&gt;
                                &lt;td&gt;
                                    &lt;span&gt;Nome:&lt;/span&gt;&lt;br /&gt;
                                    &lt;asp:TextBox runat=&quot;server&quot; ID=&quot;tbxPesqNome&quot; Width=&quot;200px&quot;&gt;&lt;/asp:TextBox&gt;
                                    &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnPesquisa&quot; Text=&quot;Pesquisar&quot; OnClick=&quot;btnPesquisa_Click&quot; /&gt;
                                    &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnNovo&quot; Text=&quot;Novo&quot; OnClick=&quot;btnNovo_Click&quot; /&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                            &lt;tr&gt;
                                &lt;td&gt;
                                    &lt;asp:GridView runat=&quot;server&quot; ID=&quot;gvPesquisa&quot; AutoGenerateColumns=&quot;false&quot; DataKeyNames=&quot;Id&quot; Width=&quot;100%&quot;&gt;
                                        &lt;Columns&gt;
                                            &lt;asp:TemplateField HeaderText=&quot;Nome&quot;&gt;
                                                &lt;ItemTemplate&gt;
                                                    &lt;asp:LinkButton runat=&quot;server&quot; ID=&quot;lnkEdit&quot; CommandArgument='&lt;%#Bind(&quot;Id&quot;)%&gt;' Text='&lt;%#Bind(&quot;Nome&quot;)%&gt;' OnClick=&quot;lnkEdit_Click&quot;&gt;&lt;/asp:LinkButton&gt;
                                                &lt;/ItemTemplate&gt;
                                            &lt;/asp:TemplateField&gt;
                                        &lt;/Columns&gt;
                                    &lt;/asp:GridView&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                        &lt;/table&gt;
                    &lt;/asp:View&gt;
                    &lt;asp:View runat=&quot;server&quot; ID=&quot;vwCadastro&quot;&gt;
                        &lt;table style=&quot;width:100%;border:1px solid black;&quot;&gt;
                            &lt;tr&gt;
                                &lt;td colspan=&quot;3&quot; style=&quot;text-align:center;&quot;&gt;
                                    &lt;span&gt;Cadastro de Pessoas com Foto&lt;/span&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                            &lt;tr&gt;
                                &lt;td&gt;
                                    &lt;span&gt;Código:&lt;/span&gt;
                                &lt;/td&gt;
                                &lt;td&gt;
                                    &lt;asp:TextBox runat=&quot;server&quot; ID=&quot;tbxCodigo&quot; Width=&quot;150px&quot; ReadOnly=&quot;true&quot;&gt;&lt;/asp:TextBox&gt;
                                &lt;/td&gt;
                                &lt;td rowspan=&quot;2&quot; style=&quot;text-align:center;&quot;&gt;
	                                &lt;!-- Desenha o HTML do Flash que faz a interface com a Webcam na resolução 320x240 --&gt;
                                    &lt;div id=&quot;upload_results&quot; runat=&quot;server&quot; style=&quot;width:320px;height:240px;background-color:Blue;&quot;&gt;
                                        &lt;asp:Image runat=&quot;server&quot; ID=&quot;imgFoto&quot; ImageUrl=&quot;~/SessionImg.aspx&quot; AlternateText=&quot;Captura de Foto&quot; /&gt;
                                    &lt;/div&gt;
                                    &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnAbrePopCaptura&quot; Text=&quot;Capturar Imagem&quot; OnClick=&quot;btnAbrePopCaptura_Click&quot; /&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                            &lt;tr&gt;
                                &lt;td&gt;
                                    &lt;span&gt;Nome:&lt;/span&gt;
                                &lt;/td&gt;
                                &lt;td colspan=&quot;2&quot;&gt;
                                    &lt;asp:TextBox runat=&quot;server&quot; ID=&quot;tbxNome&quot; Width=&quot;200px&quot;&gt;&lt;/asp:TextBox&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                            &lt;tr&gt;
                                &lt;td colspan=&quot;3&quot; style=&quot;text-align:center;&quot;&gt;
                                    &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnCancelar&quot; Text=&quot;Cancelar&quot; OnClick=&quot;btnCancelar_Click&quot; /&gt;
                                    &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnSalvar&quot; Text=&quot;Salvar&quot; OnClick=&quot;btnSalvar_Click&quot; /&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                        &lt;/table&gt;
                    &lt;/asp:View&gt;
                &lt;/asp:MultiView&gt;
                &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnRefreshFoto&quot; Style=&quot;display:none&quot; OnClick=&quot;btnRefreshFoto_Click&quot; /&gt;
            &lt;/ContentTemplate&gt;
        &lt;/asp:UpdatePanel&gt;

        &lt;asp:ModalPopupExtender ID=&quot;popWebCam&quot; runat=&quot;server&quot; PopupControlID=&quot;pnlPopWebCam&quot; CancelControlID=&quot;btnFechaPopWebCam&quot; TargetControlID=&quot;btnAcionaPopWebCam&quot; BehaviorID=&quot;bpopWebCam&quot;&gt;&lt;/asp:ModalPopupExtender&gt;
        &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnAcionaPopWebCam&quot; Style=&quot;display:none;&quot; /&gt;
        &lt;asp:Panel runat=&quot;server&quot; ID=&quot;pnlPopWebCam&quot; Width=&quot;320px&quot; Height=&quot;280px&quot; BackColor=&quot;Black&quot;&gt;
            &lt;table style=&quot;width:100%;&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;
                &lt;tr&gt;
                    &lt;td style=&quot;width:320px;height:240px;text-align:center;&quot; valign=&quot;top&quot;&gt;
                        &lt;script type=&quot;text/javascript&quot; language=&quot;JavaScript&quot;&gt;
                            document.write(webcam.get_html(320, 240));
	                    &lt;/script&gt;
                        &lt;input type=&quot;button&quot; value=&quot;Configurar...&quot; onclick=&quot;webcam.configure();&quot; /&gt;
                        &lt;input type=&quot;button&quot; value=&quot;Capturar&quot; onclick=&quot;take_snapshot();&quot; /&gt;
                        &lt;input type=&quot;button&quot; value=&quot;Reset&quot; onclick=&quot;webcam.reset();&quot; /&gt;
                        &lt;asp:Button runat=&quot;server&quot; ID=&quot;btnFechaPopWebCam&quot; Text=&quot;Fechar&quot; /&gt;
                    &lt;/td&gt;
                &lt;/tr&gt;
            &lt;/table&gt;
        &lt;/asp:Panel&gt;

        &lt;!--Funções para controle da WebCam--&gt;
        &lt;script type=&quot;text/javascript&quot;&gt;
            webcam.set_hook('onComplete', 'my_completion_handler');

            function take_snapshot() {
                // Captura a imagem e submete ao servidor
                document.getElementById('upload_results').innerHTML = '&lt;h1&gt;Realizando Upload da Foto...&lt;/h1&gt;';
                webcam.snap();
                document.getElementById('&lt;%=btnFechaPopWebCam.ClientID%&gt;').click();
            }

            function my_completion_handler(msg) {
                document.getElementById('&lt;%=btnRefreshFoto.ClientID%&gt;').click(); //Executa a rotina que atualiza o controle que exibe a foto com a foto que está na sessão.
            }
        &lt;/script&gt;

    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Vamos fazer a nossa página de cadastro em um “<strong><font color="#ff0000">Single Page Module</font></strong>”, ou seja, a mesma página serve para pesquisa, inclusão e alteração. Temos um <em>MultiView</em> com duas visões: uma para pesquisa e outra para o cadastro em si.</p>
<p>A View de Pesquisa (<em>vwPesquisa</em>) não tem segredo: Possui um campo para pesquisar por nome, os botões Pesquisar e Novo e um <em>gridview</em> para mostrar os resultados da pesquisa.</p>
<p>Na View de Cadastro (<em>vwCadastro</em>) temos os campos necessários de código, nome, os botões para salvar e cancelar e um componente do tipo Image. Neste componente é que vamos carregar a foto que estará armazenada em nossa variável de sessão (<em>SessionFacade.FotoArmazenada</em>). Também temos, abaixo do Image, um botão que faz a captura da foto.</p>
<p>Notou que temos em nossa solution um arquivo chamado <strong>SessionImg.aspx</strong> e que está na propriedade <em>ImageUrl</em> do controle <em>imgFoto</em>? Pois é. Colocaremos no <em>Stream</em> de saída de SessionImg.aspx a imagem de nossa variável <em>SessionFacade.FotoArmazenada</em>. Portanto, esta página será interpretada pelo navegador como um arquivo de imagem. Veja como isso é feito:</p>
<pre class="brush:csharp">protected void Page_Load(object sender, EventArgs e)
{
	Response.Clear();
	if (SessionFacade.FotoArmazenada != null)
	{
		Response.BinaryWrite(SessionFacade.FotoArmazenada);
	}
	else
	{
		Response.Write(&quot;Foto não disponível&quot;);
	}
	Response.End();
}</pre>
<p>Também moveremos a parte que contém o applet Flash para a captura de foto para um <em>Panel</em>, e este com um extender <em>ModalPopupExtender</em>. Assim, ao clicarmos no botão “<em>&#8216;Capturar Imagem</em>” da tela de cadastro abriremos este <em>Panel</em> em uma janela modal e a imagem estará pronta para ser capturada.</p>
<p>Clicando no botão “Capturar” do modal da WebCam, dispararemos a função <em>JavaScript</em> “<em>take_snapshot()</em>”, do jeito que fazíamos antes, mas esta função tem uma pequena diferença: ela dispara uma rotina <em>server-side</em> invocada pelo botão “<em>btnFechaPopWebCam</em>”, que nada mais faz do que invocar o método <em>Hide()</em> do <em>ModalPopupExtender</em> (isto poderia ser feito client-side, mas não lembro como faz <img src='http://leonelfraga.com/neomatrixtech/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  ).</p>
<p>O <em>handler</em> <em>JavaScript</em> que ouve o evento que é disparado quando o processamento estiver concluído também foi alterado. No lugar de exibir a URL gravada fisicamente no servidor, ele vai disparar uma rotina <em>server-side</em> que está no botão “<em><strong>btnRefreshFoto</strong></em>”. Antes de entrar no que ela faz, notaram que no HTML, logo após a declaração do <em>ContentTemplate</em> do <em>UpdatePanel</em> temos um <em><strong>HiddenField</strong></em> chamado “<strong><em><font color="#ff0000">hdfContador</font></em></strong>”? Ele vai servir para uma POG que vou explicar abaixo:</p>
<pre class="brush:csharp">protected void btnRefreshFoto_Click(object sender, EventArgs e)
{
	hdfContador.Value = (Int32.Parse(hdfContador.Value) + 1).ToString();
	imgFoto.ImageUrl = &quot;SessionImg.aspx?c=&quot; + hdfContador.Value;
	imgFoto.AlternateText = &quot;Foto&quot;;
}</pre>
<p>Para exibir corretamente as alterações do componente Image, devemos <strong>modificar a sua propriedade <em><font color="#ff0000">ImageURL</font></em></strong>. Prestaram atenção? eu disse MODIFICAR a propriedade. Como temos uma única página que exibe o conteúdo da variável de sessão (<em>SessionImg.aspx</em>), para que a URL possa ser modificada vamos alterar apenas a <em>QueryString</em> da mesma. A cada vez que precisamos mudar a foto, incrementamos esse contador e concatenamo-os com a URL SessionImg.aspx. Com a <em>QueryString</em> modificada, o navegador entende que é um outro link e redesenha a área do Image.</p>
<p>Acima somente trabalhamos na interface Web do projeto. Agora vamos tratar de persistir esses dados em um Banco de Dados.</p>
<p>A persistência é a parte mais simples. Temos uma tabela em nosso banco chamada Cadastro, com as definições abaixo:</p>
<pre class="brush:sql">create table Cadastro (
	Id int not null identity,
	Nome varchar(100),
	Foto image
);
alter table Cadastro add constraint PK_CADASTRO primary key (Id);</pre>
<p>Para persistir esta tabela, criamos a classe <strong>PessoaVO</strong> para representar os objetos e <strong>PessoaDAL</strong> para executar os comandos de gravação e pesquisa. <em>PessoaDAL</em> executa os métodos comumentes usados para persistir dados. Suponho que você já saiba utilizar o ADO.NET e métodos relacionados (o código completo está no download do exemplo, não se preocupe <img src='http://leonelfraga.com/neomatrixtech/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).</p>
<p>Vamos ver o código de gravação de dados de PessoaDAL:</p>
<pre class="brush:csharp">        public static string Gravar(PessoaVO arg)
        {
            try
            {
                using (SqlConnection cnx = new SqlConnection(ConfigurationManager.ConnectionStrings[&quot;cnx&quot;].ToString()))
                {
                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cnx.Open();
                        cmd.Connection = cnx;

                        StringBuilder sql = new StringBuilder();

                        if (arg.Id == 0) //Insert
                        {
                            sql.Append(&quot;insert into Cadastro (Nome,Foto) values (@Nome,@Foto)&quot;);
                            cmd.Parameters.Add(&quot;@Nome&quot;, SqlDbType.VarChar, 100).Value = arg.Nome;
                            cmd.Parameters.Add(&quot;@Foto&quot;, SqlDbType.Image).Value = (arg.Foto == null) ? (object)DBNull.Value : arg.Foto;
                        }
                        else //Update
                        {
                            sql.Append(&quot;update Cadastro set Nome = @Nome, Foto = @Foto where Id = @Id&quot;);
                            cmd.Parameters.Add(&quot;@Nome&quot;, SqlDbType.VarChar, 100).Value = arg.Nome;
                            cmd.Parameters.Add(&quot;@Foto&quot;, SqlDbType.Image).Value = (arg.Foto == null) ? (object)DBNull.Value : arg.Foto;
                            cmd.Parameters.Add(&quot;@Id&quot;, SqlDbType.Int).Value = arg.Id;
                        }
                        cmd.CommandText = sql.ToString();
                        cmd.ExecuteNonQuery();
                    }
                }

                return String.Empty;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }</pre>
<p>Para transferir os dados da página para o objeto <em>PessoaVO</em>, temos o seguinte código do botão Salvar:</p>
<pre class="brush:csharp">protected void btnSalvar_Click(object sender, EventArgs e)
{
	PessoaVO p = new PessoaVO();
	p.Id = tbxCodigo.Text.Equals(&quot;&quot;) ? 0 : Int32.Parse(tbxCodigo.Text);
	p.Nome = tbxNome.Text;
	p.Foto = SessionFacade.FotoArmazenada;

	string ret = PessoaDAL.Gravar(p);
	if (ret == &quot;&quot;)
	{
		ScriptManager.RegisterStartupScript(this, this.GetType(), &quot;alert&quot;, &quot;alert('Pessoa gravada com sucesso');&quot;, true);
		mv1.SetActiveView(vwPesquisa);
	}
	else
	{
		ScriptManager.RegisterStartupScript(this, this.GetType(), &quot;alert&quot;, &quot;alert('Erro ao gravar Pessoa');&quot;, true);
	}
}</pre>
<p>Atribuímos os campos normalmente, sendo que no campo “Foto” colocamos os dados gravados em nossa variável de sessão <em>SessionFacade.FotoArmazenada</em>.</p>
<p>Para exibir um registro, recuperamos ele do BD e fazemos a atribuição das propriedades na caixa de texto. Quanto à foto, atribuimos ela na variável de sessão e fazemos aquela “gambiarra” para atualizar o componente Image.</p>
<p>Bem, é isso aí. Sei que o design do exemplo está tosco, mas o que interessa é a gravação do registro em BD, e você viu que é bem simples. Um abraço e até a próxima!</p>
<p><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; border-top: 0px; border-right: 0px; padding-top: 0px" border="0" src="http://lh6.ggpht.com/_Kzg5fUTKXVY/S1sv5NsGvXI/AAAAAAAAIPo/Bo1zCLYK2qI/download15B15D5B55D5B15D_thumb5B15D5%5B1%5D.png?imgmax=800" />Download: <a title="Download do projeto exemplo" href="http://leonelfraga.com/downloads/CapturaWebcamASPNET-ExemploBD.zip" target="_blank">Projeto ASP.NET com captura de imagem via webcam e gravação em Banco de Dados (básico)</a> (.NET Framework 4.0 em Visual Studio 2010).</p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net/" rel="bookmark" class="crp_title">Capturando a imagem de uma WebCam em p&aacute;ginas ASP.NET</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/upload-em-asp-net-com-jqmodal-e-efeitos-ajax/" rel="bookmark" class="crp_title">Upload em ASP.NET com jqModal e efeitos AJAX</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/exemplo-de-uso-manipulando-planilhas-excel-com-ado-net/" rel="bookmark" class="crp_title">Exemplo de uso – Manipulando Planilhas Excel com ADO.NET</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/controle-de-usuarios-para-sistemas-asp-net-parte-4-interface-de-cadastro-de-perfisusuarios/" rel="bookmark" class="crp_title">Controle de Usuários para Sistemas ASP.NET &#8211; Parte 4 &#8211; Interface de cadastro de Perfis/Usuários</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/redirecionando-do-blogger-para-o-wordpress-com-permalinks-padro/" rel="bookmark" class="crp_title">Redirecionando do Blogger para o WordPress com permalinks padr&atilde;o</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net-salvando-o-cadastro-em-banco-de-dados/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net-salvando-o-cadastro-em-banco-de-dados/</feedburner:origLink></item>
		<item>
		<title>Emulator DVS e o futuro das interfaces para DJs</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/fAJ6DfvvqI4/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/emulator-dvs-e-o-futuro-das-interfaces-para-djs/#comments</comments>
		<pubDate>Wed, 11 Apr 2012 01:07:58 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[DJing]]></category>
		<category><![CDATA[Emulator DVS]]></category>
		<category><![CDATA[Ficção]]></category>
		<category><![CDATA[Interfaces Gráficas]]></category>
		<category><![CDATA[Touchless]]></category>
		<category><![CDATA[Touchscreen]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=795</guid>
		<description><![CDATA[Desde que me interessei pela arte da mixagem também me interessei pelo setup DJ. Sempre quando vou a uma balada me pergunto “qual é o equipamento que o DJ está utilizando? Está usando CDJ, Notebook, Timecode? Serato, Traktor ou até mesmo o Virtual DJ?”.
É fato que o público normal de balada nem se  [...]]]></description>
			<content:encoded><![CDATA[<p>Desde que me interessei pela arte da mixagem também me interessei pelo <strong><font color="#ff0000">setup DJ</font></strong>. Sempre quando vou a uma balada me pergunto “qual é o equipamento que o DJ está utilizando? Está usando CDJ, Notebook, <em>Timecode</em>? <em>Serato</em>, <em>Traktor</em> ou até mesmo o <em>Virtual DJ</em>?”.</p>
<p>É fato que o público normal de balada nem se interessa por essas coisas. O que a turma quer é saber de <em>pegação</em>, bebida, jogar papo fora com os amigos, dançar ao som da pista. Claro que se o DJ <em>sambar</em>, o público nota. Mas saber detalhes sobre a performance, nem.</p>
<p>Voltando ao meu interesse por equipamentos&#8230;</p>
<p>A moda de hoje em dia são as <strong><font color="#ff0000">controladoras</font></strong> que utilizam o protocolo <strong><font color="#ff0000">MIDI</font></strong> para enviar comandos ao software de mixagem. Elas existem nos mais variados modelos, mas a maioria tem alguns controles em comum: Mixer, Efeitos e <em>Decks</em> (play/cue, <em>jog wheel</em>, etc).</p>
<p>Uma evolução deste tipo de controle são os <strong>aplicativos para tablets</strong> (e smartphones também) que permitem enviar comandos aos programas de mixagem usando ou protocolo MIDI ou algum proprietário. Por exemplo, já temos diversos aplicativos para iPad e iPhone (além de Android também) que permitem comandar o próprio software de mixagem, a mesa de efeitos, iluminação, etc. Tudo na ponta dos dedos.</p>
<p>Eis que recentemente, a <strong><font color="#ff0000">Smithson Martín</font></strong> apresenta ao mundo o <strong><font color="#ff0000">Emulator DVS (Dual View System)</font></strong>, o primeiro sistema DJ <em>Multi-touch</em> do mundo. Trata-se de uma tela (varia de 32’’ à 46’’) multi-touch transparente que reconhece até seis toques simultâneos, que projeta em sua tela uma interface para controle de softwares para DJ, entre muitos outros.</p>
<p>É isso mesmo. Através de uma poderosa interface você pode controlar qualquer coisa em uma pista de dança e o uso não se restringe a isso. Para mostrar o poder do bichão, segue um vídeo feito pela <strong><font color="#ff0000">DJ Ban</font></strong>, onde o <em>DJ Will</em> mostra os recursos:</p>
<div style="padding-bottom: 0px; margin: 0px auto; padding-left: 0px; width: 448px; padding-right: 0px; display: block; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:be29e0c8-7776-415e-a3e7-d5b9385192d9" class="wlWriterEditableSmartContent">
<div><object width="448" height="252"><param name="movie" value="http://www.youtube.com/v/rMw6JjuT3uk?hl=en&amp;hd=1"></param><embed src="http://www.youtube.com/v/rMw6JjuT3uk?hl=en&amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"></embed></object></div>
<div style="width:448px;clear:both;font-size:.8em">Demonstração do Emulator DVS</div>
</div>
<p>Bem, depois do vídeo não preciso nem dizer, né?</p>
<p>Notaram que no título do post tem uma parte que diz “<strong><em>&#8230; e o futuro das interfaces para DJs</em></strong>”?</p>
<p>Viajando com meus botões, sempre imaginei-me tocando num club, manipulando a música e efeitos com uma interface <em><strong>touchless</strong></em>, estilo <em>Minority Report</em>. Assim:</p>
<div style="padding-bottom: 0px; margin: 0px auto; padding-left: 0px; width: 448px; padding-right: 0px; display: block; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:1bc0debc-39ea-44ef-bd5a-478a691d6d3c" class="wlWriterEditableSmartContent">
<div><object width="448" height="252"><param name="movie" value="http://www.youtube.com/v/NwVBzx0LMNQ?hl=en&amp;hd=1"></param><embed src="http://www.youtube.com/v/NwVBzx0LMNQ?hl=en&amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"></embed></object></div>
<div style="width:448px;clear:both;font-size:.8em">Interface Touchless, extraída do filme Minority Report (2002)</div>
</div>
<p>Vejam só, uma interface assim foi pensada em 2002!&#160; Hoje temos essa super tela touch do Emulator, será que estamos longe de algo como mostrado na ficção científica?</p>
<p>Versões antigas do Virtual DJ (acho que até a 6.x)&#160; tinham um recurso de <strong><font color="#ff0000">captura de movimentos</font></strong> através da WebCam, movimentos estes que eram utilizados para fazer <em>scratch</em>. Até que funcionava, mas claro que não era para ser utilizado em “produção”. Vejam uma demonstração:</p>
<div style="padding-bottom: 0px; margin: 0px auto; padding-left: 0px; width: 448px; padding-right: 0px; display: block; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:82169202-8a0e-46f5-8278-c5f1dda647dc" class="wlWriterEditableSmartContent">
<div><object width="448" height="252"><param name="movie" value="http://www.youtube.com/v/pBFV5NMFv4g?hl=en&amp;hd=1"></param><embed src="http://www.youtube.com/v/pBFV5NMFv4g?hl=en&amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"></embed></object></div>
<div style="width:448px;clear:both;font-size:.8em">Scratch no Virtual DJ através de captura de movimento</div>
</div>
<p>Em pleno 2012, já avançamos e muito no quesito captura de movimento. Olha só, podemos jogar video-game sem utilizar joystick, somente fazendo gestos pelo ar! <strong><font color="#ff0000">Microsoft Kinect</font></strong>, estou falando com você! Agora você já matou o que eu quero propor: Uma tela transparente tipo o Emulator juntando com a captura de movimento do Kinect ou outro sensor poderoso de captura de movimentos tridimensionais.</p>
<p>Com uma interface dessas, as performances “básicas” ganharão destaque perante o público “normal” de uma balada. Seria algo revolucionário MESMO, mais do que o Emulator sozinho o é.</p>
<p><strong>Agora só falta torná-la realidade, né? “<em>Os DJs pira!!!</em>”</strong></p>
<p>Abraço!</p>
<p>Fontes:    <br />[<a href="http://www.djban.com.br/noticias/emulator-dvs-workshop/" target="_blank">DJ Ban - Emulator DVS: Vídeo Review (demonstrativo) exclusivo da DJ Ban</a>]     <br />[<a href="http://www.smithsonmartin.com/emulator-dvs/" target="_blank">Smithson Martín - Emulator DVS (site do fabricante)</a>]</p>
<p><strong><font color="#ff0000">UPDATE 21/04/2012:</font></strong> Agora não falta mais tornar isso realidade, pois já o é! Agora é só amadurecer essa idéia e colocar nas pistas, né! <em>Os DJs continuam pirando</em>!!!</p>
<p> <iframe height="315" src="http://www.youtube.com/embed/7DcENxBIKTE" frameborder="0" width="560" allowfullscreen="allowfullscreen"></iframe>
<p>Fonte:    <br />[<a href="http://www.psicodelia.org/noticias/manipulando-a-musica-atraves-de-gestos-conheca-o-kinectar" target="_blank">Psicodelia.org - Manipulando a música através de gestos - Conheça o Kinectar</a>]</p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/vdeo-demonstrao-phalanger-compilador-php-para-net-framework-4-0/" rel="bookmark" class="crp_title">V&iacute;deo Demonstra&ccedil;&atilde;o: Phalanger &#8211; Compilador PHP para .NET Framework 4.0</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/vdeo-tutorial-gravando-um-set-no-traktor-2-audio-8-dj-utilizando-mixer-externo/" rel="bookmark" class="crp_title">V&iacute;deo Tutorial: Gravando um set no Traktor 2 + Audio 8 DJ utilizando Mixer Externo</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/screencast-clonando-hds-via-rede-com-o-udpcast/" rel="bookmark" class="crp_title">Screencast: Clonando HD&#8217;s via rede com o UDPCast</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/este-e-o-iphone-killer/" rel="bookmark" class="crp_title">Este é o iPhone Killer</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/jquery-jqmodal-e-asp-net-ajax-resolvendo-alguns-probleminhas/" rel="bookmark" class="crp_title">jQuery (jqModal) e ASP.NET + AJAX: Resolvendo alguns probleminhas</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/emulator-dvs-e-o-futuro-das-interfaces-para-djs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/emulator-dvs-e-o-futuro-das-interfaces-para-djs/</feedburner:origLink></item>
		<item>
		<title>Capturando a imagem de uma WebCam em páginas ASP.NET</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/Fyzp8jE5-GQ/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net/#comments</comments>
		<pubDate>Sat, 24 Mar 2012 22:53:44 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ASP.NET com Plugins no Cliente]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[WebCam]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=794</guid>
		<description><![CDATA[Olá, meus queridos! Vamos tirar a poeira do NM Tech (mais uma vez hehe) com um artigo de ótima utilidade para quem desenvolve aplicações ASP.NET e precisa capturar a imagem da WebCam instalada na máquina do usuário.
Supomos que você tenha uma aplicação Web para fazer cadastro de visitantes e que um  [...]]]></description>
			<content:encoded><![CDATA[<p>Olá, meus queridos! Vamos tirar a poeira do NM Tech (mais uma vez hehe) com um artigo de ótima utilidade para quem desenvolve aplicações ASP.NET e precisa <strong><font color="#ff0000">capturar a imagem da <em>WebCam</em> instalada na máquina do usuário</font></strong>.</p>
<p>Supomos que você tenha uma aplicação Web para fazer cadastro de visitantes e que um dos requisitos seja a captura da foto do visitante. Como todos sabemos, uma aplicação Web não possui condições de acessar os recursos de hardware do computador onde roda o navegador cliente por conta própria. Nem via <em>JavaScript</em>.</p>
<p>Para isso podemos fazer o uso de plugins (escritos utilizando <em>ActiveX</em> ou <em>Flash</em>), estes disparando eventos e respondendo a comandos em JavaScript, que fazem a ponte entre o HTML e o acesso ao hardware do usuário.</p>
<p>O que iremos fazer aqui é utilizar a biblioteca <a title="Código original do jpgcam, biblioteca para capturar imagens JPEG à partir da Webcam em uma página Web" href="http://code.google.com/p/jpegcam/" target="_blank">jpgcam</a> (<em><font size="2">acessem o site para maiores detalhes</font></em>), que faz uso de um arquivo <em><strong><font color="#ff0000">Flash</font></strong></em> para acessar os recursos da <em>WebCam</em>, um arquivo <strong><em><font color="#ff0000">JavaScript</font></em></strong>, que faz a interface entre o <em>Flash</em> e a página que incorpora este <em>script</em> e uma página <strong><em><font color="#ff0000">ASP.NET</font></em></strong> para processar o <em>upload</em> e gravar a imagem em um <strong>diretório do servidor Web</strong>.</p>
<p>No nosso projeto Web, temos o diretório <em>\camutils</em>, que contém a biblioteca <em>jpgcam</em> (exceto o arquivo MP3 que simula o som de um obturador, que deve ficar no diretório raíz do site), com o arquivo <em>webcam.js</em>, que será a interface entre a página ASPX e o arquivo <em>webcam.swf</em>, que faz a grande “mágica” de acessar a <em>WebCam</em>.</p>
<p>Observem o código da página <em>Default.aspx</em>:</p>
<pre class="brush:xhtml">&lt;%@ Page Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;Default.aspx.cs&quot; Inherits=&quot;CapturaWebcamASPNET.Default&quot; %&gt;

&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;&lt;/title&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;camutils/webcam.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
	    &lt;!-- Configura algumas opções --&gt;
	    &lt;script type=&quot;text/javascript&quot; language=&quot;JavaScript&quot;&gt;
	        webcam.set_api_url('Upload.aspx');//Página de destino do arquivo capturado
	        webcam.set_quality(90); // Qualidade do JPG (1 - 100)
	        webcam.set_shutter_sound(true); // Toca o som de câmera (o arquivo shutter.mp3, que vem com os &quot;utilitários&quot; da câmera, deve estar no diretório raíz do site)
	    &lt;/script&gt;

        &lt;table style=&quot;width:100%;&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;
            &lt;tr&gt;
                &lt;td style=&quot;width:320px;height:240px;text-align:center;&quot; valign=&quot;top&quot;&gt;
                    &lt;script type=&quot;text/javascript&quot; language=&quot;JavaScript&quot;&gt;
                        document.write(webcam.get_html(320, 240));
	                &lt;/script&gt;
                    &lt;input type=&quot;button&quot; value=&quot;Configurar...&quot; onclick=&quot;webcam.configure();&quot; /&gt;
                    &lt;input type=&quot;button&quot; value=&quot;Capturar&quot; onclick=&quot;take_snapshot();&quot; /&gt;
                    &lt;input type=&quot;button&quot; value=&quot;Reset&quot; onclick=&quot;webcam.reset();&quot; /&gt;
                &lt;/td&gt;
                &lt;td style=&quot;width:320px;height:240px;&quot; valign=&quot;top&quot;&gt;
	                &lt;!-- Desenha o HTML do Flash que faz a interface com a Webcam na resolução 320x240 --&gt;
                    &lt;div id=&quot;upload_results&quot;&gt;

                    &lt;/div&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;

        &lt;script type=&quot;text/javascript&quot;&gt;
            webcam.set_hook('onComplete', 'my_completion_handler');

            function take_snapshot() {
                // Captura a imagem e submete ao servidor
                document.getElementById('upload_results').innerHTML = '&lt;h1&gt;Realizando Upload da Foto...&lt;/h1&gt;';
                webcam.snap();
            }

            function my_completion_handler(msg) {
                // Extrai a URL da imagem do retorno de Upload.aspx
                if (msg.match(/(http\:\/\/\S+)/)) {
                    var image_url = RegExp.$1;
                    // show JPEG image in page
                    document.getElementById('upload_results').innerHTML =
					    '&lt;img src=&quot;' + image_url + '&quot;&gt;' +
                        '&lt;h1&gt;Upload Com Sucesso!&lt;/h1&gt;' +
					    '&lt;h3&gt;URL do JPG: ' + image_url + '&lt;/h3&gt;';

                    // reset camera for another shot
                    webcam.reset();
                }
                else alert(&quot;ASPNET Error: &quot; + msg);
            }
        &lt;/script&gt;

    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Inicialmente incorporamos o script <em>camutils/webcam.js</em> (<font size="2">fiz algumas anotações neste arquivo, é importante dar uma olhadinha <img src='http://leonelfraga.com/neomatrixtech/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </font> ) em nossa página na tag <em>&lt;head&gt;</em> (poderia ser fora dela), e já dentro do <em>&lt;body&gt;</em> configuramos alguns parâmetros para serem passados ao Flash. Na instrução <strong><em><font color="#ff0000">webcam.set_api_url()</font></em></strong> passamos o nome do arquivo que processará o <em>upload</em>. Não conheço o código da aplicação Flash, mas pelo seu comportamento, ele faz um HTTP POST diretamente para esta página (veremos ela mais adiante). No código original é um arquivo PHP que faz esse trabalho. Também configuramos outros parâmetros, que são a qualidade da imagem e se queremos o som do obturador.</p>
<p>Em seguida temos um layout básico de 2 colunas. Na esquerda chamamos a função <strong><em><font color="#ff0000">webcam.get_html(altura,largura)</font></em></strong>, que renderiza o HTML necessário para chamar o objeto Flash (arquivo <em>camutils/webcam.swf</em>) já passando os parâmetros correspondentes, que configuramos acima. Também temos três botões de controle a saber:</p>
<p>- <strong><em>Configurar&#8230;</em></strong>: Dispara a rotina do Flash para configurar a webcam. Chama o método da API <em>webcam.configure()</em> em seu método <em>onClick</em>;</p>
<p>- <strong><em>Captura</em></strong>r: Captura a imagem, chamando a função <em>take_snapshot()</em> que veremos em seguida.</p>
<p>- <strong><em>Reset:</em></strong> Prepara a câmera para nova captura. Chama a função da API <em>webcam.reset()</em>.</p>
<p><em><font color="#ff0000">PS: o objeto JavaScript “webcam” é definido dentro de camutils/webcam.js.</font></em></p>
<p>Na coluna da direita temos um <em>&lt;div&gt;</em> que receberá a imagem capturada.</p>
<p>No segundo bloco <em>JavaScript</em>, declaramos uma função que “ouvirá” o evento <em><strong><font color="#ff0000">onComplete</font></strong></em> do objeto da WebCam. Este evento será ouvido pela função “<strong><em><font color="#ff0000">my_completion_handler</font></em></strong>” definida abaixo. Este evento recebe um parâmetro, que é a resposta da página <strong>Upload.aspx</strong>, que deverá retornar a URL da imagem em caso de sucesso, ou outra mensagem em caso de erro.</p>
<p>Em caso de sucesso, esta função escreverá um HTML no <em>&lt;div&gt;</em> “<em>upload_results</em>”, que conterá um <em>&lt;img&gt;</em> com a URL retornada. Caso contrário, disparamos um <em>alert()</em> com a mensagem de erro. </p>
<p>A checagem de erro é feita através de uma expressão regular. Se esta expressão contiver os padrões de uma URL, será válida.</p>
<p>A função <em><font color="#ff0000"><strong>take_snapshot()</strong></font></em> não tem segredo. Ela apenas dispara o método <em><strong><font color="#ff0000">webcam.snap()</font></strong></em>. Este método aciona um método correspondente no Flash, que captura a foto da webcam e faz um HTTP POST para a página Upload.aspx. Após isso, o método que declaramos em <em>onComplete (função <strong><em><font color="#ff0000">my_completion_handler</font></em></strong>)</em> será disparado.</p>
<p>E agora, como processamos o HTTP POST gerado pelo Flash na página <em><strong><font color="#ff0000">Upload.aspx</font></strong></em> e retornamos como resposta a URL da imagem? Vamos ao código:</p>
<pre class="brush:csharp">protected void Page_Load(object sender, EventArgs e)
{
	if (!IsPostBack)
	{
		try
		{
			string Dir = Server.MapPath(&quot;uploads&quot;);
			string FileName = String.Format(&quot;{0:ddMMyyyyhhmmss}.jpg&quot;, DateTime.Now);

			string CompleteFileName = String.Format(&quot;{0}\\{1}&quot;, Dir, FileName);

			using (FileStream fs = new FileStream(CompleteFileName, FileMode.Create))
			{
				byte[] buffer = new byte[Request.InputStream.Length];
				Request.InputStream.Read(buffer, 0, (int)Request.InputStream.Length);
				fs.Write(buffer, 0, buffer.Length);
			}

			string URLSaida = String.Format(&quot;{0}://{1}{2}{3}&quot;, Request.Url.Scheme, Request.Url.GetComponents(UriComponents.HostAndPort, UriFormat.Unescaped), &quot;/uploads/&quot;, FileName);
			Response.Clear();
			Response.Write(URLSaida);
		}
		catch
		{
			Response.Clear();
			Response.Write(&quot;ERROR: Erro ao salvar imagem\n&quot;);
		}
		Response.End();
	}
}</pre>
<p>Agora sim trabalharemos no server-side!</p>
<p>Primeiro checamos se não é realizado um <em>postback</em> (evita que o <em>Page_Load</em> seja executado mais de uma vez), e configuramos o diretório (no Servidor Web) onde gravaremos as fotos e o nome que o arquivo terá. Como diretório, criei um diretório <em>\uploads</em> no diretório raíz do site e guardamos seu caminho físico, usando o método <em>Server.MapPath,</em> passando o nome da pasta <em>\uploads</em> como parâmetro, na variável <em>Dir</em>. Como nome de arquivo, gravaremos a data atual, incluíndo dia, mês, ano, minuto e segundo (em um ambiente de produção, inclua também os milissegundos ou concatene outra coisa, como a <em>SessionID</em>, para não ter risco de duplicar o nome do arquivo). <strong><font color="#ff0000">Não esqueça que o diretório deve ter permissão de gravação para a conta de usuário que roda o processo no servidor que executa a página!</font></strong></p>
<p>Após isso, guardamos o caminho físico completo do novo arquivo na variável <em>CompleteFileName</em>.</p>
<p>O arquivo Flash gerou um HTTP POST para a página Upload.aspx, diretamente. O conteúdo dele está na <em>InputStream</em> de nossa página processadora do upload. Salvamos esta <em>InputStream</em> no arquivo que nomeamos acima através de um <em>FileStream</em>.</p>
<p>Beleza, gravamos a foto no servidor, e agora precisamos retornar a URL da foto (esta Web, não física) para ser processada e exibida na página pela função que ouve o evento <em>onComplete</em> do objeto webcam em Default.aspx.</p>
<p>Geramos a URL de saída através do <em>Scheme</em> da URL (o protocolo, como o http://), do <em>Host</em> e da <em>porta</em> (exemplo: localhost:3000, e caso não tenha porta declarada &#8211; porta 80 &#8211; só localhost), do diretório onde vamos gravar a foto, e o nome do arquivo jpg (somente o nome, na variável FileName, sem o <em>path</em> físico). Concatenamos tudo isso e guardamos na variável <em>URLSaida</em>.</p>
<p>Para “jogar” essa URL na resposta, não basta apenas dar um Response.Write(URLSaida). Isto fará com que todo o HTML da página também vá junto, e somente queremos a URL. Para fazer isso, limpamos a saída com um <em>Response.Clear()</em> e em seguida sim, damos um <em>Response.Write(URLSaida)</em> e após um <em>Response.End()</em> para que a página seja imediatamente devolvida.</p>
<p>Após todo este processo, você visualizará a imagem capturada à direita e a WebCam estará pronta para outra captura.</p>
<p>Embora o artigo seja um pouquinho longo, não é difícil usar. Baixe o código-fonte exemplo, e você verá que não tem segredo. No próximo artigo vamos ver uma aplicação prática disso tudo, só que em vez de salvar em um arquivo, salvaremos em Banco de Dados.</p>
<p>Tenha bons sistemas Web ASP.NET com captura de foto!</p>
<p><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" border="0" src="http://lh6.ggpht.com/_Kzg5fUTKXVY/S1sv5NsGvXI/AAAAAAAAIPo/Bo1zCLYK2qI/download15B15D5B55D5B15D_thumb5B15D5%5B1%5D.png?imgmax=800" /> Download: <a href="http://leonelfraga.com/downloads/CapturaWebcamASPNET.zip" target="_blank">Projeto ASP.NET com captura de imagem via WebCam (básico)</a> <em>(.NET Framework 4.0 e VisualStudio 2010, mas nada impede que seja portada para outros&#8230; vejam, o original é em PHP</em>!)</p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net-salvando-o-cadastro-em-banco-de-dados/" rel="bookmark" class="crp_title">Capturando a imagem de uma WebCam em p&aacute;ginas ASP.NET &#8211; Salvando o cadastro em Banco de Dados</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/upload-em-asp-net-com-jqmodal-e-efeitos-ajax/" rel="bookmark" class="crp_title">Upload em ASP.NET com jqModal e efeitos AJAX</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/exemplo-de-uso-manipulando-planilhas-excel-com-ado-net/" rel="bookmark" class="crp_title">Exemplo de uso – Manipulando Planilhas Excel com ADO.NET</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/redirecionando-do-blogger-para-o-wordpress-com-permalinks-padro/" rel="bookmark" class="crp_title">Redirecionando do Blogger para o WordPress com permalinks padr&atilde;o</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/ajax-loader-com-bloqueio-da-tela/" rel="bookmark" class="crp_title">Ajax Loader com Bloqueio da Tela</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net/</feedburner:origLink></item>
		<item>
		<title>ILSpy: Ferramenta para “decompilar” Assemblies .NET</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/lkHEDhuwmts/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/ilspy-ferramenta-para-decompilar-assemblies-net/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 00:51:46 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[.NET Geral]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Decompilador]]></category>
		<category><![CDATA[Disassembler]]></category>
		<category><![CDATA[Ferramentas]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=791</guid>
		<description><![CDATA[Olá meu caro leitor! Faz um (bom) tempo que não posto um artigo aqui, né? Como foi a sua passagem de ano? A minha foi “male mal”&#8230; Quem lê o NM Light vai saber o motivo  .
Vamos começar 2012 falando sobre uma ferramenta que pode salvar vidas (tá, estou exagerando, mas pode salvar carreiras hehe) de  [...]]]></description>
			<content:encoded><![CDATA[<p>Olá meu caro leitor! Faz um (bom) tempo que não posto um artigo aqui, né? Como foi a sua passagem de ano? A minha foi “male mal”&#8230; Quem lê o NM Light vai saber o motivo <img src='http://leonelfraga.com/neomatrixtech/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Vamos começar 2012 falando sobre uma ferramenta que pode salvar vidas (tá, estou exagerando, mas pode salvar carreiras hehe) de quem desenvolve em .NET. Quando você pega um projeto que usa algumas bibliotecas feitas pelo desenvolvedor anterior, você PRECISA fazer algumas alterações nela ou, no meu caso, compilar o projeto com um componente mais atual porque se for usar a biblioteca original ele OBRIGA A USAR a versão antiga e <strong>que o fonte foi pras cucuias</strong>?</p>
<p>De posse da biblioteca original você poderá ver o código-fonte usando uma ferramenta oferecida pelo próprio Visual Studio:<strong> IL Disassembler</strong>, ou <strong>IL DASM</strong> para os mais chegados. Mas tem um porém: ela apresenta o código na <em>Common</em> <em>Intermediate Language (CIL)</em>, o código que o compilador JIT do .NET Framework traduz para código de máquina e por fim é executado. Bem, não é nada produtivo ficar tentando entender a IL, certo?</p>
<p>Há algum tempo atrás, existia uma ferramenta gratuita chamada <strong>.NET Reflector</strong>. Esta ferramenta traduzia a IL para C# ou outras linguagens da plataforma .NET e exportava para um projeto, prontinho para compilar. Um porém desta ferramenta é que ela forçava os updates automáticos, de forma que se a rotina de atualização fosse cancelada o programa “matava a si próprio”, ou seja, era apagado do disco. E não adiantava reinstalar. No fim, o desenvolvedor vendeu o .NET Reflector para a empresa <strong>Red Gate</strong>, que continua o seu desenvolvimento porém o aplicativo agora é pago e a versão <em>Standard</em> custa US$ 35,00 (fonte: <a href="http://www.reflector.net/">http://www.reflector.net/</a>).</p>
<p>Dando uma pesquisada por aí, achei um substituto legal e que cumpre ao meu propósito: o <strong><font color="#ff0000">IL Spy</font></strong>. Ele também é um “<em>disassembler</em>” para .NET, que traduz o código em IL para C# e permite salvar o projeto. Só que com um detalhe: é de <strong>código-aberto e grátis</strong><font size="2"> (lembre-se que uma característica não implica em ter a outra <img src='http://leonelfraga.com/neomatrixtech/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> )</font>.</p>
<p><a href="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2012/01/screens-ilspy.jpg"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="Captura de tela do IL Spy" border="0" alt="Captura de tela do IL Spy" src="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2012/01/screens-ilspy_thumb.jpg" width="350" height="230" /></a></p>
<p>Com ele, consegui pegar todas as classes que precisava, colar em um novo projeto, referenciar as bibliotecas mais atuais e compilar. Mas nem tudo são flores:<font color="#ff0000"> Ele traduz o código de algumas propriedades, principalmente indexadas, colocando no lugar da propriedade a chamada para seu método ancestral, “<em>getter</em>” ou “<em>setter</em>”</font>, por exemplo:</p>
<pre class="brush:csharp">//Como a propriedade é colocada no código original:
MeuDataSet.Tables[i];
MeuArrayList.Count;
MeuDataRow[&quot;CAMPO&quot;] = valor;

//Como ela é traduzida pelo IL Spy
MeuDataSet.get_Tables(i);
MeuArrayList.get_Count();
MeuDataRow.set_Row(&quot;CAMPO&quot;,valor);</pre>
<p>Quando compilava sem fazer o devido ajuste ocorria um erro de compilação, pois os <em>getters</em> e <em>setters</em> das propriedades exemplificadas acima não são métodos públicos, portanto não poderiam ser acessados de fora da classe onde foram declarados.</p>
<p>Tirando esse pequeno atormento (que dependendo do código se torna um grande atormento&#8230;), repito que a ferramenta atendeu os meus objetivos e a recomendo em casos de emergência ou até mesmo para estudo de fontes (desde que não estejam ofuscados, claro!).</p>
<p>Onde baixar? Aqui: <a href="http://wiki.sharpdevelop.net/ILSpy.ashx">http://wiki.sharpdevelop.net/ILSpy.ashx</a></p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/componentes-gratis-e-bom-mas/" rel="bookmark" class="crp_title">Componentes gr&aacute;tis &eacute; bom, mas&#8230;</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/repercussao-do-fud-da-symantec/" rel="bookmark" class="crp_title">Repercussão do FUD da Symantec</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net/" rel="bookmark" class="crp_title">Capturando a imagem de uma WebCam em p&aacute;ginas ASP.NET</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/capturando-a-imagem-de-uma-webcam-em-paginas-asp-net-salvando-o-cadastro-em-banco-de-dados/" rel="bookmark" class="crp_title">Capturando a imagem de uma WebCam em p&aacute;ginas ASP.NET &#8211; Salvando o cadastro em Banco de Dados</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/atualizao-compactando-e-transmitindo-datasets-via-xml/" rel="bookmark" class="crp_title">Atualiza&ccedil;&atilde;o! Compactando e Transmitindo DataSets via XML</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/ilspy-ferramenta-para-decompilar-assemblies-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/ilspy-ferramenta-para-decompilar-assemblies-net/</feedburner:origLink></item>
		<item>
		<title>Votação Bebê Hipoglós Amêndoas 2011 – Analisando o sistema de votação</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/g_Za5ZcWZlY/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/votacao-bebe-hipoglos-amendoas-2011-analisando-o-sistema-de-votacao/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 16:11:37 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[Absurdos]]></category>
		<category><![CDATA[Engenharia de Sistemas]]></category>
		<category><![CDATA[Opinião]]></category>
		<category><![CDATA[Bebê Hipoglós]]></category>
		<category><![CDATA[Sistemas de Votação online]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=788</guid>
		<description><![CDATA[
Olá caro leitor do NM Tech! Você, como desenvolvedor de sistemas, já precisou desenvolver um sistema de votação eletrônica pela Web? Se sim, você já parou para pensar qual seria a carga de acessos deste sistema e uma forma de permitir uma votação segura e confiável?
Algumas amigas minhas  [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2011/11/image.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="Hotsite Bebê Hipoglós 2011" border="0" alt="Hotsite Bebê Hipoglós 2011" src="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2011/11/image_thumb.png" width="324" height="215" /></a></p>
<p>Olá caro leitor do NM Tech! Você, como desenvolvedor de sistemas, já precisou desenvolver um sistema de votação eletrônica pela Web? Se sim, você já parou para pensar qual seria a carga de acessos deste sistema e uma forma de permitir uma votação segura e confiável?</p>
<p>Algumas amigas minhas inscreveram seus filhos para participarem do Concurso “<strong><font color="#ff0000">Bebê Hipoglós 2011</font></strong>”, onde a criança irá ser o “bebê-propaganda” do referido produto. Para votar basta entrar no site <a title="http://bebehipoglos2011.com.br/" href="http://bebehipoglos2011.com.br/">http://bebehipoglos2011.com.br/</a>, escolher o bebê, clicar no ícone “Votar”, preencher um <em>captcha</em> e dar OK. Sim, é só isso mesmo.</p>
<p>Ah, Léo.. você fazendo jabá da promoção aqui no NM Tech? Epa, calma lá, rapá! Agora vou responder as duas perguntas que fiz acima: Sim, eu já desenvolvi um sistema de votação eletrônica que era aberto ao público e que a carga era moderada. E a votação era segura e confiável graças a alguns mecanismos que foram implementados.</p>
<p>Continuando no caso do site <strong><font color="#ff0000">Bebê Hipoglós 2011</font></strong>, a página da campanha no Facebook (<a href="http://www.facebook.com/bebehipoglos">http://www.facebook.com/bebehipoglos</a>) está cheia de<strong> comentários negativos à respeito do <font color="#ff0000">sistema de votação</font></strong>. Muitas pessoas estão reclamando que o site cai toda hora e que em pouco tempo de promoção existem crianças com mais de 10 mil votos.</p>
<p>Sim, constatei por mim mesmo que o sistema está sobrecarregado, e uma das coisas que me chamaram a atenção nos meus comentários foi:</p>
<blockquote><p>“Olá pessoal estou desde as 07:15 da manhã consegui votar 511 x na minha filha mas realmente esta muito complicado votar”</p>
</blockquote>
<p>Isso mesmo, a MESMA pessoa votando várias vezes em seu bebê. Então COMO as pessoas querem que a votação seja confiável e que o sistema não tenha sobrecarga? Não foi só essa pessoa que teve essa <em><strong>ideota</strong></em> de <em><strong><font color="#ff0000">jênio*</font></strong></em>, né?</p>
<p>E para votar, como eu disse anteriormente, o sistema pede para preencher um <em>captcha</em>, muito tosco, facilmente decodificável por ferramentas de <em><abbr title="Reconhecimento Óptico de Caracteres">OCR</abbr></em>, e como sabemos,<strong> já existem robôs que possuem esta funcionalidade</strong>. Com um (um não, vários&#8230; muitas pessoas podem ter tido essa idéia) robô desses fazendo várias requisições ao servidor Web, não há estrutura que aguente.</p>
<p>Nenhuma forma de identificação do votante é requerida.</p>
<p>No sistema de eleição que fiz, antes de votar o usuário tinha que preencher seus dados, confirmá-los no sistema e aí sim escolher seu candidato. Tal sistema NÃO permite que o mesmo usuário vote novamente. E mesmo com o cadastro, o voto era computado de forma totalmente anônima, sendo IMPOSSÍVEL saber quem votou em quem.</p>
<p>Por que não implementar, como disse um comentarista no Facebook, um passo onde o usuário registraria alguns dados pessoais e o CPF (obrigatório) antes de votar e permitisse apenas UM voto por CPF? Aí sim aumentaria e muito a confiabilidade do sistema e a farra dos robôs diminuiria bastante. Bloqueio de voto por IP não resolveria, já que muitas casas hoje em dia já contam com uma pequena rede onde a conexão à Internet é compartilhada.</p>
<p>Quer ver como isso é uma coisa SIMPLES de ser implementada? Vou mostrar um modelo básico, com 2 tabelas e os passos necessários (não código) para realizar a votação:<a href="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2011/11/image1.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2011/11/image_thumb1.png" width="198" height="108" /></a></p>
<p>Veja só: apenas duas tabelas, e não há ligação nenhuma entre elas. Para gravar um voto, crie uma <em>StoredProcedure</em> no banco de dados com os parâmetros de entrada do eleitor (Nome, CPF, Email e o ID do candidato que ele votou) Coloque o modo de isolação de transação no modo <em>Repeatable Read</em> (recomendado), abra uma transação, faça um <em>select</em> no eleitor baseando-se no CPF para verificar se ele já já existe na tabela “<em>Eleitor</em>” (se sim, dispare uma exceção informando a interface desta situação), dê um <em>select</em> no candidato baseando-se no ID passado como entrada (para travar o registro, já que isolamos a transação como <em>Repeatable Read</em>), faça um <em>Update</em> no <em>Candidato</em>, incrementando 1 no campo “<em>QtdVotos</em>”, faça o <em>Insert</em> na tabela Eleitor e dê <em>commit</em> na transação.</p>
<p>Simples assim, não? Ah, e antes que venham com o “Ah, mas o DBA ou outra pessoa pode alterar o campo <em>QtdVotos</em> e tal&#8230;”, não estou contando que esta intervenção humana venha a acontecer, por que daí já é caso de Justiça e tal, são outros quinhentos.</p>
<p>Isso vai burocratizar o processo de votação? SIM. E este é o preço a pagar por uma maior confiabilidade no sistema de votação. O que é mais vantajoso para a sua empresa: Um sistema que é um pouco “chato” para votar porém os usuários falam que é confiável ou um totalmente escancarado dando margem para inúmeras reclamações quanto a idoneidade do concurso? Lembrem-se que um comentário negativo viaja milhares de vezes mais rápido que um positivo! E se não fossem pelos comentários negativos (que minhas amigas que inscreveram seus bebês fizeram e fui conferir o sistema), nem escreveria este post!</p>
<p>Eu não me conformo como um sistema que dá uma premiação em dinheiro, mexe com as emoções de milhares de mães/pais que cadastraram seus filhos (sim, porque as crianças ainda não entendem) na expectativa de vê-los em um comercial de TV e se tornarem famosos, ser modelado de uma forma TÃO TOSCA???</p>
<p>Um abraço!!!</p>
<p><em>*com “J” de JUMENTO <img src='http://leonelfraga.com/neomatrixtech/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </em></p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/controle-de-permissoes-utilizando-operacao-bit-a-bit/" rel="bookmark" class="crp_title">Controle de permiss&otilde;es utilizando opera&ccedil;&atilde;o bit a bit</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/apps-do-google-nos-galaxy-s-e-5-da-claro-claro-que-no-clarofail/" rel="bookmark" class="crp_title">Apps do Google nos Galaxy S e 5 da CLARO? CLARO que N&Atilde;O! #CLAROFAIL</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/rapidinha-customvalidators-no-disparam-o-servervalidate-quanto-est-vazio-veja-o-que-pode-ser-aqui/" rel="bookmark" class="crp_title">Rapidinha: CustomValidators n&atilde;o disparam o ServerValidate quando est&aacute; vazio? Veja o que pode ser aqui!</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/componentes-gratis-e-bom-mas/" rel="bookmark" class="crp_title">Componentes gr&aacute;tis &eacute; bom, mas&#8230;</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/nokia-e-microsoft-o-incio-de-um-casamento/" rel="bookmark" class="crp_title">Nokia e Microsoft: O in&iacute;cio de um casamento</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/votacao-bebe-hipoglos-amendoas-2011-analisando-o-sistema-de-votacao/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/votacao-bebe-hipoglos-amendoas-2011-analisando-o-sistema-de-votacao/</feedburner:origLink></item>
		<item>
		<title>Calculando idade via SQL Server (UDF)</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/kV3Ud-89pKo/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/calculando-idade-via-sql-server-udf/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 00:19:49 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[Banco de Dados]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Cálculo de Idade]]></category>
		<category><![CDATA[UDF]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=783</guid>
		<description><![CDATA[Em nossos sistemas muitas vezes precisamos consultar a idade de uma pessoa para as mais diversas finalidades. A conta é simples: diferença de anos entre a data atual e a data de nascimento, certo?
Eu diria que em partes, dependendo de como o cálculo é feito. Em se tratando apenas de SQL Server o  [...]]]></description>
			<content:encoded><![CDATA[<p>Em nossos sistemas muitas vezes precisamos consultar a idade de uma pessoa para as mais diversas finalidades. A conta é simples: diferença de anos entre a data atual e a data de nascimento, certo?</p>
<p>Eu diria que em partes, dependendo de como o cálculo é feito. Em se tratando apenas de SQL Server o nosso primeiro impulso é calcular essa diferença usando a função datediff(), passando como argumentos que queremos o resultado em anos e as datas envolvidas.</p>
<p>Calcular idade NÃO é apenas uma simples diferença entre o componente ANO das datas, que é o que a função datediff faz se passarmos como primeiro argumento que queremos a diferença em anos. Nesse caso o cálculo da diferença não leva em consideração os dias e os meses, fundamentais para o cálculo de idade. A questão que devemos ter em mente é: “A pessoa já completou determinada idade no dia atual?”</p>
<p>Para facilitar este cálculo montei uma UDF em Transact-SQL, que retorna um valor escalar que é a idade baseada na data de nascimento informada e no dia atual, que leva em consideração que tal data de aniversário foi atingida ou não. Vamos a ela:</p>
<pre class="brush:sql">create function [dbo].[CalculaIdade](@DataNascimento Datetime)
returns int
AS
BEGIN
	declare @idade int;
	--Coloca o dia e mês da data de nascimento no ano atual
	declare @DataNormalizada datetime;
	--Volta a data em 01/01 do ano atual sem utilizar concatenação de strings (evita lembrar usar o SET DATEFORMAT)
	set @DataNormalizada = dateadd(dd,0,datediff(dd,0,dateadd(dd,(-1)*day(getdate()) + 1,dateadd(mm,(-1)*month(getdate()) + 1,getdate()))));
	--Agora sim, calcula a data de aniversário no ano atual
	set @DataNormalizada = dateadd(dd,day(@DataNascimento) -1,dateadd(mm,month(@DataNascimento) -1,@DataNormalizada));

	--Calcula a idade em anos (o SQL Server irá apenas subtrair o componente ANO, sem considerar os dias)
	set @idade = datediff(yy,@DataNascimento,getdate());

	--se ainda não chegou no dia de nascimento, subtrai 1 da idade, já que ainda não estará completa.
	--O cálculo acima com datediff não leva isto em consideração.
	if( @DataNormalizada &gt; getdate())
	begin
		set @idade = @idade - 1;
	end
	return @idade;
END
GO</pre>
<p>Primeiramente declaramos uma variável @DataNormalizada, que nada mais é que a data de aniversário no ano corrente e para calculá-la sem concatenar strings (para não nos preocuparmos com formatação de data) “voltamos” o ano atual para 01/01 e em seguida acrescentamos o mês e o dia da data de aniversário. Nessa adição, necessitamos subtrair 1 do dia e do mês porque como começamos o valor em “1” e não em “0”, necessitamos compensar essa diferença.</p>
<p>Em seguida fazemos o que o nosso impulso manda: calculamos a diferença em anos utilizando a função datediff().</p>
<p>Agora que vem o pulo do gato: Lembra que calculamos a data de aniversário da pessoa no ano corrente? Pois bem: Verificamos se a data de aniversário é maior que a data atual. Se sim, significa que a pessoa ainda não fez aniversário e que a idade em anos calculada acima está incompleta, portanto, temos que subtrair 1 ano da idade.</p>
<p>Esse pequeno detalhe do cálculo da idade é crucial (sim, dependendo da área de negócio, exemplos como sistemas de gestão de saúde, a idade correta de uma pessoa é muito importante e é um dado dinâmico sempre calculado a partir da data de nascimento), portanto, preste MUITA atenção e bora utilizar a função acima para calcular!</p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/cuidado-com-converso-de-dados-no-sql-server/" rel="bookmark" class="crp_title">Cuidado com convers&atilde;o de dados no SQL Server</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/auditando-alteracoes-de-dados-no-sql-server-de-forma-simples/" rel="bookmark" class="crp_title">Auditando alterações de dados no SQL Server de forma simples</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/modelagem-bsica-de-webservices/" rel="bookmark" class="crp_title">Modelagem b&aacute;sica de Webservices</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/configuracoes-regionais-parece-algo-sem-importancia-mas/" rel="bookmark" class="crp_title">Configurações Regionais: Parece algo sem importância, mas…</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/uma-situacao-nao-prevista-fail/" rel="bookmark" class="crp_title">Uma situação não prevista: #FAIL</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/calculando-idade-via-sql-server-udf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/calculando-idade-via-sql-server-udf/</feedburner:origLink></item>
		<item>
		<title>DateTime, Serialização de DataSets em WCF, Horário de Verão… uma combinação com muitas surpresas!</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/e57y_Dkpmf0/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/datetime-serializao-de-datasets-em-wcf-horrio-de-vero-uma-combinao-com-muitas-surpresas/#comments</comments>
		<pubDate>Thu, 18 Aug 2011 01:48:45 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[.NET Geral]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[DateTime]]></category>
		<category><![CDATA[WCF]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=780</guid>
		<description><![CDATA[Veja a seguinte situação: Você possui um serviço WCF que está hospedado em um servidor e vários clientes que acessam este serviço. Este serviço possui um método que retorna um DataSet, serializando-o através do WCF e a classe cliente exibe o resultado em tela.
Pois bem, você possui neste DataSet  [...]]]></description>
			<content:encoded><![CDATA[<p>Veja a seguinte situação: Você possui um serviço WCF que está hospedado em um servidor e vários clientes que acessam este serviço. Este serviço possui um método que retorna um DataSet, serializando-o através do WCF e a classe cliente exibe o resultado em tela.</p>
<p>Pois bem, você possui neste DataSet uma (ou mais) tabela com um campo DateTime, e no seu banco de dados está gravado o valor, por exemplo, 17/10/2011 08:00, mas a sua aplicação exibe o valor 17/10/2011 09:00.</p>
<p>O que!!! Quer dizer que a aplicação está exibindo este valor uma hora ADIANTADA? Exatamente isso, meu querido! Se fomos extrair este campo para uma variável DateTime e verificarmos o resultado do método IsDayLightSavingTime(), o mesmo retornará True, indicando que a data em questão cai no horário de verão.</p>
<p>Se fomos olhar isso mais a fundo na aplicação cliente, veremos que o valor já considerando o horário de verão (no nosso caso, 1 hora adiantada) já vem do próprio DataSet que recuperamos via WCF do servidor. Se a aplicação cliente extraísse esse valor diretamente do banco de dados ele seria exibido corretamente. E se quisermos exibir o valor do banco de dados, como faz?</p>
<p>Na máquina que executa a aplicação cliente, caso você esteja utilizando o Windows XP, dê um duplo clique no relógio, acesse a guia “Fuso Horário” e desmarque a opção “Ajustar automaticamente para o horário de verão” e o seu problema estará resolvido e a aplicação passará a exibir as horas conforme estão gravadas no banco de dados.</p>
<p>Maaaaaaaas&#8230; tem um pequeno grande porém nesta “solução”: E se este flag do horário de verão não puder ser desabilitado pelo usuário (permissões no sistema, entre outros) e não acho um meio na aplicação cliente de fazer as horas serem exibidas corretamente, sento e choro?</p>
<p>Sentar e chorar é uma hipótese dependendo de como você modelou a parte servidora do seu sistema. Mas a solução definitiva é a seguinte: Ao obter um DataSet do banco de dados, devemos modificar uma propriedade chamada DateTimeMode das colunas DateTime das tabelas deste DataSet para DataSetDateTime.Unespecified, que informa para o WCF não recalcular as datas para a zona de horário das aplicações clientes na hora da serialização.</p>
<p>Vamos ao código!</p>
<pre class="brush:csharp">public DataSet RetornaDataSet()
{
	DataSet ds = new DataSet();
	//Preencher o DataSet com os valores do banco de dados aqui

	//Agora, iremos modidicar as colunas DateTime das tabelas para ignorarem o recálculo de data/hora no momento da serialização WCF
	foreach (DataTable tabela in ds.Tables)
	{
		foreach (DataColumn coluna in tabela.Columns)
		{
			if ((coluna.DataType == typeof(DateTime)) || (coluna.DataType == typeof(DateTime?)))
			{
				coluna.DateTimeMode = DataSetDateTime.Unspecified;
			}
		}
	}
	return ds;
}</pre>
<p>Com este código modificamos todas as colunas com o tipo DateTime para que quando o DataSet for serializado via WCF, as datas não sejam recalculadas conforme a zona de tempo do usuário cliente (horário de verão, fuso-horáro, etc.).</p>
<p>É isso aí!</p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/fazendo-algo-incomum-zipando-e-transmitindo-datasets-grandes-via-xml-webservices-wcf-outros/" rel="bookmark" class="crp_title">Fazendo algo incomum: Zipando e Transmitindo DataSets grandes via XML (WebServices, WCF, outros).</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/configuracoes-regionais-parece-algo-sem-importancia-mas/" rel="bookmark" class="crp_title">Configurações Regionais: Parece algo sem importância, mas…</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/cuidado-com-converso-de-dados-no-sql-server/" rel="bookmark" class="crp_title">Cuidado com convers&atilde;o de dados no SQL Server</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/auditando-alteracoes-de-dados-no-sql-server-de-forma-simples/" rel="bookmark" class="crp_title">Auditando alterações de dados no SQL Server de forma simples</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/calculando-idade-via-sql-server-udf/" rel="bookmark" class="crp_title">Calculando idade via SQL Server (UDF)</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/datetime-serializao-de-datasets-em-wcf-horrio-de-vero-uma-combinao-com-muitas-surpresas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/datetime-serializao-de-datasets-em-wcf-horrio-de-vero-uma-combinao-com-muitas-surpresas/</feedburner:origLink></item>
		<item>
		<title>Rapidinha: CustomValidators não disparam o ServerValidate quando está vazio? Veja o que pode ser aqui!</title>
		<link>http://feedproxy.google.com/~r/neomatrixtech/~3/6LY5tgQG7cw/</link>
		<comments>http://leonelfraga.com/neomatrixtech/index.php/rapidinha-customvalidators-no-disparam-o-servervalidate-quanto-est-vazio-veja-o-que-pode-ser-aqui/#comments</comments>
		<pubDate>Sat, 13 Aug 2011 02:08:47 +0000</pubDate>
		<dc:creator>Leonel Fraga de Oliveira</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[CustomValidator]]></category>
		<category><![CDATA[Validação]]></category>

		<guid isPermaLink="false">http://leonelfraga.com/neomatrixtech/?p=777</guid>
		<description><![CDATA[Veja a seguinte situação: Você tem um campo em um WebForm que é obrigatório apenas em uma determinada condição. O mesmo campo, em outra condição NÃO é de preenchimento obrigatório. Você poderia usar um RequiredFieldValidator nele, certo?
Errado! Um RequiredFieldValidator apenas irá disparar se o  [...]]]></description>
			<content:encoded><![CDATA[<p>Veja a seguinte situação: Você tem um campo em um <em>WebForm</em> que é obrigatório apenas em uma determinada condição. O mesmo campo, em outra condição NÃO é de preenchimento obrigatório. Você poderia usar um <strong><em>RequiredFieldValidator</em></strong> nele, certo?</p>
<p>Errado! Um <em>RequiredFieldValidator</em> apenas irá disparar se o campo NÃO estiver preenchido. O que queremos é que numa condição X em que um textbox esteja vazio, o validator execute, e em outra não.</p>
<p>Para isso podemos utilizar um <em><strong>CustomValidator</strong></em> e atribuir a propriedade de argumento de evento <em>IsValid</em> no evento <em>ServerValidate</em> para que seja <em>True</em> se as nossas condições forem obedecidas.</p>
<p>Porém (sempre tem um porém!) justamente quando você quer validar quando o&#160; campo está vazio utilizando um <em>CustomValidator</em> o evento <em><strong>ServerValidate</strong></em> não dispara nem a pau, mesmo você chamando diretamente o método<em> Validate()</em> do mesmo. E você não pode usar um <em>RequiredFieldValidator</em>. O que você faz, ajoelha e chora?</p>
<p>Com exceção do <em>RequiredFieldValidator</em>, TODOS os demais <em>validators</em> não executam quando um <em>textbox</em> na propriedade <em>ControlToValidate</em> está vazio. Este é um comportamento padrão. Vamos dar uma olhada na caixa de propriedades de um CompareValidator e um CustomValidator:</p>
<p><a href="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2011/08/image.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="Caixa de Propriedades de um CustomValidator x CompareValidator" border="0" alt="Caixa de Propriedades de um CustomValidator x CompareValidator" src="http://leonelfraga.com/neomatrixtech/wp-content/uploads/2011/08/image_thumb.png" width="573" height="315" /></a></p>
<p>Além das propriedades inerentes a cada tipo de <em>Validator</em>, temos uma propriedade curiosa no <em>CustomValidator</em>: <strong><em><font color="#ff0000">ValidateEmptyText</font></em></strong>. Se colocarmos ela em <em>True</em>, o evento <em>ServerValidate</em> irá ser executado ao verificar a propriedade <em>IsValid</em> da página ou outra rotina de validação. Os outros tipos de <em>validator</em> não validam quando o texto está vazio. Com isso podemos testar, por exemplo, a obrigatoriedade de um campo em determinada condição em nosso sistema.</p>
<p>Dica fácil essa, né? Quando pesquisei sobre o assunto, vi uma sugestão em que era necessário derivar uma classe do “pai” dos <em>validators</em>!</p>
<p>Espero que esta dica seja de bom proveito <img src='http://leonelfraga.com/neomatrixtech/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div id="crp_related"><h3>Artigos Relacionados:</h3><ul><li><a href="http://leonelfraga.com/neomatrixtech/index.php/conciliando-janelas-modais-e-asp-net-validators/" rel="bookmark" class="crp_title">Conciliando Janelas Modais e ASP.NET Validators</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/controle-de-permissoes-utilizando-operacao-bit-a-bit/" rel="bookmark" class="crp_title">Controle de permiss&otilde;es utilizando opera&ccedil;&atilde;o bit a bit</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/fechando-uma-janela-antes-de-carreg-la-windows-forms/" rel="bookmark" class="crp_title">Fechando uma janela antes de carreg&aacute;-la (Windows Forms)</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/momento-pog-submetendo-textboxes-readonly-alterados-via-javascript/" rel="bookmark" class="crp_title">Momento POG: Submetendo Textboxes Readonly alterados via JavaScript</a></li><li><a href="http://leonelfraga.com/neomatrixtech/index.php/breakpoints-condicionais-no-visual-studio-net/" rel="bookmark" class="crp_title">Breakpoints condicionais no Visual Studio .NET</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://leonelfraga.com/neomatrixtech/index.php/rapidinha-customvalidators-no-disparam-o-servervalidate-quanto-est-vazio-veja-o-que-pode-ser-aqui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leonelfraga.com/neomatrixtech/index.php/rapidinha-customvalidators-no-disparam-o-servervalidate-quanto-est-vazio-veja-o-que-pode-ser-aqui/</feedburner:origLink></item>
	</channel>
</rss>

