terça-feira, 4 de dezembro de 2012

Visual Studio 2012 - Como desabilitar Single-Click open

Hoje instalei o Visual Studio 2012 Express Web e algo que já me irritava nas versões de testes continuou nesta versão.

O simples fato de clicar em um arquivo abre ele em modo "preview". Eu particularmente não gosto de ter muitos arquivos abertos no visual studio e só o fato de um clique simples abrir um arquivo não me agrada.

Dei uma pesquisada nos menus aqui e achei a solução. Vá em TOOLS (isso mesmo, agora os menus do visual studio vem em caixa alta), Options. Após abrir a janela clique na primeira opção Environment em seguida em Tabs and Windows e desmarque a opção Solution Explorer (Alt+click to avoid previewing) que esta dentro do groupbox Preview Tab.

Pronto, resolvido. =)

Abraços...

segunda-feira, 3 de dezembro de 2012

MySql no Windows 8

Espero voltar a escrever com um pouco mais de frequência por aqui.

Já estou usando o windows 8 que por sinal muito bom. E hoje quando fui instalar o mysql tive alguns problemas. Pesquisando achei a solução no blog websolute.

Vou compartilhar aqui o link deles e espero que seja útil pra bastante pessoas.

MySql no Windows 8 - Solução
http://blog.websolute.com.br/mysql-no-windows-8-solucao/

segunda-feira, 30 de janeiro de 2012

Capítulo 6: Globalization and Accessibility Lição 1: Configuring Globalization and Localization

A maioria dos sites são desenvolvidos para uma só língua e cultura, entretanto o site pode ser acessado por pessoas em diversos países que falam diferentes línguas. Os desenvolvedores igoram esta larga audiência. O asp.net permite você desenvolver de forma que consiga atingir essas pessoas, salvando os textos dos seus sites em arquivos de recursos, separando por língua ou cultura.

Será criado um arquivo de recurso para cada linguagem que seu site irá suportar, no momento em que o usuário acessar o site, o asp.net irá verificar através da requisição do usuário qual sua língua e escolher o arquivo de recurso ideal para o usuário, caso seu site não suporte a cultura do usuário, será escolhido um arquivo de recurso padrão para fornecer o resultado.

Outro ponto importante é acessibilidade. Isso significa que seu site suporta diferentes tipos de visualização e entrada de dispositivos. Utilizando os recursos da acessibilidade todos os usuários irão se beneficiar ao acessar seu site.

O asp.net possui importantes ferramentas para conseguir atingir seus objetivos tanto com globalização e acessibilidade.

Lesson 1: Configuring Globalization and Localization

Existem aplicações web seja de intranet, seja aplicativos de multinacionais que necessitam atingir um público alvo amplo de diferentes países. Para esses casos o asp.net disponibiliza ferramentas para que seu site se adeque a língua e cultura do usuário que esta acessando.


About ASP.NET Resources


Para exibir uma página asp.net que suporte diferentes linguagens, você pode solicitar a língua que o usuário utiliza e escrever linhas de códigos para modificar todo seu texto, porém isto será custoso e complexo e irá requerer que uma pessoa que não seja desenvolvedora mexa no seu código. Claro que esta não é a melhor solução. Você pode externaliza seu texto, ou seja, deixa-lo separado do seu código fonte, e decidir em tempo de execução qual texto é o mais apropriado para ser exibido.


O Asp.net utiliza arquivos de recursos que suportam múltiplas linguagens. Um arquivo de recurso contém uma lingua especifica para ser exibida em uma página ou site. Sua página irá exibir o arquivo de recurso baseado na requisição do usuário, utilizando definições de sua máquina ou configurações do navegador.


Existem dois tipos de arquivos de recursos no asp.net: Local e Global. Arquivos Locais são especificos para uma página. Arquivos Globais são compartilhados por todo o site.


Using Local Resource Files


Um arquivo de recurso local é especifico para uma página web. Arquivos de Recursos locais devem ser armazenados dentro de uma pasta especial chamada App_LocalResources. Esta pasta pode estar na raíz ou dentro de outras pastas do seu projeto. Caso seu site contenha várias páginas, o ideal é criar uma sub-pasta App_LocalResources dentro de cada pasta.

Como o arquivo local é especifico para uma página você deve nomeá-lo com o nome da página mais a extensão .resx. Por exemplo se você tiver a página Home.aspx o arquivo de recurso padrão deve ter o nome Home.aspx.resx. Este será o arquivo padrão, caso seu site não possua a linguagem requisitada pelo usuário este arquivo será utilizado.

Você deve criar um arquivo específico para cada linguagem que seu site irá suportar. O nome desse arquivo deve ser o nome do arquivo padrão mais a informação da linguagem específica. Por exemplo, se você criar um arquivo para a linguagem abranger o espanhol, o arquivo de recurso da página Default.aspx deve ser Default.aspx.es.resx onde "es" é abreviação de Spanish. Se for criar para o alemão, deve ser, Default.aspx.de.resx onde "de" representa German.

Culture-Specific Local Resources

No desenvolvimento asp.net o termo culture (cultura) refere-se a linguagens regionais e diferenças de formatos. Exemplo, o Inglês falado nos Estados Unidos, é diferente do Inglês falado na Inglaterra e na Austrália ou outras partes do mundo. Cada país ou região pode ter um padrão diferente de formato de moeda, data ou número. Nos Estados Unidos por exemplo o número é formatado da seguinte forma: 12,345.67, já em algumas partes da Europa a vírgula e o ponto são invertidos: 12.345,67.

Quando uma requisição de cultura específica for feita o FrameWork irá ajustar conforme a necessidade. Você só precisa criar arquivos de recursos específicos.

Para atender diferentes culturas, como por exemplo ter textos diferentes para o Espanhol falado na Espanha e o Espanhol falado no México, basta criar o arquivo com o seguinte formato: PageName.aspx.languageId-cultureId.resx.

Exemplo, caso queria ter um texto diferenciado para o Espanhol falado no México (mx) precisa criar um arquivo: Home.aspx.es-mx.resx; Já para o Espanhol falado no restante do mundo basta: Home.aspx.es.resx.

Examining the Contents of a Resource File

O arquivo de recurso no Asp.Net é um arquivo xml com um conjunto de pares com chave e valor. A chave é única e é usada para definir e referenciar o resource. Já o valor (claro) é o valor retornado pela chave. O seguinte código é um exemplo de um chave em um arquivo de recurso:

<data name="PageResource1.Title" xml:space="preserve">
  <value>Customer Lookup</value>
</data>


Neste exemplo observe que a chave é PageResource1.Title e o valor é Customer Lookup.
O Visual Studio possui uma ferramenta própria para edição, porém caso precise ou queria pode editar seu arquivo de recurso através de algum editor Xml.

Generating Local Resources

Você pode utilizar o Visual Studio para gerar automaticamente um arquivo de recurso local para sua página. Este procedimento irá exportar para o arquivo as propriedades baseadas em textos dos controles dessa página. Para executar este procedimento, siga os passsos:
  • Abra sua página no Visual Studio;
  • Vá até o menu Tools-Generate Local Resource.
O Visual Studio irá fazer:
  • Criar a pasta App_LocalResources se for necessário;
  • Gerar um arquivo baseado em Xml, que será seu arquivo local de recursos. Ele irá conter as propriedades de sua página e de seus controles, propriedades como Text, ToolTip, Title e Caption).
Veja a imagem de exemplo, uma página que possui um TextBox, um Calendar e controles Button. Repare no menu:


Depois de clicar na opção. O Visual Studio irá gerar um arquivo de recurso com as propriedades exportadas de sua página e controles. Este arquivo irá ser nomeado com o nome de sua página mais a extensão .resx.

Observe na próxima figura o arquivo gerado, repare que foram exportadas as propriedades com seus valores que estavam informados.


Localizing Text Outside of Controls

Lembre-se que o Visual Studio não gera recursos para todo o texto de sua página, ele apenas irá gerar para os controles que possuem a propriedade Text. Verifique pela figura anterior que vários itens de texto não foram exportados para o arquivo de recurso, isto é por que as propriedades não estavam preenchidas. Esta é a única preocupação que precisa ter quando for criar seus arquivos de recursos.

Se você possui textos em sua página que necessitam utilizar recursos de localização, é melhor utilizar algum controle que exiba este texto do que utilizar apenas marcadores html. O ASP.NET possui te da duas opções de controles para esta tarefa. O primeiro é o controle <asp:Localize>. Este controle não irá gerar nenhum código na sua página quando exibida, ele só trabalha para localizar textos que estão fora de controles. Outro controle que pode ser usado é o <asp:Label> que trabalha de forma parecida. Veja como fica o código do controle <asp:Localize>


<asp:Localize ID="LabelTitle" runat="server" Text="Customer Lookup" meta:resourcekey="LabelTitleResource1"></asp:Localize>


Attaching Controls and Resources Implicitly


Quando o Visual studio gera o arquivo de resource, ele automaticamente altera o código aspx adicionando a meta:resourcekey como atributos ao controle específico. Em tempo de execução o ASP.NET procura um valor para este item no arquivo de recurso com base nessa chave.


Isto é uma localização implícita, utilizando o padrão Key.Property onde o é definido que a chave é o nome do controle e a propriedade é a propriedade do controle como ButtonFind.Text ou ButtonFindResource1.Text.


O código a seguir mostra um exemplo no botão Find, após sua propriedade Text ser exteriorizada em um recurso implicito.



<asp:Button ID="ButtonFind" runat="server" Text="Find" CssClass="submitButton" meta:resourcekey="ButtonFindResource1" />


O ASP.NET irá utilizar a chave meta:resourcekey para procurar no arquivo de recurso a mesma chave para substituir o valor da propriedade Text do botão.


Você pode usar este mesmo método de nomenclatura quando utilizar arquivo de recursos e fazer todo o processo manualmente. Isso é importante porque muitas vezes você irá adicionar ou mudar um controle de uma página após ter gerado o arquivo de recurso. E o Visual Studio não irá tentar manter em sincronia o arquivo de recurso. Portanto é importante você gerar seus arquivos de recursos com base em um dos passos anteriores.


Attaching Controls and Resources Explicitly

O modelo implícito discutido anteriormente trabalha monta a combinação dos valores da propriedade com o recurso automaticamente com base na convenção (Key.Property). Mas existe a opção de fazer esta combinação explicitamente. O código a seguir mostra como fica para definir a propriedade Text com um valor vindo de um recurso.

<asp:Button ID="ButtonFind" runat="server" CssClass="submitButton" Text="<%$ Resources:, ButtonFindResource1.Text %>" />


Quando optar pela foma explícita você sempre precisará informar qual a chave do recurso corresponde a propriedade do controle. Portanto, basta criar seu arquivo de recurso, adicionar o recurso e associar a seu controle.

Creating Language-Specific Local Resources

Quando pretende utilizar diversas linguagens e culturas em seu site, o primeiro passo é criar o arquivo de recurso padrão. Para criar o arquivo de recurso para outros idiomas, você deve copiar seguir os seguintes passsos:

1º No Solution Explorer, clique em Copiar no arquivo padrão.
2º Vá na pasta App_LocalResources e clique em Colar.
3º Renomeie seu novo arquivo incluindo a linguagem e a cultura antes da extensão do arquivo. Por exemplo para um arquivo que irá dar suporte ao Francês, o nome do arquivo deve ficar: CustomerLookup.aspx.fr.resx onde fr é a abreviação para Francês.
4º De um cliquei duplo no arquivo e altere os valores dos recursos para os valores correspondentes a linguagem.

Você deve repetir esses passos para criar o arquivo para suportar outras linguagens.

Testing Resource Files for Other Cultures

Para executar testes em seu aplicativo utilizando outras linguagens, basta alterar a linguagem padrão de sua máquina, mudando esta propriedade automaticamente quando acessar seu site o navegador irá verificar esta propriedade e enviar para o ASP.Net.

Using Global Resources

Um recurso Global é utilizado quando você precisa que este recurso seja lido por várias páginas do seu site. Um recurso Global não é utilizado para uma página específica.

Ele segue praticamente as mesas regras dos recursos locais, ele é um arquivo .resx. Você precisa criar um arquivo padrão e arquivos para as linguagens que pretende dar suporte e manter a mesma regra referente aos nomes dos arquivos. Entretanto, um arquivo de recurso Global fica salvo na pasta App_GlobalResources na raíz da aplicação. O ASP.NET sempre irá gerar objetos que facilitam a utilização desses recursos de forma simples. Uma diferença é que os recursos globais só podem ser usados explicitamente e nunca implicitamente.

Creating Global Resources

Para criar um recurso global você deve iniciar criando o arquivo e armazenando na pasta App_GlobalResources. Neste arquivo você deve preencher todo recurso que será compartilhado entre as páginas. Para criar um arquivo de recurso global, siga os passos:
  1. Clique com o botão direito na Solution Explorer. Selecione, Add ASP.NET Folder e em seguida App_GlobalResources. Ele irá criar a pasta na raíz do seu projeto.
  2. Clique com o botão direito na pasta App_GlobalResources e selecione Add New Item.
  3. Na caixa de diálogo que abrir, selecione Resource File. Defina um nome para seu arquivo seguida da extensão .resx.
Do passo anterior em diante, segue o mesmo padrão do arquivo local. Você deve abrir o arquivo para criar seus recursos. E este será seu arquivo padrão, você deve criar outros arquivos para dar suporte as cultuas que deseja.

Attaching Control Properties to Global Resources

Após criar o arquivo de recurso Global, você pode associar explicitamente as propriedades dos controles aos recursos. No caso do recurso global, se você possuir uma Label que exibe uma mensagem de saudação em todas páginas, basta você criar este recurso uma única vez e utilizá-lo em todas as páginas.

Para associar as propriedade dos controles ao recurso no modo de design, você pode usar a propriedade Expressions. Veja como:
  • Abre a página no modo de design do Visual Studio e abra a aba propriedades de um controle;
  • Selecione a propriedade Expressions que está na categoria Data. Clique no botão com 3 pontos (...) para abrir a caixa de diálogo.
  • Selecione a propriedade que deseja associar ao recurso;
  • Na lista de tipo de expressão, selecione Resources;
  • Na chave ResourceKey selecione a propriedade correspondente e clique em OK, veja na imagem:


Esses passos farão que o Visual Studio mostre o valor do recurso padrão no modo de design e quando a página for aberta pelo usuário irá mostrar conforme as definições dele. No código aspx o visual studio cria o código necessário para fazer esta ligação explicita com o recurso, veja como fica:

<asp:Label ID="LocalizeWelcome" Text="<%$ Resources:SharedLocalizedText, WelcomeString %>" runat="server"></asp:Label>

Accessing Resource Values Programmatically

O ASP.NET cria objetos que permite que você acesse os recursos através da programação, usando a sintaxe Resources.ResourceFilename.Resource. Esta é uma classe fortemente tipada do objeto  Resources.Resource para cada arquivo de recurso global. Esta classe é criada com base no nome do arquivo menos sua extensão.

Cada recurso se torna um membro da classe. Por exemplo para acessar o recurso WelcomeString que esta dentro do arquivo SharedLocalizedText você programar da seguinte forma:

LabelLocalizedWelcome.Text = Resources.SharedLocalizedText.WelcomeString;

O código anterior é quando você já possui seu arquivo criado em modo de design, quando você cria este arquivo em tempo de execução você pode acessá-lo através dos métodos GetLocalResourceObject e GetGlobalResourceObject. Veja como fica:

Button1.Text = GetLocalResourceObject("Button1.Text").ToString();
Image1.ImageUrl = (String)GetGlobalResourceObject("WebResourcesGlobal", "LogoUrl");

HTML Layout Best Practices

Globalização pode ser simples como substituir um texto pelo texto da outra linguagem, formatando os números e símbolos. Entretanto algumas línguas como a língua Árabe requer um layout diferente pois os textos são da direita pra esquerda. Quando quiser permitir que seu site de suporte a linguagens de culturas variadas, siga as seguintes diretrizes:
  • Evite utilizar posicionamento absoluto e tamanhos definidos para os controles: ao invés de definir os tamanhos em pixels nos controles, deixe que o navegador controle isso, para fazer isso não utilize posição absoluta nem tamanhos fixos.
  • Utilize a altura e largura dos formulários: devido essas línguas terem mais ou menos letras para escrever uma palavra ou frase, você não deve definir em pixels os tamanhos dos controles, utiliza porcentagem. Ex.: <table width="100%">
  • Defina os tamanhos dos controle em relação ao tamanho total do formulário: Quando precisar definir o tamanho de um controle utilize tamanhos proporcionais ao formulário. Você pode fazer isso utilizando expressões de folha de estilo. Ex.:  <div style='height: expression(document.body.clientHeight / 2); width: expression(document.body.clientWidth / 2); '>
  • Utilize células para cada controles: isso irá permitir que o texto seja moldado e garante o alinhamento entre as colunas mesmo com diferentes línguas.
  • Evite utilizar a propriedade NoWrap nas tabelas: não permita a quebra de linha, pois isso pode funcionar na língua nativa, mas não em outras línguas.
  • Evite especificar a propriedade Align nas tabelas: definindo um alinhamento da esquerda pra direita poderá substituir o layout em culturas que utilizam o texto da direita pra esquerda.
  • Desassocie controles RadioButton e CheckBox do texto: separando o texto em células separadas do controle permite que o texto seja moldado quando for necessário um texto maior quando for traduzido.
Em resumo quanto menos deixar fixo os tamanhos dos controles de sua página, mais fácil ficará adaptar para outras línguas, pois quem ficará responsável por esta tarefa é o navegador.

Setting the Culture

Normalmente utiliza-se as preferências do usuário que esta definida nas configurações do browser. Porém é interessante permitir ao usuário que modifique esta opção manualmente. Pode acontecer de um turista estar utilizando um computador público em outro país e prefere ver o site na língua nativa dele.

Você deve exibir para ele uma forma de trocar a língua. Quando o usuário mudar esta configuração você deve salvar em um cookie, sessão ou algo similar.

Nas páginas ASP.NET existem 2 propriedades para definir a linguagem e a cultura:
  • Culture: este objeto determina os resultados de funções que são dependentes da cultura, como formatações de data, moeda e número. Definindo uma cultura específica, você define tanto a linguagem como a formatação regional, tais como es-MX ou fr-FR. Você não pode definir objetos de cultura neutra que define apenas a linguagem, tais como es ou fr.
  • UICulture: esta propriedade determina os recursos globais e locais que serão carregados. Nesta propriedade você pode definir culturas neutras.
Você define as propriedade Culture UICulture sobrescrevendo o métodInitializeCulture da página. O código a seguir mostra como definir essas propriedades com o valor vindo de um dropdownlist.


protected override void InitializeCulture()
{
  if (Request.Form["DropDownList1"] != null)
  {
    //define the language
    UICulture = Request.Form["DropDownList1"];
    //define the formatting (requires a specific culture)
    Culture = Request.Form["DropDownList1"];
  }
  base.InitializeCulture();
}

O correto é você fornecer ao usuário uma lista das linguagens que você suporta em seu site. Porém você tem a opção de recuperar todas as culturas disponíveis chamando o método System.Globalization.CultureInfo.GetCultures. Este método retorna um Enumerador do tipo CultureTypes que especifica um subconjunto de culturas disponíveis. Os valores mais utilizados são:
  • AllCultures: esta lista todas as culturas disponíveis no framework, tanto culturas específicas como neutras.
  • NeutralCultures: fornece somente a língua e não configurações regionais.
  • SpecificCultures: fornece tanto a língua como definições de configurações regionais.
Setting Culture Declaratively at the Page or Site Level

Você pode definir a cultura tanto do website como somente de uma página. Para definir a cultura do website, adicione a seção <globalization> no arquivo web.config. Em seguida defina os atributos UICulture e Culture. Veja como:


<globalization uiculture="es" culture="es-MX" />


Para definir estes atributos somente para uma página você deve utilizar na diretiva @Page.


<%@ Page uiculture="es" culture="es-MX" %>


Por padrão os valores atribuidos a essas propriedades é auto.

segunda-feira, 28 de novembro de 2011

Capítulo 5: Input Validation and Site Navigation Lição 3: Using Web Parts

Muitos sites hoje possuem uma coleção de componentes que funcionam sozinhos e são auto-suficientes. Por exemplo, é padrão os sites serem divididos por uma barra lateral de navegação, uma barra no topo com o título, uma barra de rodapé, e uma área com notícias. Além disso muitos portais fornecem hoje componentes e relatórios como exemplo sobre o clima ou cotações financeiras.

ASP.NET Web Parts permite ao desenvolvedor criar estes controles. Com estes controles o usuário do site pode escolher se quer visualizar um relatório na tela, ou tem a opção de remover este controle e adicionar outro de informação do clima. Você pode fornecer ao usuário do site uma coleção de controles, para ele definir qual informação ele quer exibir na página que ele esta visualizando.

What Are Web Parts?

Web Part são componentes pré-definidos com funcionalidades que podem ser adicionados no site. Eles possuem uma estrutura definida, gerenciável e um modelo customizado. Alguns desses componentes podem ser movidos dentro do site para ser posicionado conforme a necessidade do usuário. A figura abaixo mostra um controle Web Part sendo posicionado pelo usário.


Você pode utilizar o controle CatalogZone para adicionar um catalogo de controles em sua página, onde o usuário pode adicionar e/ou remover controles Web Part das regiões pré-definidas. A figura abaixo exibe este cenário onde o usuário visualiza uma lista de controles que ele pode adicionar ou remover de sua página.


Páginas de Web Part podem oferecer ao usuário diversas opções de personalização, isso é ótimo quando você desenvolve funcionalidades que abrangem um público amplo. Veja alguns Web Parts comuns que você pode criar:
  • Uma lista de artigos e notícias
  • Um calendário com os eventos
  • Uma lista de WebSites
  • Uma caixa de pesquisa
  • Controles de Navegação
  • Blog
  • Leitores de RSS, etc...
Qualquer controle seja padrão ou controle personalizado pode se tornar um Web Part, e não necessariamente terá que escrever diversas linhas de código, pois o Visual Studio auxilia nesta tarefa.

The WebParts Namespace

O Asp.Net possui vários Web Parts, são 13 os controles disponíveis na ToolBox do Visual Studio. Esses controles e classes podem ser encontrados dentro da Namespace System.Web.UI.WebControls.WebParts. Algumas dessas classes serão discutidas mais profundamente em lições posteriores. A lista a seguir contém as classes mais importantes:
  • WebPartManager: O controle WebPartManager é necessário em todas as páginas que inclui Web Parts. Ele não tem uma representação visual. Em vez disso, ele gerencia todos os controles de Web Parts e seus eventos na página especificada.
  • CatalogPart: O controle CatalogPart fornece a interface de usuário para gerenciar um grupo de Web Parts que podem ser adicionados a uma página de Web Parts. Este grupo é normalmente todo o site (e não apenas específicos para uma determinada página).
  • PageCatalogPart: O controle PageCatalogPart é semelhante ao controle CatalogPart. No entanto PageCatalogPart são apenas grupos dentro de uma página. Se um usuário fechar uma Web Parte ele pode utilizar o PageCatalogPart para adicionar a Web Parte novamente a página.
  • EditorPart: O controle EditorPart permite aos usuários definir personalizações, como a modificação de propriedades de uma Web Part especifica.
  • DeclarativeCatalogPart: Este controle permite você declarar quais controles Web Parte estão disponíveis para adicionar no site.
  • WebPartZone: Controle utilizado para definir regiões que os controles Web Part podem ser hospedados.
  • EditorZone: Controle que definir a região na página onde pode existir os controles EditorPart.
  • CatalogZone: Defini uma região onde pode existir um controle CatalogPart.
Defining Web Part Zones

Você adiciona Web Parts na página colocando-as em zonas. As Zonas definem a área na página onde o usuário ou o desenvolvedor podem adicionar Web Parts. As zonas possuem as propriedades width, height e um local na página. É possível adicionar uma, nenhuma ou várias Web Parts dentro de uma zona. Veja a figura abaixo:


As zonas permitem definir estilos que serão aplicados a todos Web Parts que estiverem dentro dela. Isto é chamado de Web Part’s chrome. O chrome (cromo) inclui estilos de cabeçalho, estilos de menu, definições de borda e outros. As Web Parts que existiverem dentro de uma zona que teve seu chrome definido irá receber os mesmos estilos.

Você cria zonas de Web Parts com o controle WebPartZone. Este controle define a área onde podem ficar Web Parts, este controle também possui a propriedade HeaderText. Nesta propriedade irá o texto que será exibido ao usuário quando a página e a zona estiverem em modo de edição.

Para definir uma zona, você deve adicionar o controle WebPartZone em sua página, para adicionar controles a esta zona, primeiramente você deve adicionar o controle ZoneTemplate dentro de sua WebPartZone, e dentro deo ZoneTemplate você adiciona os demais controles e combinações de sua Web Part. Veja o código:

<asp:WebPartManager ID="WebPartManager1" runat="server">
</asp:WebPartManager>


<asp:WebPartZone ID="WebPartZoneVendor" runat="server" HeaderText="Vendor Aggregate" style="width: 650px; height: auto">
  <ZoneTemplate>

    <!--Add content to the zone-->

  </ZoneTemplate>
</asp:WebPartZone>


Note nas primeiras linhas desse código a existência do controle WebPartManager, apesar dele não ter uma representação visual para o usuário ele é obrigatório no uso de Web Parts.

Creating Web Parts

Existem três principais métodos de criar ASP.Net Web Parts. O primeiro é criar um user control padrão. O segundo é utilizar um controle ASP.Net como uma Label e definir como sua Web Part. O terceiro é criar um controle customizado que herde da classe WebPart, este terceiro será explicado no capítulo 7 "Creating Custom Web Controls", ele é o método mais demora e mais complicado. Os outros dois métodos são mais simples.

Building Web Parts with User Controls

Para criar uma Web Part baseado em um User Control, basta adicionar o User Controle dentro de uma Web Part Zone que o Asp.Net cuida do restante. Como qualquer User Control basta declara-lo em sua página usando a diretiva @ Register, como a seguir:

<%@ Register src="VendorWebPart.ascx" tagname="VendorWebPart" tagprefix="uc1" %>

Após seu User Controle estar registrado basta adicona-lo a uma Web Part Zone, dentro da declaração ZoneTemplate. Veja abaixo:


<asp:WebPartZone ID="WebPartZone2" runat="server" HeaderText="Fabrikam" style="width: 350px; float: left; height: auto;">

  <ZoneTemplate>
    <uc1:VendorWebPart ID="VendorWebPart1" runat="server" title="Fabrikam" />
  </ZoneTemplate>


</asp:WebPartZone>


Creating a Web Part Control from an Existing ASP.NET Control

Seguindo o modelo de utilizar User Controls, é possível utilizar controles padrões do Asp.Net, basta adiciona-los dentro do elemento ZoneTemplate como foi feito acima. Veja o código abaixo:

<asp:WebPartZone ID="WebPartZone1" runat="server" HeaderText="Vendor Aggregate" style="width: 700px; height: auto">
  <ZoneTemplate>
    <asp:Label ID="Label3" runat="server" Text="" title="Vendor Totals">
      <div style="margin-top: 12px; margin-bottom: 20px; line-height: 30px; font-size: 12pt">
        Total Active Users: <a href="#">21</a>
        <br />Total transactions today: <a href="#">166</a>
        <br />Revenue trades to-date: <a href="#">$34,450</a>
      </div>
    </asp:Label>
  </ZoneTemplate>
</asp:WebPartZone>


Enabling Users to Arrange and Edit Web Parts

Web Parts podem ser exibidas de diferentes formas. O modo como ela é exibida é indiferente do que o usuário esta fazendo com a Web Parts ou onde ela esta hospedada naquele momento. É possível alterar o modo de exibição das Web Parts utilizando o controle WebPartManager. Basta definir a propriedade DisplayMode, as opções disponíveis para esta propriedade são:
  • BrowseDisplayMode: É a forma padrão que os usuários navegam;
  • DesignDisplayMode: É o modo que permite aos usuários arrastar a Web Part para diferentes locais;
  • EditDisplayMode: Parecido com o DesignDisplayMode, permite aos usuários arrastar a Web Part, e além disso permite também editar os dados como título, tamanho, direção, aparência da janela e zona, utilizando os controles AppearanceEditorPart e LayoutEditorPart. Para utilizar este modo é necessário adicionar o controle EditorZone a sua página e em seguida o controle AppearanceEditorPart e/ou LayoutEditorPart;
  • CatalogDisplayMode:  Permite ao usuário adicionar Web Parts que você especificou no controle CatalogZone. Para utilizar este modo é necessário ter o controle CatalogZone em sua página;
  • ConnectDisplayMode: Permite ao usuário estabelecer conexões manualmente entre os controles usando o controle ConnectionZone. Por exemplo uma Web Part pode ser ligada para mostrar informações de resumo e detalhe de um relatório. Para utilizar este modo é necessário ter o controle ConnectionZone em sua página.
O código a seguir exibe no clique de um botão como alterar o modo de exibição de uma Web Part:

protected void ButtonEdit_Click(object sender, EventArgs e)
{
  string mode = (string)ViewState["mode"];
  //switch modes
  if (mode == "browse")
  {
    ViewState["mode"] = "edit";
    ButtonEdit.Text = "Done";
    WebPartManager1.DisplayMode = WebPartManager1.SupportedDisplayModes["Catalog"];
  }
  else
  {
    ViewState["mode"] = "browse";
    ButtonEdit.Text = "Edit";
    WebPartManager1.DisplayMode = WebPartManager1.SupportedDisplayModes["Browse"];
  }
}


Repare que é usado a coleção SupportedDisplayModes para definir qual modo será exibido. Neste código vale explicar que o valor da ViewState foi salvo no evento PageLoad.

Connecting Web Parts

Uma possibilidade poderosa da Web Part é a conexão entre Web Parts. Para entender o uso, imagine o cenário onde esta desenvolvendo uma aplicação para controle da folha de pagamento dos funcionários, onde você tem:
  • A Web Part principal onde o usuário navega entre os funcionários.
  • Uma Web Part que exibe um gráfico das horas extras pagas ao funcionário.
  • Uma Web Part que exibe um gráfico de pizza que exibe o valor da folha de pagamento, benefícios e pensões que se encaixam no perfil global do funcionário.
  • E uma Web Part que compara o salário do funcionário com outros funcionários do mesmo cargo.
Com a conexão de todas Web Parts o usuário irá selecionar o funcionário uma única vez e todas as outras Web Parts irão ter suas informações atualizadas automaticamente.

Outro cenário é o desenvolvimento de um portal onde você tem várias Web Parts com informações distintas como clima, notícias locais e localização de bares. Porém todas elas necessitam do CEP para localizar essas informações, o usuário do portal irá informar o CEP uma única vez e todas as Web Parts irão se comunicar para ter acesso a este CEP.

Creating a Static Connection

Conexões podem ser estáticas ou dinâmicas. Se a conexão for estática, estabelecidade pelo desenvolver no momento de desenvolvimento ela não poderá ser alterada ou excluida pelo usuário. Conexões estáticas envolvem um Provider e um ou mais WebParts consumidores. Veja os passos para se criar os controles, tanto o provider como o consumidor e estabelecer uma conexão entre eles.

Primeiro Passo: Criar o WebParte provider.
O WebPart provider pode derivar da classe WebPart ou ser um user control. Você deve criar no seu WebPart um método público que tenha o atributo ConnectionProvider. Este método deve retornar o valor que o WebPart consumidor irá receber. Veja o código:

public partial class Provider : System.Web.UI.UserControl
{
  string _textBoxValue = "";
  

  [ConnectionProvider("TextBox provider", "GetTextBoxValue")]
  string GetTextBoxValue()
  {
    return _textBoxValue;
  }
 

  protected void Button1_Click(object sender, EventArgs e)
  {
    _textBoxValue = TextBoxProvider.Text;
  }
}


Passo 2: Criar o WebPart consumidor.
Assim como o provider pode herdar de WebPart ou ser um user control. É necessário criar um método público que possua o atributo ConnectionConsumer que recebe o mesmo tipo que o método do ConnectionProvider retorna. Veja o código:

public partial class Consumer : System.Web.UI.UserControl
{
  [ConnectionConsumer("TextBox consumer", "ShowTextBoxValue")]
  void ShowTextBoxValue(string textBoxValue)
  {
    LabelConsumer.Text = textBoxValue;
  }
}


Passo 3: Crie uma WebPage e adicione o controle WebPartManager, em seguida adicione o container WebPartZone.

Passo 4: Adicione seus WebPart ao WebPartZone, tanto o provider como o consumidor:

<asp:WebPartZone ID="WebPartZoneProvider" runat="server" Height="400px" Width="300px">
  <ZoneTemplate>
    <uc1:Provider ID="Provider1" runat="server" title="Provider" />
    <uc2:Consumer ID="Consumer1" runat="server" title="Consumer" />
  </ZoneTemplate>
</asp:WebPartZone>


O próximo passo é estabelecer a conexão entre os dois controles. Adicione o elemento <StaticConnections> ao WebPartManager e dentro deste elemento adicione o controle WebPartConnection para declarar sua conexão.

O controle WebPartConnection deve ter a propriedade ID, a propriedade ProviderID identifica o controle provider, ProviderConnectionPointID identifica o método do provider, ConsumerID identifica o controle consumidor, ConsumerConnectionPointID identifica o método no consumidor. Veja o código:

<asp:WebPartManager ID="WebPartManager1" runat="server">
  <StaticConnections>
    <asp:webPartConnection
        ID="conn1"
        ProviderID="Provider1"
        ProviderConnectionPointID="GetTextBoxValue"
        ConsumerID="Consumer1"
        ConsumerConnectionPointID="ShowTextBoxValue" />
  </StaticConnections>
</asp:WebPartManager>


Repare que você deve criar um controle WebPartConnection para cada par de controle conectado.

Enabling Dynamic Connections

Conexões dinâmicas podem ser estabelecidades pelo usuário. Para permitir esta ação você precisa adicionar o controle ConnectionsZone em sua página.
Para permitir que os usuários criem ou parem conexões, siga os seguintes passos:
  1. Crie uma página com um provider e um consumidor como explicado anteriormente.
  2. Opcionalmente, estabeleça uma conexão estática entre o provider e o consumidor. Esta será uma conexão padrão que estará sempre disponível para o usuário, mas ele pode modificar criar ou parar outras conexões dinâmicas.
  3. Adicione o controle ConnectionsZone em sua página.
  4. Adiciona o controle para permitir que o usuário entre no Modo Connect como explicado anteriormente em "“Enabling Users to Arrange and Edit Web Parts".
Establishing Dynamic Connections Among Web Parts

Quando um usuário acessar sua página ele pode alterar para o modo de conexão e utilizar o controle ConnectionsZone para editar as conexões. Veja os passsos:
  1. Altere o modo de visualização para connect.
  2. O menu do WebPart irá aparecer entre o provider e consumidor, clique em Connect no menu, veja a imagem:

        3. Irá aparecer o objeto ConnectionsZone:

        4.Caso já exista uma conexão, clique em Disconnect para fechar esta conexão. Em seguida clique em Create A Connection To A Consumer, selecione o consumidor e clique em Connect:

        5.Quando finalizar a edição das conexões clique em Close. As WebParts estarão conectadas como se fosse feito estaticamente.

Personalizing Web Parts

WebParts suportam personalização. A personalização permite que as alterações feitas sejam armazenadas por cada usuário, permitindo que ele visualize a página da mesma forma na próxima visita. Personalização de WebParts dependem dos cookies do navegador do usuário, através das informações dos cookies, serão buscadas as personalizaçãoes feitas no banco de dados. Armazenada essas informações por usuário, normalmente você vai querer utilizar autenticação, mas isso não é necessário.

Enabling Personalization for Custom Controls

Para permitir esta personalização nos controles de WebPart é necessário definir no método público do controle o atributo Personalizable, veja como:

[Personalizable]
public string PostalCode
{
  get
  {
    Return _postalCode;
  }
  set
  {
    _postalCode = value;
  }
}

Enabling Shared Personalization

A personalização de WebParts são habilitadas por padrão e os usuários autenticados, conseguem personalizar uma WebPart sem qualquer configuração especial. Porém essas personalizações são feitas a nível de usuário, onde cada usuário visualiza somente sua mudança.
Caso queria dar permissão para algum usuário, como o webmaster do site altere a personalização de qualquer usuário, isto é possível. Basta habilitar a personalização compartilhada no web.config.

Dentro da sessão <system.web>, adicione a sessão <authorization>, então adicione o elemento <allow> para especificar qual usuário ou usuário tem acesso a personalização compartilhada.

<authorization>
  <allow verbs="enterSharedScope" users="SomeUserAccount" roles="admin" />
</authorization>

Desta forma os usuários podem alterar uma personalização e essas mudanças serão vistas por outros usuários.
Disabling Personalization for a Page

Caso queria desabilitar a personalização em alguma página, basta definir a propriedade WebPartManager.Personalization.Enabled para false. Veja como:

<asp:webPartManager ID="webPartManager1" runat="server">
  <Personalization Enabled="False" />
</asp:webPartManager>

sexta-feira, 4 de novembro de 2011

Capítulo 5: Input Validation and Site Navigation Lição 2: Performing Site Navigation

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 <a>, veja o exemplo:


HyperLink Control: Source
<asp:HyperLink ID="HyperLink1"runat="server" NavigateUrl="~/NavigateTest2.aspx">Goto NavigateTest2</asp:HyperLink>

HyperLink Control: Rendered HTML
<a id="HyperLink1" href="NavigateTest2.aspx">Goto NavigateTest2</a>

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:

<input id="Button1" type="button" value="Goto NavigateTest2" onclick="return Button1_onclick()" />

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 <head>:

<script language="javascript" type="text/javascript">
  function Button1_onclick() {
    document.location="NavigateTest2.aspx";
  }
</script>


Cross-Page Posting

 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)
{
  if(Page.PreviousPage == null)
  {
    LabelData.Text = "No previous page in post";
  }
  else
  {
    LabelData.Text = Server.HtmlEncode(((TextBox)PreviousPage.FindControl("TextBox1")).Text);
  }
}


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
{
  get { return TextBox1.Text; }
}


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

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)
{
  if (PreviousPage == null)
  {
    LabelData.Text = "No previous page in post";
  }
  else
  {
    LabelData.Text = PreviousPage.PageData;
  }


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)
{
  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)
{
  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 <siteMapNode>. 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:

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


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)
{
  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:

<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" StartingNodeOffset="0" ShowStartingNode="False" />

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:

<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1" MaximumDynamicDisplayLevels="5" Orientation="Horizontal">
</asp:Menu>


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:

domingo, 25 de setembro de 2011

Capítulo 5: Input Validation and Site Navigation Lição 1: Performing Input Validation

Este capítulo demonstra 2 recursos do asp.net.

O primeiro é a validação automática de entrada de dados em formulários web, podendo essas validações serem geradas como javascript melhorando assim o desempenho da resposta ao usuário. E também por segurança componentes que fazem validação do lado do servidor.

O outro recurso deste capítulo é sobre a navegação facilitada ao usuário com o uso de Web Parts.

Lesson 1: Performing Input Validation

Nesta lição serão apresentados controles que irão facilitar no momento de fazer validações de entrada de dados em formulários web.

Understanding the Validation Framework

A validação de dados é algo comum e rotineiro para desenvolvedores. O asp.net possui ferramentas que facilitam a criação dessas valições de forma rápida e com poucos códigos.

Existem 2 cenários que podem ser utilizados. Você pode utilizar a validação do lado do cliente, desta forma os controles irão gerar códigos javascripts que são rodados no browser, evitando assim que seja feita a comunicação com o servidor. Ou seja, antes mesmo do usuário clicar no botão "enviar/gravar" ele já terá uma resposta se esta preenchendo o formulário de maneira correta. Porém este é um cenário que não é totalmente seguro, usuário maliciosos podem facilmente "boicotar" essa validações que rodam do lado do cliente.

Porém o asp.net fornece ferramentas que fazem as mesmas validações do lado do servidor, garantindo assim maior segurança dos dados.

Adding Validation Controls to Your Page

Você pode localizar os controles de validação na ToolBox do Visual Studio, você irá proceder da mesma forma com que faz com outros controles. Siga os seguintes passos para adicionar uma validação a sua página:
  1. Abra a página no Design view e abra a ToolBox. Adicione um controle de entrada de dados que será validado, como um TextBox ou RadioButtonList.
  2. Vá até a aba Validation da Toolbox. Arraste um RequiredFieldValidator para próximo do TextBox que será validado como campo obrigatório.
  3. Defina a propriedade ID do RequiredFieldValidator com um nome semelhante do ID definido ao TextBox, desta forma seu código ficará mais facil de ser entendido. Por exemplo, caso seu TextBox tenha a propriedade ID dfinida como NomeTextBox, defina o ID do RequiredFieldValidator como NomeTextBoxValidator.
  4. Defina a propriedade ControlToValidate do seu RequiredFieldValidator com o ID do seu TextBox, neste caso, NomeTextBox.
  5. Defina a propriedade ErrorMessage, esta será a mensagem exibida ao usuário, utilize algo que facilite o entendimento do usuário. É comum exibir essas mensagens todas em um único controle chamado ValidationSummary.
  6. Defina a propriedade Text do TextBox para algo que "avise" o usuário que a validação falhou. Caso você utilize um ValidationSummary, pode definir a propriedade Text com um asterisco (*).
  7. Caso não queria exibir nada na propriedade Text é recomendado utilize a propriedade tooltip com uma mensagem curta e similar a mensagem de erro que é exibida no ValidationSummary, desta forma quando o usuário levar o cursor ao TextBox irá ver que a validação falhou.
  8. Caso não queira que seja exibida mensagem ao usuário se a validação falhe, defina a propriedade Display para None. Se deseja exibir a mensagem pro usuário, defina a propriedade como Static, porém como é uma mensagem estatica, defina uma mensagem em branco que irá aparecer antes de ocorrer a validação. Caso contrário deixe a propriedade como Dynamic para que o asp.net formate a saída do texto caso ocorra uma falha de validação;
  9. Opcionalmente utilize o controle ValidationSummary para exibir várias mensagem de erros de validação. É muito útli quando possui vários controles que são validados e dificulta posicionar todas as mensagens de forma separada em sua página. É interessante que este controle seja posicionado próximo ao botão de submit ou no topo do formulário. Você pode definir a propriedade ShowMessageBox para true, onde este controle irá exibir um PopUp com as mensagens de erros de validação.
Server-Side Validation

Os controles de validação trabalham em conjunto com o objeto Pag, para garantir que os dados do clientes sejam válidos quando chegar ao servidor. A classe Page possui a propriedade Validators que contém que é uma coleção de todos os validadores da página. A classe possui também um método chamado Validate que pode ser executado para verificar cada controle de validação.

O Asp.net chama o método Validate automaticamente após o Load da página. Portando você pode descobrir se a página é válida através da propriedade Page.IsValid.

Client-Side Validation

O Asp.net escreve os códigos de validação do lado do cliente quando você utiliza um controle de validação. O Asp.net escreve os códigos javascript que são executados quando o usuário sai de um campo que possui algum tipo de validação. 

Toda vez que um controle que possui uma validação perder o foco será disparado a validação javascript podendo assim exibir uma mensagem de aviso ao usuário. Você pode usar a propriedade SetFocusOnError para definir um foco ao controle quando sua validação falhar, desta forma o usuário so conseguirá sair deste campo quando entrar com dados válidos.

Determining When to Cause Validation

Utilizar a validação do lado do cliente é útil pois evita o envio da página para o servidor caso a página não seja válida. Porém isto pode ocasionar problemas em algumas situações. Por exemplo, caso você tenha um botão de Ajuda ou de Cancelar, estes botões não conseguiram disparar seus eventos para o servidor enquanto a página não estiver totalmente válida.

Para estes casos, existe a propriedade CausesValidation. Esta propriedade pode ser definida como false quando deseja que algum botão seja executado sem passar pela validação, pode ser usados em botão de Limpar, Voltar, etc...

Using Validation Groups

Existem cenários onde é necessário validar somente parte dos controles da sua página. Você pode agrupar seus controles de uma forma que serão válidados por grupos. Os controles de validação possuem a propriedade ValidationGroup que recebe uma string, esta string deve ser comum aos controles que deseja validar ao mesmo tempo.


Isso é possível por que o método Validate da página possue uma sobrecarga que recebe uma string como parâmetro, que é o ValidationGroup. Esta sobrecarga é executada quando ocorre um postback na página causando a validação dos controles.

O objeto Page possue também o método GetValidators que recebe uma string como parâmetro, neste caso devemos informar o ValidationGroup, e este método retornará todos os controles que são validados neste ValidationGroup.

Understanding the RequiredFieldValidator Control

O controle RequiredFieldValidator é utilizado para forçar que o usuário informe ou altere a informação de algum controle. O RequiredFieldValidator não valida informações como data, números inteiros e outros. Ele é utilizado para forçar o usuário a preencher os dados.

Além de obrigar o usuário a preencher o text de um textbox por exemplo, você definir um valor padrão para a propriedade text do seu controle, obrigando o usuário a alterar este valor. O RequiredFieldValidator possue a propriedade InitialValue, o valor informado para esta propriedade será considerado inválido caso o usuário não altere.

Exemplo: Você possui um dropdownlist de Estado, onde o primeiro valor do seu dropdownlist é "Selecione um estado...", você pode informar este valor para o InitialValue do seu RequiredFieldValidator forçando o usuário a escolher outra opção.


Using the CompareValidator Control

O controle CompareValidator permite validação de comparações, usando operadores como maior ou menor para comparar entrada de dados do usuário em um ou diferentes controles.

O CompareValidator pode ser usado para validar se o tipo de dados esta correto em um controle, como por exemplo se é uma data ou um número. Para este propósito você deve definir a propriedade Type para um tipo válido que será verificado. Se o objetivo for somente verificação de dados, pode ser definida a propriedade Operator para DataTypeCheck.

A imagem abaixo mostra a janela de propriedade do controle CompareValidator.




O CompareValidator utiliza a propriedade ValueToCompare para definir uma constante que será usada para fazer a comparação. Como exemplo, se você deseja que o usuário informe uma data superior a 1900, você deve definir a propriedade ValueToCompare para 1/1/1900 e definir a propriedade Operator, onde terá as seguintes opções: Equal, NotEqual, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, ou DataTypeCheck. Neste caso deve definir GreaterThanEqual (maior ou igual que). 


Também é possível utilizar este controle para validar duas datas, se uma é maior que a outra, ou validar se dois controles tem o mesmo valor, existe uma série de validações que podem ser criadas com o CompareValidator.


Using the RangeValidator Control


Muitas vezes temos a necessidade de validar um valor dentro de uma variação. Por exemplo, podemos querer que um campo de data seja informado com o Ano que seja o mesmo que o Ano corrente. Para este tipo de validação usamos o RangeValidator, ele possui duas propriedade principais, MinimumValue e MaximumValue, o nome delas já são bem intuitivos, outro propriedade é a Type que define qual o tipo de dados irá validar. 

No exemplo a baixo o controle recebe o valor do ano corrente como valor máximo e 1900 como valor minimo para não permitir que o usuario informe uma data fora deste intervalo.


protected void Page_Load(object sender, EventArgs e)
{
  if (!IsPostBack)
  {
    RangeValidatorSalesDate.MinimumValue = "1990";
    RangeValidatorSalesDate.MaximumValue = DateTime.Now.Year.ToString();
  }
}


Using the RegularExpressionValidator Control 

Este controle efetua suas validações através de expressões regulares. Uma expressão regular é uma série de combinações de caracteres que são usadas para identificar sequências de caracteres simples ou complexas. O controle possui a propriedade ValidationExpression onde você deve informar sua expressão regular.


Expressões regulares são complexas, porém não são exigidas nesta certificação, por isso o assunto não é muito discutido. Mas em todo o caso, o visual studio possui algumas expressões regulares pré-definidas neste controle, como por exemplo, validação de endereço de e-mail ou uma url válida. Veja na imagem a baixo.



The CustomValidator Control


Apesar dos diversos controles de validação que o asp.net fornece, pode acontecer de você precisar de algum outro tipo de validação. Para estes casos, você deve utilizar o controle CustomValidator. A validação deste controle é baseada no código em que o desenvolvedor cria. Você tem a opção de utilizar a validação com javascript para rodar do lado do cliente, ou fazer via c# para rodar do lado do servidor.


Custom Client-Side Validation

Como ja falado diversas vezes, a validação do lado do cliente acontecerá bem mais rápido para quem estiver utilizando sua página.
O primeiro passo é escrever sua validação do lado cliente, você deve possui um método com a seguinte assinatura:

function ClientFunctionName(source, arguments)

Você pode renomear o método conforme sua necessidade, porém os parâmetros de entrada não podem ser modificados. Após este método ser referenciado em seu controle, o framework de valiação irá executar seu método automaticamente. Quando a função de validação for executada, o parâmetro chamado source irá conter uma referência ao controle de validação que este sendo executado. Já o parâmetro arguments tem a propriedade chamada Value que possue os dados a serem validados.


Em seguida deve escrever seu código de validação, e definir a propriedade arguments.IsValid para true ou false. E para finalizar basta definir a propriedade ClientFunctionName de seu controle, com o nome de sua função.


No exemplo a seguir, existe o seguinte cenário: você possui em sua página um controle TextBox, um botão para confirmar os dados, um ValidationSummary para exibir as mensagens de erro, e um RequiredFieldValidator para obrigar o usuário a informar uma nova senha no TextBox. Além disso tem o CustomValidator que irá fazer a seguinte validação nos dados do textbox, é um campo de senha que deve ter entre 6 e 14 caracteres, deve conter pelo menos 1 letra maiscula, uma minuscula, e pelo menos 1 número. Veja como fica o código:


<%@ Page Language="VB" AutoEventWireup="false" CodeFile="NewPassword.aspx.vb" Inherits="NewPassword" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head2" runat="server">
        <title>Change Password</title>
    </head>
    <body style="font-family: Arial">
        <form id="form1" runat="server">
            <div>
                <table width="400">
                    <tr><td colspan="2" style="font-size: x-large">Change Password</td></tr>
                    <tr>
                        <td colspan="2">
                            <asp:ValidationSummary ID="ValidationSummary1" runat="server" />
                        </td>
                    </tr>
                    <tr>
                        <td width="190" align="right" valign="middle">New password:</td>
                        <td width="210" valign="middle">
                            <asp:TextBox ID="NewPasswordTextBox" runat="server" TextMode="Password"></asp:TextBox>
                            <asp:RequiredFieldValidator ID="RequiredFieldValidatorPassword" runat="server" ErrorMessage="Please enter a valid password" text="*" ToolTip="Please enter a valid password" ControlToValidate="NewPasswordTextBox"></asp:RequiredFieldValidator>
                            <asp:CustomValidator ID="NewPasswordCustomValidator" runat="server" Text="*" ToolTip="Password must be between 6-14 characters and include 1 capital letter, 1 lowercase letter, and 1 number" ErrorMessage="Password must be between 6-14 characters and include 1 capital letter, 1 lowercase letter, and 1 number" ControlToValidate="NewPasswordTextBox" ClientValidationFunction="ValidatePassword"></asp:CustomValidator>
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td><asp:Button ID="ButtonSubmit" runat="server" Text="Submit" /></td>
                    </tr>
                </table>
            </div>
        </form>
    </body>
</html>


O próximo passo é adicionar o código javascript com a função de validação. A função chama ValidatePassword. Observe que a assinatura do método segue o padrão mostrado anteriormente, e que como é definida o arguments.IsValid.

<script language="javascript" type="text/javascript">
    function ValidatePassword(source, arguments) {
        var data = arguments.Value.split('');
      
        //start by setting false
        arguments.IsValid = false;
      
        //check length
        if(data.length < 6 || data.length > 14) return;
      
        //check for uppercase, lowercase, and number
        var uc = false; var lc = false; var num = false;
      
        for (var c in data) {
            if (data[c] >= 'A' && data[c] <= 'Z') {
                uc = true;
            } else if (data[c] >= 'a' && data[c] <= 'z') {
                lc = true;
            } else if (data[c] >= '0' && data[c] <= '9') {
                num = true;
            }
      
            if (uc && lc && num) {
                arguments.IsValid = true;
                break;
            }
        }
    }
</script>


Como último passo basta definir a propriedade ClientValidationFunction com o nome da função javascript, no momento do teste, assim que o foco sair do TextBox, a validação será executada.


Custom Server-Side Validation

O CustomValidador pode ser usado para validar os dados do lado do cliente, do servidor ou ambos. Para utilizar do lado do servidor, você deve utilizar o evento ServerValidate. Você associa este evento ao controle da mesma forma com que faz outros eventos de outros controles. Os parâmetros de entrada da assinatura do evento é a mesma utilizada com a validação do lado do cliente. Os parâmetros source e args. Utilizando as mesmas propriedade para definir se a valiação foi válida ou não. O código a seguir, demonstra o mesmo exemplo utilizado anteriormente.


protected void NewPasswordCustomValidator_ServerValidate(object source, ServerValidateEventArgs args)
{
    string data = args.Value;
   
    // Start by setting false
    args.IsValid = false;
   
    // Check length
    if (data.Length < 6 || data.Length > 14) return;
   
    // Check for uppercase, lowercase, and numeric
    bool uc = false; bool lc = false; bool num = false;
    foreach (char c in data)
    {
        if (char.IsUpper(c))
        {
            uc = true;
        }
        else if (char.IsLower(c))
        {
        lc = true;
        }
        else if (char.IsNumber(c))
        {
        num = true;
        }
        if (uc && lc && num)
        {
            //must be valid
            args.IsValid = true;
            break;
        }
    }
}


Assim encerra esta primeira lição!!