Capítulo 5: Input Validation and Site Navigation Lição 2: Performing Site Navigation
Autor: quintelab | Publicado: 2011-11-04T08:43:00-07:00

Os sites devem prover aos usuários formas simples de navegação. Os desenvolvedores devem controlar como o usuário navega em seu site e até mesmo as execuções de PostBack em suas páginas. Esta lição mostra ferramentas que auxiliam nessas tarefas.

Is Page Navigation Necessary?

Navegação entre páginas é o processo de passagem de uma página para outra. Entretanto com alguns recursos que temos atualmente como Asynchronous JavaScript e XML (AJAX), você pode executar vários processos na mesma página, sem a necessidade de ficar trocando de páginas. Você não precisa mais ficar trocando de páginas para executar algo, pode fazer isso com um PostBack para o servidor ou até mesmo do lado do cliente. Claro que existem cenários que será necessário o armazenamento em banco de dados ou coisas do tipos.

Mas é importante que saiba que hoje dependendo do cenário pode fugir de metodologias antigas de navegação entre páginas para gerenciar processos.

Choosing a Method to Navigate Pages

O asp.net possui algumas maneiras de navegar entre as páginas. É bom conhecer detalhamente as diferenças entre cada maneira. Veja as opções disponíveis:
Client-side navigation: um código cliente permite que seja solicitado uma nova página. Este código solicita uma nova página com base no evento de um hyperlink ou a execução de um JavaScript;
Cross-page posting: um controle e um formulário são configurados para enviar um PostBack para uma página diferente da que faz a solicitação;
Client-side browser redirect: um código servidor, envia uma mensagem ao navegador solicitando uma página diferente;
Server-side transfer: um código servidor solicita uma transferência para uma página diferente;
Client-Side Navigation

A forma mais simples de permitir a navegação entre as páginas do seu site é utilizar um controle de Hyperlink, basta definir a propriedade NavigateUrl com o destino do link. O controle asp.net Hyperlink quando renderizado, gera o elemento html &lt;a&gt;, veja o exemplo:


HyperLink Control: Source
&lt;asp:HyperLink ID="HyperLink1"runat="server" NavigateUrl="~/NavigateTest2.aspx"&gt;Goto NavigateTest2&lt;/asp:HyperLink&gt;

HyperLink Control: Rendered HTML
&lt;a id="HyperLink1" href="NavigateTest2.aspx"&gt;Goto NavigateTest2&lt;/a&gt;

No exemplo acima quando este link for clicado o navegador requisitará a página NavigateTest2.aspx, neste caso não estamos passando nenhum informação de dados na URL, mas podemos utilizar a querystring para fornecer algumas informações caso necessário.

Outra forma de se fazer o mesmo processo é via javascript. O objeto document representa o formulário atual no javascript. Podemos definir a propriedade location para requisitar a nova página. Veja o exemplo:

&lt;input id="Button1" type="button" value="Goto NavigateTest2" onclick="return Button1_onclick()" /&gt;

Quando o botão for clicado ele irá acionar uma função javascript chamada Button1_onclick(), esta função deve ser criada dentro da tag &lt;head&gt;:

&lt;script language="javascript" type="text/javascript"&gt;
&nbsp; function Button1_onclick() {
&nbsp;&nbsp;&nbsp; document.location="NavigateTest2.aspx";
&nbsp; }
&lt;/script&gt;

Cross-Page Posting

&nbsp;Cross-Page Posting, ou postagem entra páginas é frequentamente usado em cenários onde por exemplo existem 2 páginas, a primeira com um formulário e a segunda utilizada para exibir os dados. Na primeira basta definir a propriedade PostBackUrl de um botão com o nome da segunda página, chamada de página de processamento. Esta página recebe o PostBack com os dados da primeira página para executar o processamento.


Nesta página de processamento é possível validar se ocorreu o PostBack na página anterior enviando uma coleção de dados. Através da propriedade Page.PreviousPage, você valida se ocorreu ou não o PostBack, veja o exemplo a baixo:


protected void Page_Load(object sender, EventArgs e)
{
&nbsp; if(Page.PreviousPage == null)
&nbsp; {
&nbsp;&nbsp;&nbsp; LabelData.Text = "No previous page in post";
&nbsp; }
&nbsp; else
&nbsp; {
&nbsp;&nbsp;&nbsp; LabelData.Text = Server.HtmlEncode(((TextBox)PreviousPage.FindControl("TextBox1")).Text);
&nbsp; }
}

Accessing Posted Data as Strongly Typed Data

É possível acessar propriedades com tipos definidos entre páginas, sem a necessidade de chamar o FindControl ou executar alguma conversão. Você pode criar uma propriedade pública na sua primeira página que terá seu valor acessado pela segunda página. Além de criar esta propriedade na primeira página, só é necessário adicionar a diretira PreviousPageType na segunda página, a página de processamento.

Imaginando o mesmo cenário do exemplo anterior, na primeira página chamada DataCollection.aspx temos um textbox e um botão onde sua propriedade PostBackUrl foi definida como "~/ProcessingPage.aspx". Crie a seguinte propriedade na primeira página:

public string PageData
{
&nbsp; get { return TextBox1.Text; }
}

Para ter acesso a esta propriedade na página de processamento, adicionar a diretiva PreviousPageType, como a seguir:
&nbsp;&lt;%@ PreviousPageType VirtualPath="~/ProcessingPage.aspx" %&gt;

Na página de processamento temos uma label que irá exibir a propriedade da página anterior:

protected void Page_Load(object sender, EventArgs e)
{
&nbsp; if (PreviousPage == null)
&nbsp; {
&nbsp;&nbsp;&nbsp; LabelData.Text = "No previous page in post";
&nbsp; }
&nbsp; else
&nbsp; {
&nbsp;&nbsp;&nbsp; LabelData.Text = PreviousPage.PageData;
&nbsp; }
}&nbsp;

Acessando a propriedade PreviousPage.PageData conseguirá ter acesso ao valor do textbox da página anterior. Desta forma é possível declarar outras propriedade, fugindo da necessidade de conversões ou a chamada ao FindControl.


Client-Side Browser Redirect

Este é o famoso Response.Redirect que usamos. Diversas vezes precisamos redirecionar o usuário a uma outra página com base em uma ação que ele executou no site. O objeto Page.Response contém o método Redirect que faz isso.

O Redirect é executado do lado do servidor, porém não é um PostBack, ele ocorre após o PostBack. Considere o exemplo que você possui uma página SubmitOrder.aspx que contém um botão que irá ocasionar um PostBack no servidor, após este PostBack você irá redirecionar o usuário a página OrderDetails.aspx

protected void ButtonSubmit_Click(object sender, EventArgs e)
{
&nbsp; Response.Redirect("~/OrderDetails.aspx");
}

O redirecionamento ocorre por que é enviado para o browser o código de resposta 302 junto com o novo endereço url. Assim a url do navegador é alterada e o usuário é redirecionado para a nova página. É necessário utilizar em momento certos, pois como é executado do lado do servidor, existe um "custo" para realizar esta operação.

A propriedade PreviousPage não é alimentado neste caso, para acessar dados da página anterior é necessário utilizar outras fomas como armazenar em Cookie, variáveis de Sessão ou via QueryString.

Server-Side Transfer

Você pode usar a Server.Transfer para forçar o Asp.Net a processar uma página diferente da informada na URL sem a necessidade de uma nova requisição no browser. Por exemplo, se você acessa uma página page1.aspx e nessa page1.aspx ela executa Page.Server.Transfer("page2.aspx") o Asp.Net irá processar e exibir a página page2.aspx, porém para o usário isso será invisivel e na URL do navegador continuará aparecendo page1.aspx. Exemplo de código:

protected void Button1_Click(object sender, EventArgs e)
{
&nbsp; Server.Transfer("~/OrderProcessing.aspx", false);
}

O método Transfer possui uma sobrecarga que possui um parâmetro boleano chamado preserveForm. O valor informado para este parâmetro indica se você quer manter seu formulário e os dados de query string. É possível acessar a propriedade PreviousPage durante a transferência. Se ocorrer alguma excessão na nova página que foi chamada, o processo irá retornar a página original.

Este capítulo faz questão de salientar que o uso do Server.Transfer é mais importante do que parece. Ele é útil quando você quer por exemplo navegar entre diferentes páginas no seu site, mas exibir apenas uma URL ao usuário.

O "poder" do Server.Transfer esta em você alternar suas páginas sem que o usuário veja isto.


Using the Site Map Web Server Control


Já foram explicada técnicas de como ajudar o usuário movimentado-o entre as páginas. Um quesito importante no seu website é uma estrutura sólida de navegação que auxilia e facilita o usuário na navegação em seu site. O Asp.Net possui uma forma de gerenciar sua estrutura e fornece-la ao usuário.

Você pode gerenciar e documentar a estrutura do seu site usando um site map. O site map no Asp.Net é um arquivo Xml que contém a estrutura e a hierarquia do seu site, ele é utilizado para popular controles de navegação como NavigationMenu, SiteMapPath, e TreeView.

Para adicionar um site map clique com o botão direito no seu projeto e selecione Add New Item | Site Map. Será criado um arquivo xml com a extensão .sitemap. Você adiciona nós no site map adicionando elementos &lt;siteMapNode&gt;. Cada elemento desse possui o atributo title que será exibido ao usuário, atributo url que contém a página que irá navegar e o atributo description que contém uma definição da página. Exemplo de sitemap:

&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" &gt;
&lt;siteMapNode url="~/Default.aspx" title="Home" description=""&gt;
&lt;siteMapNode url="~/Catalog.aspx" title="Our Catalog" description=""&gt;
&lt;siteMapNode url="~/ProductCategory.aspx" title="Products" description="" /&gt;
&lt;siteMapNode url="~/Product.aspx" title="View Product" description="" /&gt;
&lt;/siteMapNode&gt;
&lt;siteMapNode url="~/Cart.aspx" title="Shopping Cart" description="" /&gt;
&lt;siteMapNode url="~/Account.aspx" title="My Account" description=""&gt;
&lt;siteMapNode url="~/SignIn.aspx" title="Login" description="" /&gt;
&lt;siteMapNode url="~/PassReset.aspx" title="Reset Password" description="" /&gt;
&lt;siteMapNode url="~/AccountDetails.aspx" title="Manage Account" description=""&gt;
&lt;siteMapNode url="~/Profile.aspx" title="Account Information" description="" /&gt;
&lt;siteMapNode url="~/OrderHistory.aspx" title="My Orders" description=""&gt;
&lt;siteMapNode url="~/ViewOrder.aspx" title="View Order" description="" /&gt;
&lt;/siteMapNode&gt;
&lt;/siteMapNode&gt;
&lt;/siteMapNode&gt;
&lt;siteMapNode url="~/AboutUs.aspx" title="About Us" description="" /&gt;
&lt;siteMapNode url="~/Privacy.aspx" title="Privacy Policy" description="" /&gt;
&lt;siteMapNode url="~/ContactUs.aspx" title="Contact Us" description="" /&gt;
&lt;siteMapNode url="~/MediaKit.aspx" title="Media Relations" description="" /&gt;
&lt;/siteMapNode&gt;
&lt;/siteMap&gt;

Using the SiteMap Class

A classe SiteMap permite acessar em tempo de execução através do código de programação a hierarquia do seu site. Existem duas propriedades primárias RootNode e CurrentNode ambas retornam uma instância SiteMapNode. O objeto SiteMapNode representa um nó no seu arquivo sitemap e nele você tem acesso as propriedades antes listadas: title, url e description. Para ter acesso aos nós na hierarquia você deve utilizar as propriedades ParentNode, ChildNodes, NextSibling, e PreviousSibling na instância do SiteMapNode. O código abaixo mostra quem é o nível superior da página que esta sendo acessada:

protected void Button1_Click(object sender, EventArgs e)
{
&nbsp; Response.Redirect(SiteMap.CurrentNode.ParentNode.Url);
}

Displaying Site Map Information to Users

O sitemap é apenas um arquivo xml com informações, para exibir esses dados ao usuário são necessários controles de navegação. Esses controles de navegação podem conectar diretamente em seu arquivo site map, vou conectar no controle SiteMapDataSource.

O SiteMapDataSource é um controle simples designado a permitir que o programador acesse o arquivo site map. Este controle é usado como fonte de dados de controles de navegação. Para usar este controle basta arrasta-lo para sua página e ele automaticamente irá conectar no site map definido no seu site.

Existem dois atributos que podem ser usados para configurar o controle SiteMapDataSource. ShowStartingNode você define como false caso não queira que o usuário visualize o nós raíz do seu site. O segundo é o StartingNodeOffset, é útil quando estiver usando um controle de sub-navegação e queira mostrar apenas partes da navegação. Veja como fica o código do controle:

&lt;asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" StartingNodeOffset="0" ShowStartingNode="False" /&gt;

Assim como o site map o controle SiteMapDataSource não tem representação visual para o usuário, é necessário utilizar algum controle de navegação que faça isso. Existem três principais controle de navegação no asp.net: Menu, TreeView, e SiteMapPath.

O controle Menu como o nome ja diz é para exibir a estrutura do seu site como um menu, o usuário conseguirá navegar desde as páginas raíz até seus últimos níveis. O Menu possui várias propriedade que envolvem principalmente layout e estilo. Mas existe dois atributos que o livro foca, é o DataSourceId e Orientation. No DataSourceId você irá definir o nome do controle DataSource, você pode informar o nome do SiteMapDataSource que adicionou em sua página. Já Orientation é para definir se irá mostrar o menu de forma veritical ou horizontal. Veja o código abaixo:

&lt;asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1" MaximumDynamicDisplayLevels="5" Orientation="Horizontal"&gt;
&lt;/asp:Menu&gt;

Com base no site map que foi postado nesta lição, o resultado deste menu será:


Já o controle TreeView exibe a estrutura do site no formato de uma "árvore", onde o usuário poderá navegar entre os itens até chegar ao último nível e selecionar a página desejada, para utilizar o SiteMapDataSource como fonte de dados, deve ser feito o mesmo processo do controle Menu. Veja como fica a TreeView:


O último controle é o SiteMapPath, ele permite ao usuário saber em qual página ele esta, e quais são os níveis anteriores para chegar nesta página. Este controle cria um rastro de navegação até a página que o usuário esta utilizando. Adicionando este controle a sua página ele automaticamente irá utilizar o arquivo site map, não é necessário configurar seu DataSource como nos outros controles anteriores. Veja como fica seu resultado: