Enviando e-mail com Flex e .net

[Atualizado em 05/04/2010]

Quando criei esse tutorial pela primeira vez, fiz apenas a parte de envio de e-mail não expliquei como se faz a integração com a aplicação .net pois não achei necessário explicar novamente sendo que já tinha postada links a respeito. Decidi adicionar a esse artigo essa parte da integração também para que não fique muito confuso.

Utilizarei para esse tutorial: Visual Studio 2008, Adobe Flex 3 e FluorineFx.dll.

Parte 1: Criando aplicação de envio de e-mail com o Visual Studio, e preparando a aplicação .net para a integração.

1.1 – Para fazer a integração de uma aplicação .net com uma aplicação Flex, utilizaremos o framework FluorineFx que é open source. Faça o download do FluorineFx aqui, não tem mistério a instalação é o básico de sempre: “Next, Next e Finish”.

1.2 – Após instalar o FlourineFx vamos criar nossa estrutura de pastas, crie uma pasta em um diretoria qualquer chamada “FlexEnviarEmail”, dentro dessa pasta crie outras três pastas chamadas: “FlexFonte”, “AspNetFonte” e “publicado”. As pastas “FlexFonte” e “AspNetFonte” serão os diretorias das aplicações do Flex e do AspNet, a pasta “publicado” será a pasta onde publicaremos a aplicação.

Estrutura de pastas FlexEnviarEmail

1.3 – Abra o VS e vá em File > New > Web Site…, escolha a pasta que você criou chamada “AspNetFonte” e “Language” C#. Renome-e o arquivo “Default.aspx” para “Gateway.aspx”. Ainda no projeto do .net, vamos agora adicionar a referencia ao framework FluorineFx, clique com o botão direito em cima da solução e em seguida clique em “Add reference…”.

Adicionando referencia há FluorineFx .net

Se você instalou corretamente o framework FlourineFx, você vai ver na lista de referencias na aba .Net o framework.

Adicionando referencia ao FluorineFx .net

Selecione o “FlourineFx for .NET Framwork 2.0”, caso sua aplicação não tenha a pasta BIN, a mesma será criada para ser adicionada essas dll’s.

Precisamos também registrar o framework FluorineFx no web.config. Então abra o web.config e adicione o seguinte código dentro do nod “configSections”:

<sectionGroup name="fluorinefx">
        <section name="settings" type="FluorineFx.Configuration.XmlConfigurator, FluorineFx"/>
</sectionGroup>

Agora dentro do nod “httpModules”:

<httpModules>
<add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx"/>
</httpModules>

Muito bem, a parte de configuração do framework FluorineFx já está pronta, agora vamos fazer a aplicação para enviar o e-mail.

1.4 – Crie uma Classe chamada Email.cs (botão direito em cima do projeto > Add new item…), se o VS 2008 perguntar se você deseja criar a pasta App_Code e colocar a Classe dentro dela clique em sim. Adicione o código abaixo:

using FluorineFx;
using System.Net.Mail;

[RemotingService]
public class Email
{
    #region --- ATRIBUTOS ---
    private String nome;
    public String Nome
    {
        get { return nome; }
        set { nome = value; }
    }

    private String userMail;
    public String UserMail
    {
        get { return userMail; }
        set { userMail = value; }
    }

    private String assunto;
    public String Assunto
    {
        get { return assunto; }
        set { assunto = value; }
    }

    private String mensagem;
    public String Mensagem
    {
        get { return mensagem; }
        set { mensagem = value; }
    }
    #endregion

    public Email()
    { }

    #region --- MÉTODOS ---
    /// <summary>
    /// Envia o email.
    /// </summary>
    /// <returns>Retorna True caso dê tudo certo e false caso gere algum erro.</returns>
    public void EnviarEmail(Email _email)
    {
        MailMessage message = new MailMessage();
        SmtpClient client = new SmtpClient();

        //E-mail do rementente
        message.From = new MailAddress("email-remetente", "Remetente");
        message.IsBodyHtml = true;
        message.Body = "Nome: " + _email.nome + "<br />E-mail: " + _email.userMail + "<br />Assunto: " + _email.assunto + "<br />Mesagem: " + _email.mensagem;
        message.Subject = _email.assunto;
        //E-mail do destinatário
        message.To.Add(new MailAddress("email-destinatario", "Destinatário"));

        //E-mail e senha para enviar a mensagem
        client.Credentials = new System.Net.NetworkCredential("email-remetente/envio", "senha-email");
        //Número da porta:
        client.Port = 25;
        //Seu host para envio do e-mail
        client.Host = "host";

        client.Send(message);
        message.Dispose();
        message = null;
        client = null;
    }
    #endregion
}

As configurações de para envio de e-mail (host, porta, e-mail de envio e senha) são configurações de cada um, então não quer dizer, por exemplo, que a porta é a 25 como está no código acima, isso depende das suas configurações. Precisamos importar a FluorineFx para usar o “[RemoteService]”. O [RemoteService] que se encontra em cima da declaração da classe, serve para dizermos para o FluorineFx que essa classe será acessada remotamente pelo Flex. Criamos as propriedades nome, mail, assunto e mensagem, que são informações que pegaremos no formulário da aplicação Flex e enviaremos por e-mail. O método EnviarEmail recebe um parâmetro que é um objeto da própria classe Email (Isso ficara mais claro na aplicação Flex) e envia o e-mail.

1.5 – Agora configure a pasta “AspNetFonte” no IIS, para isso basta você clicar com o botão direito na pasta “AspNetFonte” e na aba “Compartilhamento web” escolher a opção “Compartilhar essa pasta”, na opção “alias” (apelido) coloque flexmail. Caso não tenha a aba “Compartilhamento web”, significa que seu IIS não está instalado, veja como você pode instalá-lo por esse tutorial (aconselho a trabalhar com o IIS), se você não tiver o IIS instalado, pode fazer o seguinte: O VS tem tipo um IIS interno para rodar as suas aplicações, então quando você roda uma aplicação pelo VS (apertando o F5, por exemplo) ele gera um número de porta aleatório e roda aplicação nesse servidor próprio, então a url fica mais ou menos algo assim: “http://localhost:3845/AspNetFonte/Gateway.aspx”, então rode sua aplicação e anote a url gerado no browser pois vamos precisar dela na aplicação Flex.

Pronto, já criamos nossa classe que enviara o e-mail, agora vamos para o Flex.

Parte 2: Criando formulário para envio de e-mail no Flex.

2.1 – Abra o Flex, vá em File > New > Flex Project e selecione a pasta FlexFonte que você criou anteriormente, coloque um nome qualquer para o projeto (no caso eu coloquei o mesmo nome da pasta) e clique em finish. Crie uma pasta dentro da pasta src com o nome de classes, agora adicionamos uma arquivo ActionScript Class com o nome de Email dentro dessa pasta (botão direito na pasta classes > new > actionscript class). Essa classe precisa ter exatamente o mesmo nome da classe na aplicação .net (no caso Email), então ela deve se chamar “Email.as”. Adicione o código abaixo nessa classe:

package classes{
	[RemoteClass(alias="Email")]
	public class Email{
		private var nome:String;
		public function get Nome():String{
			return nome;
		}
		public function set Nome(n:String):void{
			this.nome = n;
		}

		private var mail:String;
		public function get Mail():String{
			return mail;
		}
		public function set Mail(m:String):void{
			this.mail = m;
		}

		private var assunto:String;
		public function get Assunto():String{
			return assunto;
		}
		public function set Assunto(a:String):void{
			this.assunto = a;
		}

		private var mensagem:String;
		public function get Mensagem():String{
			return mensagem;
		}
		public function set Mensagem(msg:String):void{
			this.mensagem = msg;
		}

		public function Email(){
		}
	}
}

Assim como na classe da aplicação .net, no Flex também precisamos dizer qual é a classe remota que ele irá acessar, por isso inserimos o [RemoteClass(alias=”Email”)] no começo da classe. A classe “Email” que está setado no “alias=”, é a classe “Email.cs” da aplição .net. Note que até mesmo o nome das propriedades tem que ser o mesmo do que a classe “Email.cs”. O get e set do actionscript 3.0 é bem semelhando ao do .net como podemos reparar.

2.2 – Dentro do arquivo principal do Flex, adicione o código abaixo:

<mx:RemoteObject id="roMail" source="Email" destination="fluorine" showBusyCursor="true">
		<mx:method name="EnviarEmail" result="{resultadoEnviar(event)}" fault="{falhaEnviar(event)}"/>
	</mx:RemoteObject>

	<mx:VBox height="384" width="300" horizontalCenter="0" verticalCenter="0">
		<mx:TextInput id="txtNome" focusIn="removeTextoPadrao(this.txtNome)" focusOut="addTextoPadrao(this.txtNome)" text="Nome"/>
		<mx:TextInput id="txtEmail" width="280" focusIn="removeTextoPadrao(this.txtEmail)" focusOut="addTextoPadrao(this.txtEmail)" text="E-mail"/>
		<mx:ComboBox id="comboAssunto" creationComplete="preencheCombo()"></mx:ComboBox>
		<mx:TextArea width="300" height="120" id="txtMensagem" focusIn="removeTextoPadraoTextArea(this.txtMensagem)" focusOut="addTextoPadraoTextArea(this.txtMensagem)" text="Mensagem"/>
		<mx:Button label="Enviar" id="btnEnviar" click="enviarEmail(event)"/>
	</mx:VBox>

O “mx:RemoteObject” serve para se conectar remotamente com a classe “Email.cs”, especificamos qual classe ele ira se conectar através da propriedade “source”. A propriedade “showBusyCursor=true” serve para que enquanto o RemoteObject estiver sendo executado será exibido um cursor de carregando (tipo a ampulheta do windows).

Na tag mx:Method dizemos qual o método iremos usar da classe “Email.cs” pela propriedade “name” (pode se ter varias tags mx:Method para os métodos da classe), a propriedade “result” indica qual função será executada caso dê tudo certo na execução do método da classe “Email.cs”, caso dê algo errado, será executada a função que está registrada na propriedade “fault” (criaremos essas funções mais a frente). Em alguns controles pode-se observar que existem funções ligadas aos eventos focusIn (evento disparado quando o focu está no controle) e focusOut (evento disparado quando o focu sai do controle), que veremos no próximo passo.

2.3 – Crie um bloco “mx:Script” logo acima do código que você adicionou anteriormente, depois adicione esse código ao script:

import mx.rpc.remoting.mxml.RemoteObject;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
import classes.Email;
import mx.collections.ArrayCollection;

/********** EVENTOS DOS CONTROLES DO FORMULÁRIO **********/
			//Preenche o combo box com as opções de assunto
			private function preencheCombo():void{
				var lista:ArrayCollection = new ArrayCollection();
				lista.addItem("Selecione --");
				lista.addItem("Dúvida");
				lista.addItem("Sugestão");
				lista.addItem("Reclamação");
				comboAssunto.dataProvider = lista;
			}

			//Retira o texto padrão dos inputs nome e email
			private function removeTextoPadrao(t:TextInput):void{
				if (t.text == "Nome" || t.text == "E-mail")
					t.text = "";
			}

			//Adiciona o texto padrão dos inputs nome e email
			private function addTextoPadrao(t:TextInput):void{
				if (t.id == "txtNome" && t.text == "")
					t.text = "Nome";
				else if (t.id == "txtEmail" && t.text == "")
					t.text = "E-mail";
			}

			//Remove texto padrão do textarea
			private function removeTextoPadraoTextArea(ta:TextArea):void{
				if (ta.text == "Mensagem")
					ta.text = "";
			}

			//Adiciona texto padrão do textarea
			private function addTextoPadraoTextArea(ta:TextArea):void{
				if (ta.text == "")
					ta.text = "Mensagem";
			}

			//Volta com todos os textos padrões
			private function textoPadrao():void{
				txtNome.text = "Nome";
				txtEmail.text = "E-mail";
				txtMensagem.text = "Mensagem";
				comboAssunto.selectedIndex = 0;
			}

/********** FUNÇÕES DE CONECXÃO COM A APLICAÇÃO .NET **********/
			//Função que é executada se ocorreu algum erro ao enviar o e-mail
			private function falhaEnviar(evt:FaultEvent):void{
		    	Alert.show("Ocorreu o seguinte erro ao tentar executar o método:\n" + evt.fault.message, "Erro");
			}

			//Função que é executada se não ocorreu erros no envio de e-mail
			private function resultadoEnviar(evt:ResultEvent):void{
	        	textoPadrao();
	        	Alert.show("E-mail enviado com sucesso!");
		    }

			//Função que é acionado com o clique do mouse
			private function enviarEmail(evt:MouseEvent):void{
		    	if (evt.type == MouseEvent.CLICK){
		        	var email:Email = new Email;
		        	email.Nome = txtNome.text;
		        	email.Mail = txtEmail.text;
		        	email.Assunto = comboAssunto.selectedLabel;
		        	email.Mensagem = txtMensagem.text;
		        	roMail.getOperation("EnviarEmail").send(email);
		    	}
			}

A função “preencheCombo” serve para preencher o comboBox assunto, com informações de um arrayCollection. As funções que seguem abaixo da função “preencheCombo” servem somente para retirar ou adicionar texto padrão nos inputs. A função “textoPadrao” serve para retornar os textos padrões para os inputs depois que o e-mail for enviado. A função “falhaEnviar” que recebe como parâmetro um “FaultEvet” é a função que será executada caso ocorra algum erro na execução do RemoteObject, e a função “resultadoEnviar” será disparada caso ocorra tudo bem, perceba que as duas funções simplesmente executam um “Alert” informando o que aconteceu.

A função “enviarEmail” é executada quando clicamos no botão “btnEnviar” (o evento clique chama a função enviarEmail) e dentro dessa função, criamos um objeto da classe “Email.as” e preenchemos os atributos com os valores do formulário. Para executar o método que está registrado no “roMail” (id do mx:RemoteObject), executamos o “getOperation” do “roMail” e passamos como parâmetro o nome do método registrado, em seguida executamos o send(). Como já sabemos, o método “EnviarEmail” da classe “Email.cs” espera um parâmetro do tipo “Email”, então no “send()” do “getOperation” passamos o objeto da classe “Email.as” que criamos com os dados do formulário(“.send(email)”). Caso o método “EnviarEmail” da classe “Email.cs” não esperasse nenhum parâmetro, bastava executar o “send()” sem parâmetros mesmo.

Parte 3: Configurando a aplicação Flex para se conectar com a aplicação .net.

3.1 – Clique com o botão direito na pasta src e selecione File > New > File, coloque o nome do arquivo de “services-config.xml”, é com esse arquivo que faremos o mapeamento das classes ActioScript com .Net/C#. Adicione o código abaixo nesse arquivo:

<?xml version="1.0" encoding="UTF-8"?>
    <services-config>
        <services>
            <service id="remoting-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
                <destination id="fluorine">
                    <channels>
                        <channel ref="my-amf"/>
                    </channels>
                    <properties>
                        <source>*</source>
                    </properties>
                </destination>
            </service>
        </services>
        <channels>
        <channel-definition id="my-amf"
        class="mx.messaging.channels.AMFChannel">
            <endpoint uri="http://localhost/flexmail/Gateway.aspx"
            class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>
</services-config>

Se você configurou a aplicação .net no IIS, coloque a url da aplicação na opção “uri” do nod “endpoint” (como você pode observar, a url que está no código acima é uma url de uma aplicação que está configurada no IIS), caso você não esteja usando o IIS e sim o VS, então coloque a url gerada pelo VS (passo 1.5) e adicione no “uri” do nod “endpoint”. Agora clique com o botão direito em cima da aplicação Flex e clique em properties:

Na opção “Flex Compiler” adicione o texto “-services services-config.xml” no “Additional compiler arguments”:

Deixe um espaço em branco entre o “-locale en_US” e o “-services services-config.xml”. Agora já está tudo ok, já da para testar a aplicação, se você conseguiu configurar a aplicação no IIS, basta executar a aplicação no Flex e já estará tudo funcionando. Caso você tenha usado a url gerado pelo VS, você terá que executar a aplicação .net primeiro, e depois executar a aplicação Flex, é preciso fazer isso para que o VS inicie o seu servidor interno.

Parte 4: Publicando as aplicações.

4.1 – Para isso você precisara do IIS instalado, primeiro vamos publicar a aplicação .net, abra o VS e abra a aplicação que esta na pasta “AspNetFonte”, clique com o botão direito na solução e clique em “Publish Web Site”:

clique no botão “…” e selecione a pasta que você criou chamada “publicado”, deixe apenas a opção “Allow this precompiled site to be updatable” marcada e clique em ok.

Pronto, a aplicação .net está publicada, agora vamos publicar a aplicação Flex. Abra a aplicação Flex, depois abra o arquivo services-config.xml, e na opção “uri” do nod “endpoint”, deixe assim:

<endpoint uri="Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>

Isso por que toda a pasta publicado será uma aplicação, e a aplicação Flex e .net estarão na mesma pasta, então não é preciso colocar o caminho completo da aplicação. Agora selecione o projeto Flex, clique no botão superior Project > Export Release Build…:

Na opção “Browser” selecione a pasta “publicado” e clique em Finish. Agora configure a pasta “publicado” no IIS, agora é só acessar a aplicação no seu localhost e pronto.

Baixe o projeto aqui, até a próxima!

Categorias:Tutoriais Tags:, , , ,

Preenchendo ComboBox e List com dados de um banco (Flex + .net)

Nesse tutorial vou mostrar como preencher um controle ComboBox do Flex com dados de um banco, e preencher um controle List de acordo com o dado que foi selecionado no controle ComboBox. Para isso vou usar o Visual Studio 2008 com c#, Sql Server 2005 com o banco Northwind, Adobe Flex 3 e actionscript 3.0. Como citei no post anterior (Flex e .net – dicas, links e tutoriais), todos os artigos que eu escrever que terão a integração de Flex com .net, criarei com base no artigo que se encontra na minha lista de links (Flex + .net).

1 – Vamos começar criando a aplicação no Visual Studio 2008, File > New > Web Site. Coloquei o nome de “pcAspNet”, pois a aplicação que vou criar no Adobe Flex se chamará “PreencheControles”. Vamos criar uma classe chamada Selecao, dentro dela vamos importar a ddl FluorineFx para a integração das aplicações, e acima da classe Selecao colocar [RemotingService] (a estrutura da aplicação é semelhante à aplicação que se encontra no link que se está na minha lista de links, e tudo que citei anteriormente também é explicado lá).

2 – Agora vamos adicionar uma string de conexão com o banco no web.config (claro que, essa configuração é baseada no meu servidor de banco, adapte a mesma para o seu banco).

<add name="NorthwindConn" connectionString="Data Source=RICARDO-FC13DCB\SQLEXPRESS;Initial Catalog=Northwind;User ID=sa;Password=server" providerName="System.Data.SqlClient" />

3 – Agora vamos adicionar os métodos que retornaram os dados para a aplicação Flex:

public ArrayList SelecionaCategorias()
    {
        ArrayList lista = new ArrayList();
        try
        {
            SqlConnection Conn = new SqlConnection(GetConnectionString());
            Conn.Open();
            SqlCommand Comm = new SqlCommand("SELECT CategoryName FROM Categories", Conn);
            SqlDataReader Reader = Comm.ExecuteReader();
            while (Reader.Read())
            {
                lista.Add(Reader.GetValue(0).ToString());
            }
        }
        catch (Exception ex)
        { }
        return lista;
    }

    public ArrayList SelecionaProdutos(String CategoryName)
    {
        ArrayList lista = new ArrayList();
        try
        {
            SqlConnection Conn = new SqlConnection(GetConnectionString());
            Conn.Open();
            SqlCommand Comm = new SqlCommand("SELECT  P.ProductName FROM Products AS P INNER JOIN Categories AS C ON P.CategoryID = C.CategoryID WHERE (C.CategoryName = '" + CategoryName + "')", Conn);
            SqlDataReader Reader = Comm.ExecuteReader();
            while (Reader.Read())
            {
                lista.Add(Reader.GetValue(0).ToString());
            }
        }
        catch (Exception ex)
        { }
        return lista;
    }

    private String GetConnectionString()
    {
        return ConfigurationManager.ConnectionStrings["NorthwindConn"].ConnectionString;
    }

Para usar o ArrayList, precisamos importar a classe Collections (using System.Collections;).O primeiro método retorna um ArrayList contendo o nome de todas as categorias, o segundo, retorna o nome de todos os produtos de acordo com o nome de uma categoria especifica. E o terceiro serve simplesmente para retornar a string de conexão que se encontra no web.config.

4 – Agora vamos para o Adobe Flex, crie um novo projeto File > New > Flex Project, configure-o em um diretório que você queira, e coloque o nome dele de PreenchendoControles. IMPORTANTE: Após fazer toda a configuração necessário no Flex para a integração entre as aplicações (veja o link na lista de links), configure a aplicação pcAspNet no IIS e coloque o endereço da mesma no arquivo “service-config.xml”.

5 – Adicione os controles ComboBox e List no Flex, com os id’s: comboCategorias e listProdutos. Adicione também o controle RemoteObject como no código abaixo:

<mx:RemoteObject id="ro" source="Selecao"
     destination="fluorine" showBusyCursor="true">        
        <mx:method name="SelecionaCategorias"
        result="{AddCategorias(event)}" fault="{errorFault(event)}"/>
        <mx:method name="SelecionaProdutos"
        result="{AddProdutos(event)}" fault="{errorFault(event)}"/>
    </mx:RemoteObject>

    <mx:ComboBox id="comboCategorias" change="ro.SelecionaProdutos(comboCategorias.selectedLabel)" creationComplete="{ro.SelecionaCategorias()}" y="10" width="200" x="121"></mx:ComboBox>	
	<mx:List id="listaProdutos" x="329" y="9" width="200" height="150"></mx:List>

Como já sabemos, a propriedade source do RemoteObject precisa ser setada com o nome da classe que criamos no pcAspNet (Selecao), nas tag method, são configurados os métodos da classe Selecao. IMPORTANTE: No ComboBox tem um evento chamado creationComplete, esse evento é disparado assim que o ComboBox é renderizado na tela, então assim não corremos o risco de preencher os dados do ComboBox antes de ele ser criado na tela. No evento change, que o evento que é disparado toda a vez que muda a seleção no ComboBox, coloquei o método que preencherá o List com a lista de produtos toda a vez que o valor do ComboBox for alterado.

6 – Agora vamos criar o bloco de script que terá os métodos que preencheram os controles:

<mx:Script>
    <![CDATA[
        import mx.controls.Alert;
        import mx.rpc.events.ResultEvent;
        import mx.rpc.events.FaultEvent;
        import mx.collections.ArrayCollection;
        
        private function errorFault(evt:FaultEvent):void
        {
            Alert.show(evt.fault.faultString);
        }
        
        private function AddCategorias(e:ResultEvent):void
        {        	
        	var lista:ArrayCollection = e.result as ArrayCollection;
        	lista.addItemAt("Selecione --", 0);
        	comboCategorias.dataProvider = lista;        	   
        }
        
        private function AddProdutos(e:ResultEvent):void
        {
        	var lista:ArrayCollection = e.result as ArrayCollection;        	
        	listaProdutos.dataProvider = lista; 
        }

        ]]>
    </mx:Script>

Precisamos importar as classes acima para poder trabalhar. O método errorFault é chamado somente se acontece algum erro, o AddCategorias é o método que preencherá o controle ComboBox: Criamos uma variável do Tipo ArrayCollection que receberá o ArrayList do c# com os nomes das categorias, depois adicionamos um item a mais na posição “0”. E no final definimos o ArrayCollection com sendo o dataProvider do ComboBox. No AddProduto fazemos praticamente a mesma coisa, só não adicionamos nada na primeira posição.

E pronto, sem mistério, agora é só rodar a aplicação e você preencherá o List somente quando selecionar uma opção no ComboBox.

Segue o arquivo para download. Até a próxima!

Categorias:Tutoriais Tags:, , ,

Flex e .net – dicas, links e tutoriais

Fiquei muito tempo sem atualizar o blog, o motivo principal foi a falta de tempo mesmo. Alem de trabalhar com desenvolvimento web, principalmente com .net, tenho estudado muito sobre o Adobe Flex e actionscritp 3.0 e a integração deles com .net, a partir de hoje pretendo colocar tudo que eu aprender a respeito e algumas experiências que eu fizer. Nesse post irei colocar links bastante úteis que encontrei nas minhas buscas.

Links:

Twitter:

Além de vários conteúdos que eu achei na internet, estou lendo um livro que se chama: Adobe Flex 3 Treinamento Direto da Fonte (http://www.livrariasaraiva.com.br/produto/2657203/adobe-flex-3-treinamento-direto-da-fonte/?ID=BB49E13C7DA03150E30210590), é um livro muito bom, caso você realmente esteja interessando em aprender Flex, eu recomendo esse livro.

Bom, é isso, até a próxima!

Múltiplos uploads com asp.net + jquery

Pesquisando a respeito de como fazer múltiplos uploads em asp.net, me deparei com o um excelente tutorial em inglês: Upload Multiple Files in ASP.NET using jQuery, resolvi traduzi-lo e dar uma customizado em alguns detalhes.

Criei um web site no VS 2008 framework 2.0. No link do tutorial em inglês encontra-se os links necessários dos scripts e projetos, porem, basta clicar aqui e efetuar o download do meu projeto de exemplo que contem todos os arquivos necessários.

1 – Criei um novo web site: “File > New > Web Site …”, agora crie as seguintes pastas: imagens, img, js. Dentro da pasta js crie a pasta: multiple_upload (essa estrutura é opcional), deve ficar igual a imagem abaixo.

2 – Na pasta img adicione a imagem “deletar.gif”, na pasta multiple_upload adicione os arquivos “jquery-1.3.2.js” e “jquery.MultiFile.js”. Esses arquivos podem ser encontrados no projeto que disponibilizei para download.

3 – No arquivo Default.aspx adicione o código(explicarei sobre o código logo abaixo do mesmo):

<head runat="server">

    <title>Upload múltiplo | asp.net + jquery</title>

    <script src="js/multiple_upload/jquery-1.3.2.js" type="text/javascript"></script>
    <script src="js/multiple_upload/jquery.MultiFile.js" type="text/javascript"></script>

    <style type="text/css">
        .divUpload{height:150px; width:400px; padding:5px; overflow:auto; border:solid 1px #333333}
        .mensagem{margin:0px; height:22px}
    </style>

</head>
<body>
    <form id="form1" runat="server">

        <div class="divUpload">
            <asp:FileUpload ID="fileUp" runat="server" class="multi" />
        </div>

        <p class="mensagem">
            <asp:Label ID="lblMensagem" runat="server" Visible="false"></asp:Label>
        </p>

        <asp:Button ID="btnUpload" runat="server" Text="Upload todos" onclick="btnUpload_Click" />

    </form>
</body>

Não há nada d+ nesse código, no head colocamos as referencias para os scripts que estão na pasta “js/multiple_upload”, logo abaixo temos um pequeno css para o bloco de upload, dentro do body temos um FileUpload, um label para dizer ao usuário quantos arquivos foram adicionados e um botão para enviar os arquivos.

4 – Agora no arquivo Default.aspx.cs, vamos adicionar o evento click do botão e colocar dentro dele o código para o upload dos arquivos, deve ficar algo parecido com isso:

    protected void btnUpload_Click(object sender, EventArgs e)
    {
        int cont = 0;
        try
        {
            HttpFileCollection hfc = Request.Files;
            for (int i = 0; i < hfc.Count; i++)
            {
                HttpPostedFile hpf = hfc[i];
                if (hpf.ContentLength > 0)
                {
                    hpf.SaveAs(Server.MapPath("~/imagens/" + hpf.FileName));
                }
                cont++;
            }

            if (cont > 0)
            {
                lblMensagem.Visible = true;
                lblMensagem.Text = cont.ToString() + " arquivos adicionados.";
            }
        }
        catch (Exception ex)
        {
            lblMensagem.Visible = true;
            lblMensagem.Text = "Ops! Algo deu errado!";
        }
    }
 

O sistema de upload funciona da seguinte maneira, toda a vez que se busca um arquivo pelo fileupload, o javascript adiciona outro controle fileupload na tela em cima do que já existe, então temos a impressão de sempre usar o mesmo fileupload. Então usamos a classe HttpFileCollection que disponibiliza acesso, como uma coleção de ficheiros, a todos os ficheiros que são transferidos. Caso a página permita a transferência de mais de um ficheiro (recorrendo a vários controles fileupload), então esta coleção pode ser percorrida para obter informação sobre cada um dos ficheiros. Já a classe HttpFileCollection Fornece Acesso a arquivos individuais que foram carregados por um cliente. Então criei um loop para percorrer a coleção de ficheiros e adicioná-los um a um na pasta “imagens”. Usamos um contador para mostrar o resultado para o usuário.

5 – Muito bem, o sistema já está pronto, agora vamos customizar um pouco as saídas dos scripts (traduzir as mensagens de inglês para português e melhorar um pouco a exibição dos arquivos adicionados). No arquivo jquery.MultiFile.js, vá até a linha de número 295, e deixe o código assim:

//CÓDIGO NOVO
         r = $('<div style="font-size: 13px; padding: 2px; text-align: left; border-bottom: solid 1px #cccccc" class="MultiFile-label"></div>'),
         v = String(slave.value || ''/*.attr('value)*/),
         a = $('<span class="MultiFile-title" title="'+MultiFile.STRING.selected.replace('$file', v)+'">'+MultiFile.STRING.file.replace('$file', v.match(/[^\/\\]+$/gi)[0])+'</span>'),
         b = $('<span> - </span><a class="MultiFile-remove" title="Remover" href="#'+MultiFile.wrapID+'"><img alt="Remover" style="border: 0px; vertical-align: bottom" width="15" height="15" src="img/deletar.gif">'+/*Remover+MultiFile.STRING.remove+'*/'</a>');

         //CÓDIGO ANTIGO
         //r = $('<div class="MultiFile-label"></div>'),
         //v = String(slave.value || ''/*.attr('value)*/),
         //a = $('<span class="MultiFile-title" title="'+MultiFile.STRING.selected.replace('$file', v)+'">'+MultiFile.STRING.file.replace('$file', v.match(/[^\/\\]+$/gi)[0])+'</span>'),
         //b = $('<a class="MultiFile-remove" href="#'+MultiFile.wrapID+'">'+MultiFile.STRING.remove+'</a>');

        // Insert label
        MultiFile.list.append(
         //CÓDIGO NOVO
         r.append(a, ' ', b)

Agora vá na linha 497:

//CÓDIGO NOVO
		STRING: {
			remove:'x',
			denied:'You cannot select a $ext file.\nTry again...',
			file:'$file',
			selected:'Arquivo selecinado: $file',//File selected:
			duplicate:'Esse arquivo ja foi selecionado.\n$file'//This file has already been selected:
		},

		//CÓDIGO ANTIGO
		//STRING: {
			//remove:'x',
			//denied:'You cannot select a $ext file.\nTry again...',
			//file:'$file',
			//selected:'File selected: $file',
			//duplicate:'This file has already been selected:\n$file'
		//},

Observe que eu comentei os códigos originais e fiz umas modificações no html gerado pelo javascript, comente a modificação e depois tire o comentário do código antigo para ver a diferença.

Bom, é isso, até o a próxima!

Paginar um DataSource em asp.net (Paginar um Repeater em asp.net)

Existem controles que já vem com uma paginação basta apenas você habilita-la ou não, como o GridView por exemplo. Mas às vezes temos a necessidade de apenas exibir informações de um banco sem que isso afeta o layout. Por exemplo, existe um site de notícias, e esse site foi estruturado em css, o estruturador preparou a lista de notícias do site usando apenas “ul” e “li” e se você optar por usar um GridView para exibir essas notícias ira gerar um serie de erros de layout, pois o GridView gera uma tabela para exibir os dados. Para esse tipo de caso seria interessante usar o Repeater, pois o mesmo não gera nenhuma estrutura de HTML, ele apenas exibi as informações do banco e repete qualquer HTML que estiver dentro de seu “ItemTemplate”. Ou seja, você tem controle total sobre o Repeater podendo modificar sua estrutura por completo, porém, ao contrário do GridView, ele não possui uma paginação “embutida” que podemos ou não habilitar por isso é preciso criar uma paginação “Não mão”.

Para isso, usa-se o “PagedDataSource”, vamos ver como ele funciona:

Obs: Esse tutorial funciona perfeitamente tanto no framework 2.0 quanto no 3.5, no caso criei a aplicação usando o framework 2.0.

1 – Abra o VS 2008, “File > New > Web Site…”.

2 – Crie um arquivo novo chamado “noticias.aspx”.

3 – Criei um banco de dados no Access para este tutorial, faça o donwload do projeto no final do tutorial para pegar o banco. Assim que estiver com o banco, coloque-o dentro da pasta App_Data. Caso não tenha essa pasta em seu diretório, clique com o botão direito em cima da solução e “Add Asp.Net Folder > App_Data” ou simplesmente adicione uma pasta com esse nome no diretório da solução.

4 – Vamos adicionar uma string de conexão para o banco, abra o web.config e adicione o código como na imagem abaixo:

<appSettings/>
<connectionStrings>
<add name="DB" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|/TESTE.mdb;" providerName="System.Data.OleDb">
</add>
</connectionStrings>

5 – Na página Defaul.aspx coloque um link para a página de notícias, e na url do link coloque um querystring como na imagem abaixo (usaremos uma querystring para armazenar o valor da página):

<body>
<form id="form1" runat="server">
<a href="noticias.aspx?pagina=1">Notícias</a>
</form>
</body>

6 – Na página noticias.aspx usaremos uma estrutura de lista (“ul”,”li”) para exibir as notícias. Vai funcionar assim: Cada “li” conterá uma notícia, então usaremos o Repeater para buscar a notícia do banco e colocá-la dentro da “li”, o Repeater então repetirá esse processo para todas as notícias que forem selecionadas do banco. A paginação acontecerá através dos controles HyperLink que serão adicionados no final da página abaixo da lista de notícias. Então, na tela de notícias, monte a seguinte estrutura (importante: Não é possível editar o ItemTemplate do Repeater no modo “Design” do Visual Studio, apenas no modo “Source”):

<ul>

<asp:Repeater ID="rprNoticias" runat="server">
<ItemTemplate>

<li>

<b><%#Eval("TITULO")%></b>
<p><%#Eval("NOTICIA")%></p>

</li>

</ItemTemplate>
</asp:Repeater>
</ul>

<div>

<asp:HyperLink ID="linkAnterior" runat="server"><< Anterior</asp:HyperLink>&nbsp;
<asp:HyperLink ID="linkProximo" runat="server">Proximo >></asp:HyperLink>

</div>

7 – Agora vamos para a página noticias.aspx.cs, dentro do método “Page_Load” vamos primeiro verificar se há alguma querystring, fazendo assim:

protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["pagina"] != null)
 {
 }
}

8 – Para manipular um banco do tipo “Access” precisamos adicionar a seguinte referencia: “using System.Data.OleDb;” , e para usarmos o DataSet precisamos adicionar “using System.Data;”.

9 – Todos os códigos demonstrados abaixo devem estar dentro do comando “if” mostrado acima na parte 7. Agora vamos estabelecer a conexão com o banco e fazer o “select” das notícias:

OleDbConnection Connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["DB"].ConnectionString);
OleDbDataAdapter Adapter = new OleDbDataAdapter("SELECT * FROM NOTICIAS", Connection);

DataSet Ds = new DataSet();
Adapter.Fill(Ds, "NOTICIAS");

O construtor “OleDbConnection()” espera como parâmetro a string de conexão do banco. Lembra que colocamos a string de conexão no web.config? O código que está como parâmetro dentro do construtor “OleDbConnection()” retorna a string de conexão que está no web.config. Para utilizarmos o “ConfigurationManager” é preciso adicionar a referencia: “Using System.Configuration;”.

10 – Agora digite o código abaixo:

int paginaAtual = int.Parse(Request.QueryString["pagina"]);
PagedDataSource Pgds = new PagedDataSource();
Pgds.AllowPaging = true;
Pgds.CurrentPageIndex = (paginaAtual - 1);
Pgds.PageSize = 2;
Pgds.DataSource = Ds.Tables["NOTICIAS"].DefaultView;
rprNoticias.DataSource = Pgds;
rprNoticias.DataBind();

IMPORTANTE: O índice das páginas de um objeto “PagedDataSource” é semelhante a um índice de um array em C#, ou seja, a contagem começa do “0” (zero) porem na querystring desse exemplo tratamos como se a contagem começasse do “1”(um). Então para setarmos a página atual no “DataSouce” pegamos a querystring e subtraímos 1.

A variável “paginaAtual” pega a página atual que está em uma querystring. Logo abaixo, criamos o objeto “PagedDataSource” e configuramos o mesmo. Setamos o “AllowPaging” como true para que haja a paginação, “CurrentPageIndex” é onde pegamos e/ou setemos a página atual que é exibida, “PageSize” significa a quantidade de itens que serão exibidos por página, no banco de dados em anexo temos 6 notícias cadastradas, como optamos por exibir 2 por página, logo podemos supor que teremos três páginas cada uma exibindo duas notícias. Em seguida setamos o “DataSet” como sendo o “DataSource” do Repeater, em seguida fazemos um “DataBind” do Repeater para carregar as informações.

11 –Já temos nossa paginação pronta! Agora vamos criar uma pequena navegação com os dois HyperLinks que colocamos no final da página.

if (paginaAtual > 1)
{

linkAnterior.NavigateUrl = "noticias.aspx?pagina=" + (paginaAtual - 1).ToString();

}
else
{

linkAnterior.NavigateUrl = "noticias.aspx?pagina=1";

}
if (Pgds.IsLastPage)
{

linkProximo.NavigateUrl = "noticias.aspx?pagina=" + (Pgds.PageCount).ToString();

}
else
{

linkProximo.NavigateUrl = "noticias.aspx?pagina=" + (paginaAtual + 1).ToString();

}

O HyperLink: “linkAnterior” – Primeiro verificamos se já não estamos na primeira página, ou seja se a querystring “pagina” for menor ou igual a 1, significa que estamos na primeira página, então simplesmente desabilitamos o link, caso seja maior setamos o “NavigateUrl” com: (valor atual – 1).

HyperLink: “linkProximo” – Usamos o método “IsLastPage” do objeto “Pgds” que retorna true caso a página exibido seja a ultima. Sendo assim basta setarmos o “NavigateUrl” do linkProximo com sendo o total de páginas (Pgds.PageCount) a serem exibidos pelo DataSource, caso contrario (paginaAtual + 1).

Baixe aqui o projeto, e até o próximo artigo!

Categorias:Tutoriais Tags:,

Reescrever url em asp.net (url amigável em asp.net)

Explicarei aqui uma maneira bem simples de se reescrever uma url também conhecidas como “Url’s amigáveis”. Existem inúmeras vantagens para se reescrever a url uma delas é que os buscadores, como o google, tem dificuldade de entender querystrings como “?” ou “&”, outra seria a legibilidade para o usuário que em vez de ter que memorizar alguma coisa como: “noticias.aspx?id=50&c=esporte&x=10…” vai lidar com algo como: “noticias/50/esporte/nome_da_noticia.aspx”.

1 – Estarei usando o Visual Studio 2008 porém a aplicação funcionará perfeitamente no VS 2005 e no framework 2.0. Abra o VS 2008, vá em File > New > Web Site. Escolha a linguagem C# dê um nome qualquer ao projeto e clique em “Ok”.

2 – Agora clique com o botão em cima do projeto e clique em “Add new item…”, escolha o tipo “Web Form” e de o nome de “produtos.aspx”.

3 – Abra o arquivo “Deafult.aspx” que é criado junto com o projeto e coloque o código abaixo nele:

<a href="produtos/camisas.aspx">Camisas</a><br />
<a href="produtos/calcados.aspx">Calçados</a><br />
<a href="produtos/bermudas.aspx">Bermudas</a><br />

4 – Agora abra o arquivo “produtos.aspx” crie um “label” e coloque o código abaixo no “produtos.aspx.cs”:

produtos.aspx.cs

protected void Page_Load(object sender, EventArgs e)
 {
 if (Request.QueryString["categoria"] != null)
 {
 lblCategoria.Text = Request.QueryString["categoria"];
 }
}

produtos.aspx

<asp:Label ID="lblCategoria" runat="server" Text="Label"></asp:Label>

5 – Agora clique novamente com o botão direito em cima do projeto e escolha a opção “Add new item…”, adicione um arquivo do tipo “Global Application Class”, deixe o nome como “Global.asax” mesmo, esse é um arquivo de configurações e pode apenas ter um por projeto. Abra o mesmo e coloque esse código dentro:

void Application_BeginRequest(object Sender, EventArgs e)
 {
 string originalPath = Request.Url.ToString();

 if (originalPath.Contains("produtos/camisas.aspx"))
 {
 Context.RewritePath("~/produtos.aspx?categoria=camisas");
 }
 else if (originalPath.Contains("produtos/calcados.aspx"))
 {
 Context.RewritePath("~/produtos.aspx?categoria=calcados");
 }
 else if (originalPath.Contains("produtos/bermudas.aspx"))
 {
 Context.RewritePath("~/produtos.aspx?categoria=bermudas");
 }
 }

6 – O Evento “Application_BeginRequest” é o primeiro evento a ser executado em sua aplicação, se você colocar um botão por exemplo e clicar nele, antes de qualquer coisa sua aplicação vai passar por esse evento e depois pelos outros eventos, é nele que colocamos a lógica para reescrever a url.

Clique aqui para baixar o projeto, até a próxima!

Categorias:Tutoriais Tags:, ,