Ajax – Conhecendo seus componentes (Parte 1)

Ajax pode-se dizer que é uma revolução no conceito de aplicações pra web, essa tecnologia foi implementada nos anos 2000, e permite aperfeiçoar o trafico de dados entre um servidor web e um browser. Utiliza um protocolo XML HTTP para fazer uma comunicação assíncrona com o servidor, isso significa que, com o Ajax, apenas uma “porção” da tela será atualizada, somente o que desejar, sem a necessidade de atualizar toda a página quando quiser realizar uma ação. Com ele é possível criar aplicações muito mais leves e amigáveis, pois os PostBacks deixam de existir.
Quando se fala em Ajax, para facilitar o serviço, a Microsoft disponibiliza o ASP.NET AJAX Control Toolkit, que é composto por uma série de controles com recursos Ajax. Ao decorrer dos artigos postados neste blog, serão detalhados alguns destes controles. Neste artigo será explicado como instalar o ajaxControltoolKit, o que é e como utilizar os controles UpdatePanel e ModalPopUpExtender.
Instalando o AJAX Control Toolkit
Para instalar o AjaxControlToolKit, você pode baixá-lo em http://ajaxcontroltoolkit.codeplex.com/ e siga os passos de instalação, ou simplesmente baixar os arquivos DLL clicando aqui , e colocá-lo na pasta BIN de seu projeto.
Colocando os arquivos na pasta BIN, após criar o projeto, na página em que irá utilizar o AJAX, deve-se informar que a mesma ela irá trabalhar com o Ajax Control Toolkit, portanto deve ser feita uma chamada do mesmo antes de abrir a tag HTML, veja:
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
Repare que, foi informado o valor “cc1” para a TegPrefix, portanto toda chamada de controles do Ajax Control Toolkit na pagina será feita através desta Tag.
Para trabalhar com o Ajax, deve-se inserir na página o ScriptManager, pois este é responsável por gerenciar os PostBacks que serão realizados e transformar em requisições XML HTTP. Dentro do form, insira:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
Agora, serão detalhados alguns controles do AJAX Control Toolkit:
UpdatePanel
O controle UpdatePanel permite criar aplicações web onde seja possível atualizar apenas a área que está delimitada pelo componente, ou seja, pode-se atualizar parcialmente o site sem necessidade de carregar novamente a página usando um PostBack.
Não há limite de UpdatePanel que se pode usar em uma página, portanto, pode-se definir regiões específicas de uma página, que podem ser atualizadas sem realizar um Refresh por completo.
Propriedades do UpdatePanel
Abaixo serão citadas algumas propriedades mais usuais.
  • UpdateMode: Esta propriedade obtém ou indica quando um conteúdo dentro do UpdatePanel é atualizado;
  • ChildrenAsTriggers: Por padrão definida como True, indica quando acontece um PostBack de um UpdatePanel filho;
  • Triggers: Permite disparar uma atualização dentro do UpdatePanel, como exemplo, se faz necessário quando deseja enviar imagem para o servidor utilizando o FileUpload;
Exemplificando
Será codificada uma área que atualizará uma informação em um determinado local do site. O Exemplo a ser mostrado, é simples e intuitivo, onde o usuário clicará em um botão, e a informações que ele digitar em um Textbox será adicionado em uma Label. O detalhe é que este estará dentro de um UpdatePanel, para que, o preenchimento da Label seja realizado sem o PostBack da página.
Para isso, crie um novo projeto, e no webform, adicione o ScriptManager, pois como foi dito no artigo “CascadingDropDown passo a Passo”, este é responsável por gerenciar os PostBacks que serão feitos na página e transformar em requisições XML HTTP. Adicione também 1 Label, 1 Textbox e 1 Button, veja abaixo o código:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:Label ID="lblValor" runat="server" Text=""></asp:Label>
<br />
<asp:TextBox ID="txtValor" runat="server"></asp:TextBox>
<asp:Button ID="btnValor" runat="server" Text="Add" />
Vá a modo “Design” em seu Visual Studio e dê duplo clique sobre o botão, para que este gere automaticamente o método onclick. Neste método realize a ação de adicionar o texto informado no Textbox na Label, da seguinte maneira:
lblValor.Text = txtValor.Text;
Simples, porém quando executar, perceba que ao clicar no botão, a página é atualizada por completo, para realizar o carregamento apenas do local desejado, sem que a página realize um PostBack, coloque os componentes que deseja atualizar dentro de um UpdatePanel, veja abaixo:
<asp:UpdatePanel ID="upValor" runat="server">
<ContentTemplate>
<asp:Label ID="lblValor" runat="server" Text=""></asp:Label>
<br />
<asp:TextBox ID="txtValor" runat="server"></asp:TextBox>
<asp:Button ID="btnValor" runat="server" Text="Add"            
     OnClick="btnValor_Click" />
</ContentTemplate>
</asp:UpdatePanel>
Executando o projeto pressionando o botão “Add”, observe o comportamento da página. Perceba que usando o UpdatePanel o as ações do botão não exigem que a página atualize por completo, tornando assim a interação com o usuário mais rápida e dinâmica.
ModalPopUpExtender
Com o ModalPopUpExtender é permitido criar popups em aplicações AJAX, janelas “modais” que sobrepõe a outros controles, algo que não é possível fazer em aplicações web tradicionais, porém, utilizando-o é muito simples simular essas janelas popups através de Panel , e qualquer controle pode ser adicionado à este Panel, também é possível customizá-lo da forma desejada.
Propriedades do ModalPopUpExtender
Algumas propriedades serão descritas abaixo:
  • TargetControlID - O ID do componente que irá ativar a janela modal;
  • PopupControlID - O ID do componente que será a janela modal;
  • DropShadow - Configurado como “true” realiza um efeito de sombreamento;
  • OkControlID - O ID do componente que irá descartar a janela modal;
  • OnOkScript - Executa um script do lado do cliente, irá ocorrer quando o modal popup for indeferido com o OkControlID;
  • CancelControlID - O ID do componente que irá cancelar a janela modal;
  • OnCancelScript - Irá executar quando o modal popup for indeferido com o CancelControlID.
Exemplificando
Será criada uma página onde conterá um link, que quando clicado, irá abrir uma janela modal simples, onde conterá uma Label informativa e um botão de fechar. Exemplo criado simplesmente com objetivo de mostrar o funcionamento do ModalPopUpExtender.
Utilizando o mesmo projeto citado no exemplo acima, crie uma nova página, adicione o ScriptManager, coloque um Hyperlink na página com id “hlModal”, adicione um Panel, com id “pnlModal” (customize-o da maneira que achar melhor), dentro do Panel, adicione uma Label e um Button, com IDs “lblInfo” e “btnFechar” respectivamente, observe na Figura 1.
Figura 1 – Utilizando o ModalPopUpExtender
Próximo passo é fazer com que o “pnlModal” se torne uma janela popup , e apareça somente quando o usuário clicar sobre o Hyperlink “hlModal”, para isso basta adicionar o ModalPopupExtender na página, como mostra o código abaixo:
<ajax:ModalPopupExtender ID="mpeModal" runat="server"  
    TargetControlID="hlModal" DropShadow="true"
    OkControlID="btnFechar" PopupControlID="pnlModal"> 
</ajax:ModalPopupExtender>
Perceba que, foram configuradas as seguintes propriedades: TargetControlID, DropShadow, OkControlID e PopupControlID, de acordo com cada componente que foi adicionado na página. Compile a aplicação e perceba que inicialmente o pnlModal está invisível, e que quando clica-se sobre o link “hlModal”, o Panel aparece como um popup.
Com o texto acima descrito, pode-se perceber que, utilizando à tecnologia AJAX, as páginas Web ficaram de certa forma mais eficientes, direta e objetiva. Cria-se aplicações mais leves e amigáveis, pois o usuário não precisa aguardar a página ser recarregada a cada requisição de dados com o servidor.

Paginando dados utilizando Datalist

Utilizando o Visual Studio 2008, percebe-se que, os controles GridView, FormView e DetailsView já possuem o recurso de paginação integrado, porém, o Datalist não fornece wizards para paginação, sendo assim, a mesma deve ser criada de forma customizada utilizando o objeto PagedDataSource.
Perceba que, o exemplo que será mostrado neste artigo, permitirá uma paginação onde possui os botões “next” e “preview”, bem como os links para cada pagina criada e uma legenda informativa dizendo qual página está selecionada, veja na Figura 1 abaixo:
Figura 1 – Paginação Datalist
Figura 1 – Paginação Datalist
Confira as propriedades do PagedDataSource, perceba que existem outras propriedades como isFirstPage (ir para primeira página) e isLastPage (ir para última página).
Com o PagedDataSource, será permitido utilizá-lo em conjunto ao Datalist, Repeater, Dropdownlist, dentre outros, basta associar a ele uma fonte de dados e quantas informações por página este irá exibir, perceba pelo exemplo abaixo, utilizando um sqlDataSource:
Aspx:

<div style="float: left">
     <asp:Label ID="lblPaginasTopo" runat="server" Text="" ForeColor="Black" Font-Size="14px">         
     </asp:Label>
</div>
<div style="float: left; padding-left: 20px;">
     <asp:ImageButton ID="btnPrevTopo" runat="server" AlternateText="Voltar" OnClick="btnPrev_Click"
                    ImageUrl="~/design/bgBack.gif" Width="19px" Height="19px" />
     <asp:LinkButton ID="divLinks" runat="server" OnClick="link_Click"></asp:LinkButton>
     <asp:ImageButton ID="btnNextTopo" runat="server" AlternateText="Próximo" OnClick="btnNext_Click"
           ImageUrl="~/design/bgNext.gif" Width="19px" Height="19px" />
</div>

C#:
protected void Page_Load(object sender, EventArgs e)
  {
        GetData();
        if (!Page.IsPostBack)
        {
            GetData();
            if (ViewState["PagedDataSource"] != null)
            {
              createPaging((int)ViewState["PagedDataSource"]);
            }
        }
        else
        {
            if (ViewState["PagedDataSource"] != null)
            {
                createPaging((int)ViewState["PagedDataSource"]);
            }
        }
    }
    private void GetData()
    {
        PagedDataSource pgds = new PagedDataSource();   
pgds.AllowPaging = true;
        pgds.DataSource = sdsResultado.Select(DataSourceSelectArguments.Empty);     
        pgds.PageSize = 10;
     pgds.AllowPaging = true;
pgds.CurrentPageIndex = PaginaAtual;
       btnNextTopo.Enabled = !pgds.IsLastPage;
        btnPrevTopo.Enabled = !pgds.IsFirstPage;
      
lblPaginasTopo.Text = string.Concat("Página ", (PaginaAtual + 1).ToString(), " de ", pgds.PageCount.ToString());
        ViewState["PagedDataSource"] = pgds.PageCount;
       
dlResultado.DataSource = pgds;
        dlResultado.DataBind();
    }
    public int PaginaAtual
    {
        get
        {
            object o = this.ViewState["PaginaAtual"];
            if (o == null || (int)o < 0)
                return 0;
            else
                return (int)o;
        }
        set
        {
            this.ViewState["PaginaAtual"] = value;
        }
    }
    protected void createPaging(int pgds)
    {
        for (int i = 0; i < pgds; i++)
        {
            LinkButton link = new LinkButton();
            link.Text = (i + 1).ToString();
            link.ID = string.Concat("txt_", i.ToString());
            link.Click += new EventHandler(link_Click);
            divLinks.Controls.Add(link);
            LiteralControl space = new LiteralControl("&nbsp;");
            divLinks.Controls.Add(space);
        }
    }
    protected void link_Click(object sender, EventArgs e)
    {
        LinkButton link = (LinkButton)sender;
        PaginaAtual = Convert.ToInt32(link.Text) - 1;
        GetData();
    }
    protected void btnPrev_Click(object sender, ImageClickEventArgs e)
    {
        PaginaAtual--;
        GetData();
    }
    protected void btnNext_Click(object sender, ImageClickEventArgs e)
    {
        PaginaAtual++;
        GetData();
    }
Perceba que, na criação da página aspx, foram adicionados os seguintes componentes:


  • 1 Label - “lblPaginasTopo” , para que no método GetData(), esta receba o texto informando
    em qual página está o resultado da consulta;




  • 2 ImageButton - “btnPrevTopo” e “btnNextTopo”, sendo estes os botões de “preview”
    e “next”, que através de seus metodos de OnClick irão “navegar” pelo resultado;




  • 1 – LinkButton, “divLinks” que irá receber, através do método “createPaging” o link
    para cada página que foi encontrada de paginação.



  • Observando o método GetData(), perceba que “sdsResultado” é um sqlDataSource que contém o resultado de uma determinada consulta, e que “pgds.PageSize” irá informar quantos resultados por página serão exibidos.
    Com o texto acima, pode-se realizar uma simples, rápida e eficiente paginação de dados utilizando sqlDatasource em conjunto com Datalist.

    Team Foundation Server (TFS) – Visão Geral

    Há algum tempo, os projetos eram desenvolvidos individualmente, porém, com o passar dos anos, surgiu à necessidade de compartilhar o código fonte entre pessoas que programavam a mesma aplicação, pois, mais pessoas passaram a fazer parte dos mesmos projetos.

    Devido à necessidade citada acima, surgiram soluções de controle de código, tais como SVN, CVS, Visual Source Safe, dentre outras. Então foi criado o Team Foundation Server (TFS), que é um produto da Microsoft onde oferece controle de código, coleta de dados, relatórios e acompanhamento de projetos, sendo destinado para projetos de desenvolvimento de software colaborativo.

    O TFS é totalmente baseado em WebServices, portanto, este permite que, pessoas de qualquer lugar trabalhem no mesmo projeto ao mesmo tempo.

    Na versão 2010, a Microsoft lançou novos recursos que atendam também os desenvolvedores autônomos e pequenas empresas. Recursos que permitem o TFS ser instalado em sistemas operacionais como Windows Vista e Windows 7, sem a necessidade de ter um Windows Server instalado na máquina de desenvolvimento.

    Portanto, utilizando o Team Foundation Server, gera-se mais agilidade e confiabilidade ao desenvolver um software e permite que a aplicação seja desenvolvida por uma equipe, estando essa, em qualquer lugar do mundo.

    Como criar Url Amigável utilizando Global.asax

    Atualmente é muito comum aplicações web, que exibem suas informações dinamicamente através do uso de scripts que rodam no servidor. Imagine uma página que exiba as informações completas de uma determinada notícia, a url seria algo como: http://www.site.com/noticias.aspx?id=3,onde 3 é o código identificador da notícia.
    Isto é muito interessante, porém, normalmente encontram-se URLs grandes ou complicadas demais, difíceis de memorizar e sem significado, onde até mesmo, dificulta a indexação do site por mecanismos de busca.
    O ASP.NET 2.0 traz recursos de URL rewriting, onde permitem criar URLs amigáveis, por exemplo, pode-se permitir que o usuário acesse a notícia 3, citada no exemplo acima, da seguinte maneira : http://www.site.com/noticia,3,titulo-da-noticia ..
    O exemplo mostrado neste artigo é de simples entendimento, será criada uma simples aplicação onde possua uma página que contenha uma listagem de notícias, sendo que, quando o usuário clicar no link da notícia que deseja ler, este será redirecionado a uma página de visualização, onde mostrará o identificador desta notícia.
    Utilizando o Visual Studio 2008, crie uma página chamada Default.aspx, adicione 3 HyperLinks, identificados como: hlNoticia1, hlNoticia2 e hlNoticia 3. Defina a propriedade Text da seguinte maneira: "Título da primeira notícia", "Título da segunda notícia" e "Título da terceira notícia", respectivamente. Posicione os componentes em tela, observe na Figura 1.
    Figura 1 – HyperLinks posicionados
    Figura 1 – HyperLinks posicionados
    Em seguida, será adicionado os links para cada "notícia", imagine que, quando forem clicados, deve-se transferir através de QueryString o ID para a página Noticia.aspx, para que a notícia visualizada por completo, ou no nosso caso, exibir o identificador na página.
    Adicione o link do primeiro HyperLink da seguinte maneira : "noticias.aspx?id=1". Agora imagine uma URL, que atinja este objetivo, como exemplo, pode-se criá-la da seguinte forma: "noticia,1,titulo-da-primeira-noticia.aspx". Perceba que, neste endereço de URL, foi adicionado o "id" de valor "1" e o título da notícia, tornando assim, um endereço mais simples de se trabalhar.
    Adicione os seguintes links para os componentes:
    hlNoticia1 - noticia,1,titulo-da-primeira-noticia.aspx
    hlNoticia2 - noticia,2,titulo-da-segunda-noticia.aspx
    hlNoticia3 - noticia,3,titulo-da-terceira-noticia.aspx
    Agora, compile a aplicação, perceba que, ao clicar no link, será gerado o seguinte erro "The resource cannot be found.", pois o servidor não encontrou a página informada. Isso acontece por que o diretório informado não existe, então, para que este diretório seja funcional, deve-se criar a página Noticias.aspx, pois esta irá exibir toda a notícia detalhada.
    Após criar esta nova página da web, deve-se configurar a aplicação para que, ao clicar no hlNoticia1, seja direcionado ao endereço "noticia,1,titulo-da-primeira-noticia.aspx", e a aplicação interprete este diretório da seguinte maneira: "Noticias.aspx?id=1".
    Para exemplificar a visualização, no Page_Load da página Noticias.aspx, adicione o seguinte código:
    string id = Request.QueryString["id"];
    Response.Write("Identificador da notícia: " + id);
    Para que a aplicação interprete a url amigável e entenda que é a página Noticias.aspx, deve-se adicionar um Global.asax, como mostra a Figura 2.
    Figura 2 – Add new Global.asax
    Figura02 – Add new Global.asax
    Através do Global.asax, pode-se executar um determinado código quando a aplicação é iniciada/finalizada ou até mesmo quando qualquer página da aplicação for requisitada,
    No Global.asax, adicione o seguinte método abaixo:

    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        HttpContext incoming = HttpContext.Current;
        string oldpath = incoming.Request.Path.ToLower();
        string pageid;
        Regex regex = new Regex(@"noticia,(\S+),(\S+).aspx", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
        MatchCollection matches = regex.Matches(oldpath);
        if(matches.Count > 0)
        {
            //Extrai o id da noticia e envia para Noticias.aspx
            pageid = matches[0].Groups[1].ToString();
    incoming.RewritePath(string.Format("Noticias.aspx?id={0}&titulo={0}", pageid));
        }
    }
    Deve-se entender que, o método Application_BeginRequest é disparado cada vez que uma nova requisição é efetuada, portanto antes de a página ser carregada, este método será executado.
    Entendendo o código:
    Perceba que, inicialmente foi instanciado a variável icoming, recebendo o contexto da aplicação, em seguida duas strings foram criadas, oldpath e pageid, sendo que uma irá receber o caminho absoluto da url, e a outra receberá o id passado na URL, respectivamente.
    Foi usado o Regex com o código (@"noticia,(\S+),(\S+).aspx que é uma expressão regular. Observe que, essa expressão regular recebe a url passada, sendo que, o primeiro parâmetro contém o valor do ID da notícia e o segundo possui o título.
    Veja que, incoming.RewritePath irá redirecionar a url amigável para a página correta, passando o id e o título da mesma.
    Execute o projeto e perceba que, quando clicar sobre qualquer hyperlink q está na Default.aspx, será redirecionado para a pagina Noticias.aspx de uma forma amigável, observe a Figura 3.
    Figura 3 – Página com Url Amigável
    Figura 3 – Página com Url Amigável
    O intuito deste artigo foi apresentar como criar URLs amigáveis, tanto para o usuário quanto para os mecanismos de busca. Escreva soluções que concretizem sua necessidade, utilize a criatividade e atinja seus objetivos de forma eficaz.

    CascadingDropDown Passo a Passo

    Este artigo tem como objetivo criar um passo a passo, informando o que é, e como funciona o CascadingDropDown.
    Deve-se entender que, o CascadingDropDown é um webControl que faz parte do Atlas toolkit, onde permite a montagem de DropDowns em cascata, ou seja, o usuário seleciona uma informação na primeira dropDown para filtrar a 2a e assim por diante, em um número indeterminado de vezes.
    Para entender melhor, será mostrado um exemplo onde se realiza uma busca de um veículo, através do fabricante, modelo, ano e versão. Para isso, essas informações devem estar disponíveis em dropDowns, para que o usuário realize a filtragem, veja na Figura 1.

    Figura 1- Busca de veículo
    Antes de partir para o desenvolvimento da aplicação, primeiramente será criado o banco, para que assim, interaja-se posteriormente o mesmo com os dropDowns.
    Criando o banco

    Foi utilizado o banco SQL Server 2005 para criação da base “Mercado” e das tabelas “tbFabricante”, “tbModelo”, “tbAno” e “tbVersao”.
    Segue abaixo o script de criação:

    /*Cria Base Mercado */

    create database Mercado


    /*Cria tabela tbFabricante */

    CREATE TABLE [dbo].[tbFabricante](
          [IdFabricante] [int] IDENTITY(1,1) NOT NULL,
          [Nome] [nvarchar](50),
     CONSTRAINT [PK_tb_Fabricante] PRIMARY KEY CLUSTERED
    (
          [IdFabricante] ASC
    )WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]

    /*Cria tabela tbModelo que possui uma referência do fabricante */

    CREATE TABLE [dbo].[tbModelo](
          [IdModelo] [int] IDENTITY(1,1) NOT NULL,
          [Nome] [nvarchar](50) ,
          [IdFabricante] [int] NOT NULL,
     CONSTRAINT [PK_tbModelo] PRIMARY KEY CLUSTERED
    (
          [IdModelo] ASC
    )WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]

    GO
    ALTER TABLE [dbo].[tbModelo]  WITH CHECK ADD  CONSTRAINT [FK_Modelo_Fabricante] FOREIGN KEY([IdFabricante])
    REFERENCES [dbo].[tbFabricante] ([IdFabricante])
    GO
    ALTER TABLE [dbo].[tbModelo] CHECK CONSTRAINT [FK_Modelo_Fabricante]



    /*Cria tabela tbAno que possui uma referÊncia do modelo */

    CREATE TABLE [dbo].[tbAno](
          [IdAno] [int] IDENTITY(1,1) NOT NULL,
          [Nome] [nvarchar](50) ,
          [IdModelo] [int] NOT NULL,
     CONSTRAINT [PK_tbAno] PRIMARY KEY CLUSTERED
    (
          [IdAno] ASC
    )WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]

    GO
    ALTER TABLE [dbo].[tbAno]  WITH CHECK ADD  CONSTRAINT [FK_Ano_Modelo] FOREIGN KEY([IdModelo])
    REFERENCES [dbo].[tbModelo] ([IdModelo])
    GO
    ALTER TABLE [dbo].[tbAno] CHECK CONSTRAINT [FK_Ano_Modelo]



    /*Cria tabela tbVersao que possui uma referência do ano */

    CREATE TABLE [dbo].[tbVersao](
          [IdVersao] [int] IDENTITY(1,1) NOT NULL,
          [Nome] [nvarchar](50) ,
          [IdAno] [int] NOT NULL,
     CONSTRAINT [PK_tbVersao] PRIMARY KEY CLUSTERED
    (
          [IdVersao] ASC
    )WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]

    GO
    ALTER TABLE [dbo].[tbVersao]  WITH CHECK ADD  CONSTRAINT [FK_Versao_Ano] FOREIGN KEY([IdAno])
    REFERENCES [dbo].[tbAno] ([IdAno])
    GO
    ALTER TABLE [dbo].[tbVersao] CHECK CONSTRAINT [FK_Versao_Ano]
    Observa-se na Figura 2 que a tabela criada possui o seguinte relacionamento:

    Figura 2 – Diagrama da base Mercado
    Agora, serão inseridos alguns registros no banco recém criado, com objetivo futuro de testes. Segue script abaixo:
    /*Inserir na tbFabricante*/

    INSERT [tbFabricante] ([Nome]) VALUES ('FIAT')
    INSERT [tbFabricante] ([Nome]) VALUES ('FORD')


    /*Inserir na tbModelo com referencia ao fabricante*/

    INSERT [tbModelo] ([Nome], [IdFabricante]) VALUES ('PALIO', 1)
    INSERT [tbModelo] ([Nome], [IdFabricante]) VALUES ('UNO', 1)
    INSERT [tbModelo] ([Nome], [IdFabricante]) VALUES ('FIESTA', 2)


    /*Inserir na tbAno com referência ao modelo */


    INSERT [tbAno] ([Nome], [IdModelo]) VALUES ('2011', 1)
    INSERT [tbAno] ([Nome], [IdModelo]) VALUES ('2010', 1)
    INSERT [tbAno] ([Nome], [IdModelo]) VALUES ('2010', 2)
    INSERT [tbAno] ([Nome], [IdModelo]) VALUES ('2009', 2)
    INSERT [tbAno] ([Nome], [IdModelo]) VALUES ('2008', 3)
    INSERT [tbAno] ([Nome], [IdModelo]) VALUES ('2009', 3)


    /*Inserir na tbVersao com referência ao ano*/


    INSERT [tbVersao] ([Nome], [IdAno]) VALUES ('1.8 MPI WEEKEND 8V', 1)
    INSERT [tbVersao] ([Nome], [IdAno]) VALUES ('1.0 MPI ELX 8V', 1)
    INSERT [tbVersao] ([Nome], [IdAno]) VALUES ('1.8 MPI R 8V', 3)
    INSERT [tbVersao] ([Nome], [IdAno]) VALUES ('1.4 MPI TREKKING', 3)
    INSERT [tbVersao] ([Nome], [IdAno]) VALUES ('1.6 MPI TRAIL', 8)
    Após a criação do banco, incia-se o desenvolvimento da aplicação. Utilizando o Visual Studio 2008, crie um novo projeto denominado Mercado, em seguida adicione quatro DropDownList e quatro Label no formulário do projeto (Figura 3), renomeie-os  para “ddlFabricante”, “ddlModelo”, “ddlAno”, “ddlVersao”, conseqüentemente. Posicione-os em tela para ficar esteticamente viável (observe a Figura 4). Compile o projeto e confirme a opção Add a new Web.config.

    Figura 3 – Toolbox do Visual Studio 2005

    Figura 4 – Página em construção
    É claro que, como a aplicação está utilizando uma extensão do Ajax, deve-se ter na nossa aplicação, mais especificamente na pasta Bin, as ddls do AjaxControlToolKit, caso você não possua, clique aqui (http://ajaxcontroltoolkit.codeplex.com/releases/view/43475) para baixar.
    Agora, deve-se entender o seguinte, é claro que, pode-se popular estes dropDowns sem utilizar o CascadingDropDown, porém o foco deste artigo é ver as vantagens que este webControl proporciona.
    Toda a lógica sobre como preencher os DropDownList através de buscas no banco, ficará armazenada em um WebService. O WebService de exemplo usado neste exemplo, lê os dados a partir de uma ‘select’ SQL simples e exibe-os nos combos em questão.
    Deve-se então, criar este WebService, para isso, vá até a Solution Explorer do Visual Studio, em seguida clique com o botão direito sobre o diretório do projeto, escolha Add New Item (Figura 5). Nesta nova janela, selecione o item Web Service e renomeie-o para wsVeiculo.asmx, em seguida clique em Add ( veja na Figura 6).
    Deve-se observar que, para trabalhar com CascadingDropDown, o WebService precisa estar localizado no mesmo site que a página criada, devido a segurança contra Cross-Site Scripting existente no browser, que impedirá um script de fazer a chamada para um webService em outro domínio.

    Figura 5 – Add New Item

    Figura 6 – Add novo Web Service
    Após adicionar o WebService no projeto, vá ao Solution Explorer, em seguida acesse App_Code -> wsVeiculo.cs. Nesta classe serão configurados os métodos que irão realizar as consultas que forem necessárias à base de dados.
    Dentro do wsVeiculo.cs, apague o método HelloWorld, pois este é apenas demonstrativo.em seguida, deve-se adicionar a seguinte linha antes de publicicar a classe, pois esta, tem o objetivo de indicar que o WebService poderá ser invocado a partir de um script.
    [ScriptService]
    Póximo passo é instanciar uma string onde indicará qual conexão de banco de dados será utilizada, porém, para isso, deve-se informar para aplicação, qual servidor deseja acessar, bem como a base de dados desejada, portanto, acesse o web.config que foi criado, e configure sua connectionstring da seguinte maneira.
    <connectionStrings>
       <add name="mercadoCS" connectionString="Data Source=NOMEDOCOMPUTADOR\SQLEXPRESS;Initial Catalog=NOMEDABASE(Mercado);Integrated Security=True" providerName="System.Data.SqlClient" />
    </connectionStrings>
    Agora volte ao WebService, e instancie uma string, com o nome conString, que irá através do ConfigurationManager, receber a string de conexão informada no web.config.
    string conString = ConfigurationManager.ConnectionStrings["mercadoCS"].ToString();
    Importe a classe Configuration:
    using System.Configuration;
    Próximo passo será criar o método que será utilizado para retornar os fabricantes para o DropDownList ddlFabricante.
        [WebMethod]
        public AjaxControlToolkit.CascadingDropDownNameValue[] GetDropDownFabricante(string knownCategoryValues, string category)
        {
            SqlConnection sqlConn = new SqlConnection(conString);
            sqlConn.Open();
            SqlCommand sqlSelect = new SqlCommand("select * from tbFabricante ORDER BY Nome", sqlConn);
            sqlSelect.CommandType = System.Data.CommandType.Text;
            SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlSelect);
            DataSet myDataset = new DataSet();
            sqlAdapter.Fill(myDataset);
            sqlConn.Close();

            List<AjaxControlToolkit.CascadingDropDownNameValue> cascadingValues = new List<AjaxControlToolkit.CascadingDropDownNameValue>();

            foreach (DataRow dRow in myDataset.Tables[0].Rows)
            {
                string categoryID = dRow["IdFabricante"].ToString();
                string categoryName = dRow["Nome"].ToString();
                cascadingValues.Add(new AjaxControlToolkit.CascadingDropDownNameValue(categoryName, categoryID));
            }

            return cascadingValues.ToArray();
        }
    Este WebService criado, recebe 2 parâmetros string e retorna um parâmetro de tipo especial. É valido frisar que, AtlasControlToolkit.CascadingDropDownNameValue, é um array deste tipo . O parâmetro Category contém a informação que está sendo requisitada. Cada combo recebe um nome, uma identificação para a informação que ela representa. Pode-se utilizar somente este método para retornar para todos droDowns que for desejado, porém, será apresentado com métodos independentes para melhor entendimento.
    Para verificar se este método está funcionando corretamente em conjunto à aplicação, basta voltar para pagina Default.aspx. Trabalhando em modo Source, adicione o código abaixo antes de começar a tag HTML, pois este irá “informar” para o AjaxControlToolKit que esta página irá utilizá-lo.
    <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
    Em seguida será adicionado o ScriptManager na página, pois este é necessário quando se trabalha com Ajax, observe na Figura 7.

    Figura 7 – Add ScriptManager
    Neste momento, será configurado o webControl cascadingdropdown, adicione o seguinte código na aplicação:
    <cc1:CascadingDropDown ID="cddFabricante" runat="server" Category="IdFabricante" TargetControlID="ddlFabricante" PromptText="Selecione um Fabricante" LoadingText="carregando fabricantes…" ServicePath="wsVeiculo.asmx"                ServiceMethod="GetDropDownFabricante"></cc1:CascadingDropDown>
    Deve-se entender que, o CascadingDropDown aparece como um webControl não visual e atua como um extender. Renomei o ID para cddFabricante, veja abaixo suas propriedades:
    ·         Category - Nome da categoria representada pela DropdDownList. Em nosso exemplo, "Id" pois este é o nosso identificador (da tabela tbFabricante);
    ·         TargetControlID - Nome da DropDownList a ser identificada. Definimos o ddlFabricante;
    ·         PromptText - Texto de um item nulo que é inserido na DropDownList, por exemplo, "Selecione um Fabricante";
    ·         LoadingText  - O texto que será exibido no momento em que os dados estão sendo carregados;
    ·         ServicePath - O diretório de onde está localizado seu WebService.asmx;
    ·         ServiceMethod - Nome do método no WebService que será executado.
    Após configurar o CascadingDropDown, compile e veja se o ddlFabricante exibiu os fabricantes cadastrados, repare na Figura 8.

    Figura 8 – Seleção de um Fabricante
    Sendo exibido corretamente todos fabricantes, agora será criado o WebService do Modelo, Ano e Verão, segue abaixo, o código exemplo do método do Modelo:
        [WebMethod]
        public AjaxControlToolkit.CascadingDropDownNameValue[] GetDropDownModelo(string knownCategoryValues, string category)
        {
            int categoryID;

            StringDictionary categoryValues = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

            categoryID = Convert.ToInt32(categoryValues["IdFabricante"]);


            SqlConnection sqlConn = new SqlConnection(conString);
            sqlConn.Open();
            SqlCommand sqlSelect = new SqlCommand("select * from tbModelo WHERE IdFabricante = @IdFabricante order by Nome", sqlConn);
            sqlSelect.CommandType = System.Data.CommandType.Text;
            sqlSelect.Parameters.Add("IdFabricante", SqlDbType.Int).Value = categoryID;
            SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlSelect);
            DataSet myDataset = new DataSet();
            sqlAdapter.Fill(myDataset);
            sqlConn.Close();

            List<AjaxControlToolkit.CascadingDropDownNameValue> cascadingValues = new List<AjaxControlToolkit.CascadingDropDownNameValue>();

            foreach (DataRow dRow in myDataset.Tables[0].Rows)
            {
                string productID = dRow["IdModelo"].ToString();
                string productName = dRow["Nome"].ToString();
                cascadingValues.Add(new AjaxControlToolkit.CascadingDropDownNameValue(productName, productID));
            }

            return cascadingValues.ToArray();
        }
    Observando este método, percebem-se poucas diferenças para o GetDropDownFabricante, veja o código abaixo :
        categoryID = Convert.ToInt32(categoryValues["IdFabricante"]);
    O categoryID vai receber o valor identificador do DropDownList (no nosso caso ddlFabricante), percebam que, em categoryValues["IdFabricante"], o identificador entre as aspas é exatamente o mesmo que está na tabela tbFabricante.
    Será feita uma busca na tabela do modelo de acordo com o fabricante que foi selecionado, observe :
        sqlSelect.Parameters.Add("IdFabricante", SqlDbType.Int).Value = categoryID;
    Deve-se entender que , o retorno productId, neste método, é o identificador do modelo, vejam:
        string productID = dRow["IdModelo"].ToString();
    Segue abaixo os metodos do Ano e Versão, respectivamente:

        [WebMethod]
        public AjaxControlToolkit.CascadingDropDownNameValue[] GetDropDownAno(string knownCategoryValues, string category)
        {
            int categoryID;

            StringDictionary categoryValues = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

            categoryID = Convert.ToInt32(categoryValues["IdModelo"]);


            SqlConnection sqlConn = new SqlConnection(conString);
            sqlConn.Open();
            SqlCommand sqlSelect = new SqlCommand("select * from tbAno WHERE IdModelo = @IdModelo order by Nome Desc", sqlConn);
            sqlSelect.CommandType = System.Data.CommandType.Text;
            sqlSelect.Parameters.Add("IdModelo", SqlDbType.Int).Value = categoryID;
            SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlSelect);
            DataSet myDataset = new DataSet();
            sqlAdapter.Fill(myDataset);
            sqlConn.Close();

            List<AjaxControlToolkit.CascadingDropDownNameValue> cascadingValues = new List<AjaxControlToolkit.CascadingDropDownNameValue>();

            foreach (DataRow dRow in myDataset.Tables[0].Rows)
            {
                string productID = dRow["IdAno"].ToString();
                string productName = dRow["Nome"].ToString();
                cascadingValues.Add(new AjaxControlToolkit.CascadingDropDownNameValue(productName, productID));
            }

            return cascadingValues.ToArray();
        }



        [WebMethod]
        public AjaxControlToolkit.CascadingDropDownNameValue[] GetDropDownVersao(string knownCategoryValues, string category)
        {
            int categoryID;

            StringDictionary categoryValues = AjaxControlToolkit.CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

            categoryID = Convert.ToInt32(categoryValues["IdAno"]);


            SqlConnection sqlConn = new SqlConnection(conString);
            sqlConn.Open();
            SqlCommand sqlSelect = new SqlCommand("select * from tbVersao WHERE IdAno = @IdAno order by Nome", sqlConn);
            sqlSelect.CommandType = System.Data.CommandType.Text;
            sqlSelect.Parameters.Add("IdAno", SqlDbType.Int).Value = categoryID;
            SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlSelect);
            DataSet myDataset = new DataSet();
            sqlAdapter.Fill(myDataset);
            sqlConn.Close();

            List<AjaxControlToolkit.CascadingDropDownNameValue> cascadingValues = new List<AjaxControlToolkit.CascadingDropDownNameValue>();

            foreach (DataRow dRow in myDataset.Tables[0].Rows)
            {
                string productID = dRow["IdVersao"].ToString();
                string productName = dRow["Nome"].ToString();
                cascadingValues.Add(new AjaxControlToolkit.CascadingDropDownNameValue(productName, productID));
            }

            return cascadingValues.ToArray();
        }
    Agora que foram criados os métodos, será ativado os CascadingDropDown para o drops ddlModelo, ddlAno e ddlVersao.
    Observe que, a única propriedade diferente neste cddModelo, é a ParentControlID, que refere ao DropDownList “pai”, neste caso é o ddlFabricante.
    Modelo :
                <cc1:CascadingDropDown ID="cddModelo" runat="server" Category="IdModelo" TargetControlID="ddlModelo" PromptText="Selecione um Modelo" ParentControlID="ddlFabricante" LoadingText="carregando modelos…" ServicePath="wsVeiculo.asmx" ServiceMethod="GetDropDownModelo">
                </cc1:CascadingDropDown>
    Ano:
                <cc1:CascadingDropDown ID="cddAno" runat="server" Category="IdAno" TargetControlID="ddlAno" PromptText="Selecione um Ano" ParentControlID="ddlModelo" LoadingText="carregando anos…" ServicePath="wsVeiculo.asmx" ServiceMethod="GetDropDownAno">
                </cc1:CascadingDropDown>
    Versão:
                <cc1:CascadingDropDown ID="cddVersao" runat="server" Category="IdVersao"   TargetControlID="ddlVersao" PromptText="Selecione um Versão" ParentControlID="ddlAno" LoadingText="carregando versões…" ServicePath="wsVeiculo.asmx" ServiceMethod="GetDropDownVersao">      
                </cc1:CascadingDropDown>
    Como o estudo realizado, percebe-se que, utilizando o CascadingDropDown para realizar este tipo de filtragem, facilita a implementação do código, e gera agilidade no carregamento de informações, devido essas consultas serem feitas através de WebServices.