Conhecendo paths ASP.NET

Conhecendo paths ASP.NET

O ASP.NET contém muitas propriedades para recuperar informação sobre paths da requisição atual,controle e aplicação.
Há muita informação sobre paths no objeto Request,alguns desses são pra sobrepor e outros vão a níveis mais baixos do path,por isso pode ser confuso achar apenas o caminho certo que você está procurando.

Eu achei uma boa idéia listar as opções de path junto com sua descrição e um exemplo.

Aqui está uma lista de propriedades relacionada com o objeto Request e o objeto Page.Tomamos como exemplo o caminho http://www.webabstract.com/webclass/learn/paths.aspx, onde webclass é o nome do virtual.

Propriedade do Request Descrição e valor
ApplicationPath Retorna a raiz-relativa lógica da pasta virtual da aplicação
/webclass/
PhysicalApplicationPath Retorna o caminho local (FileSystem) da pasta virtual da aplicação
c:\inetpub\wwwroot\webclass
PhysicalPath Retorna o caminho local do script
atual
ou do path atual
c:\inetpub\wwwroot\webclass\learn\paths.aspx
Path

FilePath

CurrentExecutionFilePath

Todos esses retornam o caminho lógico completo da raiz-relativa incluindo paths e nome de scripts.CurrentExecutionFilePath <br />retorna o caminho da requisição atual,depois de um Transfer enquanto FilePath sempre retorna o caminho original da requisição
/webclass/learn/paths.aspx
AppRelativeCurrentExecutionFilePath Retorna o caminho virtual da raiz-relativa do script ou caminho da requisição atual.<br />Se estiver num Transfer o caminho da transferencia é que é retornado
~/learn/paths.aspx
PathInfo Retorna qualquer extra path depois do nome do script.Se não houver extra path retorna o caminho da raiz-relativa.
/webclass/learn/paths.aspx/ExtraPathInfo
RawUrl Retorna a URL completa da raiz-relativa incluindo QueryString e Extra Path

/webclass/learn/paths.aspx?nome=DotNet
Url Retorna a URL completa incluindo QueryString e ExtraPath.Note que retorna uma instancia do objeto Uri ao invés de string.

http://www.webabstract.com/webclass/learn/paths.aspx?nome=DotNet

UrlReferrer Retorna a URL completa da página que enviou a requisição.Também retorna uma instância do objeto Uri e retorna NULL se a página foi acessada diretamente sendo digitada na barra de endereço.

http://www.webabstract.com/webclass/learn/default.aspx?Info

Como você pode ver,há muita informação disponível pra cada um dos 3 formatos de path comuns:

  • Caminho Físico (Physical Path):
    é um caminho do tipo do OS que aponta para um caminho ou arquivo no disco.
  • Caminho lógico (Logical Path):
    é um caminho Web que é relativo a raiz do servidor.
  • ~/(raiz-relativa) Path:
    é um caminho especifico do ASP.NET que inclue ~/ pra indicar a raiz virtual do caminho Web.O ASP.NET pode converter caminhos virtuais tanto em caminhos lógicos usando Control.ResolveUrl() ou caminhos fisicos usando Server.MapPath().Caminhos de raiz-relativa são uteis para especificar URL móveis que não dependem da estrutura de diretórios relativa e muito util para uso em controles ou componentes.

Você deve conseguir pegar qualquer formato de path ou script necessário do ASP.NET usando esses mecanismos

Variáveis com formulas fields no Crystal Reports

Introdução

Formula fields do Crystal reports permitem a você injetar blocos de código em um relatório quando um simples comando  SELECT,não é suficiente.Você pode declarar variáveis,criar blocos if/then,criar arrays,executar loops,ou chamar funções já prontas do Crystal Reports.Esse artigo vai criar um relatório num web site ASP.NET e mostrar como criar um formula field,manipular datas na formula assim como criar uma variavel e lhe atribuir um valor, e tambem usar a lógica if/then pra criar campos de resumo para o trimestre no relatório.

Antes de começar você precisa ter o VS2008 instalado com o crystal reports.Os exemplos foram escritos no VS2008 mas funcionam também no VS2005.Eu criei um banco de dados simples com uma tabela,pra usar como exemplo no relatório:

Passo 1:Criar o banco

  1. Abra o Sql Management Studio 2005/2008 e conecte se ao seu servidor.
  2. Crie um novo banco e lhe de o nome de CrystalFormulas
  3. Esse banco só vai conter uma tabela chamada SalesHeader.Crie a tabela conforme a seguir:
Nome do campo Tipo Permite nulo
SalesHeaderID Int (Identity) Não
SalesDate Datetime Não
Total Money Não

Eu preenchi esta tabela com registros de Janeiro a Junho.Segue o script para a criação deste banco:

create database CrystalFormulas
go
use CrystalFormulas
go
create table [dbo].SalesHeader
(
SalesHeaderID int identity(10,1) not null,
SalesDate datetime not null,
Total money not null,
constraint PK_SALES_HD primary key clustered(SalesHeaderID)
)
go
INSERT [SalesHeader] ( [SalesDate], [Total]) VALUES (CAST(0x00009D2C00000000 AS DateTime), 632.7600)
INSERT [SalesHeader] ( [SalesDate], [Total]) VALUES (CAST(0x00009D1000000000 AS DateTime), 45.6500)
INSERT [SalesHeader] ( [SalesDate], [Total]) VALUES (CAST(0x00009CF100000000 AS DateTime), 65.8700)
INSERT [SalesHeader] ( [SalesDate], [Total]) VALUES (CAST(0x00009D2C00000000 AS DateTime), 231.5600)
INSERT [SalesHeader] ( [SalesDate], [Total]) VALUES (CAST(0x00009D1000000000 AS DateTime), 76.8900)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 235.7400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 874.3600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES (CAST(0x00009D1000000000 AS DateTime), 98.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 234.8400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 121.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 738.8900)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 376.1000)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 473.9800)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 46.9800)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 87.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 234.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 334.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 908.7000)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 23.6700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 45.8900)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 23.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 93.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 363.9800)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 63.2300)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 574.0000)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 34.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 897.4600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 232.4300)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 121.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 88.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 34.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 87.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 22.4200)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 234.6600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 44.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 99.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 235.6500)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 34.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 232.6300)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D2C00000000 AS DateTime), 78.6700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D1000000000 AS DateTime), 46.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009CF100000000 AS DateTime), 34.8800)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 454.6500)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 452.6500)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 651.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 23.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 767.8900)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 25.7400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 84.3600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 985.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 24.8400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 21.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 78.8900)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 36.1000)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 73.9800)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 465.9800)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 873.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 23.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES (CAST(0x00009D6900000000 AS DateTime), 34.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 808.7000)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 234.6700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 453.8900)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES (CAST(0x00009D4B00000000 AS DateTime), 232.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 937.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 36.9800)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 633.2300)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 57.0000)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 345.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 89.4600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 22.4300)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 21.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 885.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 343.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 879.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 222.4200)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 24.6600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 404.7600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 996.5600)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 23.6500)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 344.5400)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 23.6300)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D8800000000 AS DateTime), 783.6700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D6900000000 AS DateTime), 462.8700)
INSERT [SalesHeader] (   [SalesDate], [Total]) VALUES ( CAST(0x00009D4B00000000 AS DateTime), 348.8800)

Você pode rodar esse script no SQL Management Studio pra criar a tabela e inserir os registros.

Você pode usar Integrated Security quando for conectar ao banco ou criar um SQL Login.De qualquer forma você precisa se lembrar qual método você escolheu quando estiver pronto pra se conectar ao banco,como definido nos passos abaixo.

Passo 2:Criar o web site,Add o relatório, e conectar ao banco

1. Rode o VS2008 e escolha File>New WebSite
2. Selecione o template de ASP.NET Web Site.Escolha o local que deseja salvar o projeto.Escolha a linguagem C# e clique em OK.
3. Clique com o direito no nome do projeto no Solution Explorer e escolha “Add New Item…”
4. Selecione o template Crystal Reports e mude o nome para QuartelySales.rpt.Clique no botão adicionar.
5. Irá aparecer uma caixa de dialogo do CR.Selecione “As Blank Report” e clique no botão OK.Isso irá add o arquivo do CR ao seu projeto e vai abrir o CR Design.
6. Agora você precisa se conectar ao banco.Clique com o direito em “Database Fields” no Field Explorer e selecione “Database Expert”.
7. A caixa de dialogo “Database Expert” irá aparecer.Clique no sinal de expansão de “Create New Connection”.Clique no sinal de expansão de OLE DB(ADO).A caixa de dialogo do OLE DB(ADO) deve aparecer.
8. Selecione SQL Native Client na lista de provedores e clique em NEXT.
9. Coloque o nome do seu servidor.Você tem então a opção de escolher usar SQL LOGIN ou Integrated Security.Para esse exemplo nós vamos usar Integrated Security,clicando no checkbox “Integrated Security”.
10. Coloque o nome do banco que foi criado no Passo 1,CrystalFormulas.Clique no botão finish.
11. Você deve ver o banco listado abaixo do nó OLE DB(ADO).Clique no sinal de expansão do banco para ver o schemas.Clique no sinal de expansão do dbo para ver as tabelas.
12. Clique na tabela SalesHeader e depois clique no botão > pra mover esta tabela para a lista de tabelas selecionadas para esse relatório.

Clique no botão OK.

Passo 3:Adicionando fields e formulas para o relatorio

Agora que você está conectado ao banco você pode adicionar os campos para o seu relatório.Qualquer campo que você queira mostrar em linha no relatório,deve ser posto na “Details Section”.

  1. No field explorer clique no sinal de expansão  de DatabaseFields.Clique no sinal de expansão de SalesHeader para ver os campos desta tabela.
  2. Arraste os campos SalesDate e Total para a Details Section no relatório.O CR irá automaticamente add o cabeçalho da coluna na seção Page Header quando você arrastar os campos na Details Section.


3. Agora iremos criar um formula field pra mostrar o trimeste de SalesDate.Clique com o direito no nó Formula fields no Field Explorer e escolha “New…”.Coloque quarter para o nome do formula field e clique no botão “Use Editor”.

  1. O CR tem inumeras funções já prontas que você pode usar nas suas próprias formulas.As funções estão listadas na seção de ‘Functions” do formula editor.Clique no sinal de expansão de Functions e depois clique no nó de Date and time.Isso irá mostrar a lista de funções disponiveis para manipular datas.A que estamos procurando se chama DatePart.Se você descer a barra de rolagem do Date and Time você deve encontrar essa função.Observe que as funções não estão em ordem alfabética então você deve ir até o final da lista.
  2. A função DatePart tem 3 diferentes assinaturas.Clique-duplo na primeira assinatura e essa irá aparecer no corpo da fórmula.

  1. O primeiro parâmetro para a função DataPart é o Intervalo.O intervalo pode ser  year(yyyy),quarter(q),month(m),day(d),hour(h),minute(n),second(s),day of week (w) e week (ww).Coloque (q) então o  trimeste é recuperado das datas.
  2. O segundo parâmetro é a expressão de data que deve ser analisada.Esse é o campo SalesData na tabela SalesHeader.O texto da formula deve se parecer com o seguinte:

DatePart (‘q’, {SalesHeader.SalesDate})

  1. Clique no botão “Save and Close”.A formula “Quarter”,irá agora aparecer no nó de Formula fields no Field Explorer.
  2. Arraste o campo para a Details Section.Clique no botão “Main Report Preview” pra mostrar o relatório .Você deve ver ou 1 ou 2 para o trimestre.

Passo 4:Criar formulas com variáveis

O próximo passo será adicionar duas formulas para o relatório.Esse relatório deve mostrar a soma para o 1 trimestre e 2 trimestre.

  1. Clique para voltar em “Main report”.
  2. Clique com o direito  em Formula Fields e escolha “New…”.
  3. Nomeie para “Quarter1” e clique no botão “Use editor”

Essa fórmula vai criar uma variável para armazenar o total  de qualquer venda que ocorreu no 1 trimestre.Variaveis tem 3 opções de escopo:Local,Global,ou Shared.Local significa que a variável é usada na função especifica e seu valor é perdido quando a formula acaba.Global significa que a variavel mantém o valor mesmo depois do final da função e poder ser usada em outras formulas no relatorio.Shared significa que você pode usar essa variável em outras fórmulas ou mesmo em sub-relatórios.Por padrão se você omitir o escopo a variável será Global.Entre com o seguinte código no corpo da formula:

Global NumberVar quarter1;

if DatePart(‘q’, {SalesHeader.SalesDate}) = 1 then
quarter1 := quarter1 + ToNumber({SalesHeader.Total})
else
quarter1 := quarter1

Isso cria uma variavel global chamada  quarter1.O código depois então checa se a data está no primeiro trimestre.Se estiver então é adicionada para a variavel quarter1.

  1. Clique no botão Save and Close
  2. Clique no botão “Main Report Preview” pra mostrar o relatório

  1. Clique para voltar em “Main report”.
  2. Crie um segundo formula field chamado Quarter2  e entre com o seguinte código:

Global NumberVar quarter2;

if DatePart(‘q’, {SalesHeader.SalesDate}) = 2 then
quarter2 := quarter2 + ToNumber({SalesHeader.Total})
else
quarter2 := quarter2

Salve  a formula e arraste para a Details Section proximo do formula Quarter1 e clique no botão preview:

Note que o código não está mostrando o total.Isso é porque a variavel foi declara num escopo local e não global.

  1. Clique para voltar para o design.
  2. Clique com o direito no campo Quarter2 na Details Section e selecion “Edit ”.Retire a palavra local antes da declaração da variavel.Por padrão esta agora será global.Clique em Save and close.De um preview no relatório novamente.Desta vez você verá o total para o 2 trimestre.
  3. Clique para voltar para o design.Arraste os fields Quarter1 e Quarter2 para a seção “Report footer” do relatório nas suas repectivas colunas.
  4. Delete os fields Quarter1 e Quarter2 da Details Section.
  5. Clique com o direito na Details Section e escolha “Suppress (No-Drill-down)”
  6. Agora se você rever o relatório você verá somente os totais.

Conclusão

Formula Fields no crystal reports permitem você manipular seus dados de várias maneiras quando um simples SELECT não é suficiente.A sintaxe é bem simples de usar se você já conhece C# ou VB.CR também tem inumeras funções já prontas que você pode usar nas fórmulas.Você também pode usar loopings,como FOR e WHILE.Você também pode achar o próximo valor ou o valor anterior de um field.O poder das formulas e a linguagem de script é tremendo e permite a você cobrir qualquer requerimento dos usuarios mais exigentes.

ASP.NET MVC 2.0 Areas

Introdução

Conforme as necessidades de uma aplicação WEB crescem,o número de arquivos associados com esta aplicação cresce rapidamente.Em uma aplicação web form,as páginas são geralmente seperadas em subpastas,com cada subpasta representando um grupo lógico destas páginas.Projetos web form podem usar qualquer estrutura de pastas para organizar os arquivos.
ASP.NET MVC trabalha por convenção,por isso a estrutura de arquivos é um pouco mais “rigida”;todas as páginas são agrupadas em subpastas da pasta raiz “Views”,com cada subpasta representando o nome de um controle na pasta Controllers.Por exemplo,o controle “Organizations”,tem uma pasta “Organizations” dentro da pasta “Views”,com todas as páginas ASPX representando as views para o controle “Organization”.Um exemplo de estruturas de pastas está na imagem a seguir:

Apesar do processo poder tambem ser um pouco customizado,a estrutura de páginas permanece rigída por causa da convenção.Uma recente mudança a essa convenção trouxe o conceito de “Areas”,que é um balanço entre a rigída configuração do framework ASP.NET MVC e a separação de componentes lógicos.A maneira mais facil de ver isto em ação é dar uma olhada na estrutura de pastas.Abaixo está o mesmo projeto de exemplo,rearranjado pra usar “INLINE AREAS”:

AREAS permitem aos projetos MVC manter a estrutura de pastas de controllers,models e views,enquanto separa os componentes lógicos uns dos outros;a implementação do“coração” do projeto está separado da AREA Organizations.AREAS de uma aplicação podem duplicar  nome de classes de controle,nome de classe de models,views,etc.Porém,cada AREA pode também compartilhar recursos na pasta “Shared”.

Você pode ver nos meus 2 exemplos acima,que a “linguistica” da estrutura de pastas mudou um pouco;primeiramente um controle Organization,depois uma organization AREA,com outro nivel de hierarquia no link(o “ManagementController”  se anexa a URL com /management).Agora requisições para /Organizations/Index são roteadas para  /Organizations/Management/Index.

Routing

O mecanismo de routing padrão do MVC entre views é por convenção.Por exemplo,na figura 1,um link para a “action” Manage iria ser gerado através do seguinte comando “Html.ActionLink”,que renderiza um hyperlink para redirecionar  para o controle Organizations no projeto principal:

Html.ActionLink(“Manage this Organization”, “Manage”,

new { controller = “Organizations”, key = 1 })

O primeiro parâmetro especifica o texto do link,os 3 ultimos parametros  especificam o action metódo a ser chamado,e os parametros da “route”,que são passados como querystring.

O conceito de AREAS muda isso um pouco,porque nós precisamos poder diferenciar a area pra qual nós queremos rotear.Isso é simples;adicione um  “key/value pair AREA” para a lista de parametros da “route”.Para rotear para nossa nova “inline area”,nós podemos usar a seguinte sintaxe:

Html.ActionLink(“Manage this Organization”, “Manage”, “Management”,

new { area = “Organizations”, key = 1 })

Informando a area especifica podemos navegar para a area correta;sem isso,o link iria mandar para o ManagementController no projeto principal,que não existe;Adicionando o parametro area=”Organizations”, faz com que as requisições seja corretamente roteadas para os controles dentro daquela area.

Mas há alguns outros passos para que isto aconteça,e requer o uso de um novo objeto chamado “AreaRegistration”.Um processo personalizado de registro deve ser criado para as AREAS,como a seguir:

public class OrganizationsAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return “Organizations”;
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
“Organizations_default”,
“Organizations/{controller}/{action}/{id}”,
new { action = “Index”, id = UrlParameter.Optional }
);
}
}

O método RegisterArea é o componente chave para fazer o registro adicionando outra “route” para a coleção de “routes” de AREA.Note que o nome da AREA “Organizations” está fixado na URL;todas as requisições prefixadas com o nome de areas são tratadas de forma diferente.

Você deve estar pensando: porque nós não podemos especificar   Organizations para a definição de “routes” na aplicação principal?Se nós tivessemos adicionado  para a tabela de “routes” padrão,e não através do contexto da area,nós ainda teríamos que ter todos os arquivos no nosso mesmo projeto,e perderíamos os beneficios da separação de Areas de projeto.

Multi-projects Area

Não suportado diretamente no ASP.NET MVC 2 nem no ASP.NET MVC ,a versão RC e beta,tambem suportam “areas” que são “projetos separados”.Um projeto MVC separado poderia ser referenciado como uma area e funcionar  da mesma maneira que uma “INLINE AREA”.A forma de se fazer é muito parecido com “INLINE AREAS”,com a execeção de algum trabalho de configuração adicional no projeto MVC.

Essas configurações adicionais precisam de uma técnica que copia o conteúdo do projeto e fazem o “deploy” dele no projeto principal,basicamente mesclando a AREA que contem o projeto externo com o projeto principal do ASP.NET MVC.O processo de “deploy” funciona sem emendas para você,e acontece automaticamente através de uma tarefa MSBUILD,como parte de futuros assemblies do ASP.NET MVC.Existe um assembly chamado Microsoft.Web..Mvc.Build.dll que faz esse processo para você.

Isso não é oficialmente suportado pela microsoft;no entanto,se você quiser tentar essa configuração,os seguintes recursos irão ajuda-lo a implementar a tarefa no seu projeto:

http://msdn.microsoft.com/en-us/library/ee307987%28VS.100%29.aspx

http://dotnetslackers.com/articles/aspnet/a-first-look-at-asp-net-mvc-2.aspx

Considerações Finais

Areas são uteis para separar conteudo,mas eu lhe recomendo,não abusar,por varios motivos.Primeiro,areas realmente aumentam o numero de arquivos do projeto.Manter o projeto reduzido dentro do possivel ajuda na manutenção.Eu não estou advogando contra AREAS,eu estou recomendando um balanço entre o tamanho do projeto e a separação lógica de conteudo.

Uma coisa legal com AREAS é que você pode configurar controles com nomes similares para as views e fazer com que o site pareça mais consistente.Por exemplo,as areas account,store, e catalogo podem ter URLS consistentes dando nomes similares aos controles e actions de cada Area.Por exemplo,seu site poderia ter o seguinte:

/Accounts/Search/Index

/Store/Search/Index

/Catalog/Search/Index

Conclusão

Areas ajudam a separar conteudo,e alteram o processo de “routing”.Areas tem suas próprias estruturas de pastas e roteam suas próprias requisições de controles para as views.Routes requerem uma novo parametro de  “AREA de “routing”,que é usado para rotear para a area correta.

Criando relatórios com Crystal Reports e ASP.NET – Parte 4

Nos posts Criando relatórios com Crystal Reports e ASP.NETParte 1, Parte 2,Parte 3 nós desenvolvemos o coração do relatório.Nessa última parte vamor finalizar o relatório com o rodapé,e depois veremos como manipula-lo em tempo de execução e como visualiza-lo na página .aspx.

Criando o rodapé

O último passo no desenvolvimento do relatório é ádiconar o número da página na seção “Page Footer”:

  1. Clique com o direito na seção “Page Footer” e selecione “Insert Special Field Page N of M”.
  2. Arraste o campo para a seção “Page Footer”.
  3. Deixe o campo da largura da página.
  4. Clique com o direito no campo e selecione “Format Object”.
  5. Na aba “Common”,mude o alinhamento horizontal para “centered” e clique OK.

Se você ver o relatório agora,vai notar que o número da página reseta  para 1 cada vez que o “SalesOrderNumber” muda.

Visualizando o relatório na página ASP.NET

Agora que o relatório está pronto,podemos criar a página para visualiza-lo.Vamos criar uma página simples que permite ao usuário selecionar o cliente e ver qualquer fatura para o mesmo.

  1. Abra a página Default.aspx no VS.Adicione a seguinte declaração logo abaixo da tag “Page”,ou simplesmente arraste o controle Crystal Reports Viewer para a página:
<%@ Register assembly=”CrystalDecisions.Web, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304″ namespace=”CrystalDecisions.Web” tagprefix=”CR” %>

Isso permite você usar o controle Crystal Reports Viewer que vem com o VS.

Adicione o seguinte código entre as tags “DIV”:

Select a customer:<asp:DropDownList ID="ddlCustomer" runat="server">
</asp:DropDownList>

<asp:Button ID="btnPreview" runat="server" onclick="btnPreview_Click"
  Text="Preview" />

<br />
<br />
<CR:CrystalReportViewer ID="CrystalReportViewer1" runat="server"
  AutoDataBind="true" />

Isso adiciona um DropDownList que será preenchido com a lista de Customers (clientes) no Page_Load da página.O botão preview irá buscar todos os dados do cliente selecionado e dar uma bind no relatório.

  1. Adicione os seguintes namespaces no code behind:
using System.Data.SqlClient;
using System.Configuration;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;

Adicione o seguinte código no evento Page_Load:

if (!IsPostBack)
{

SqlConnection cn = new SqlConnection(
ConfigurationManager.ConnectionStrings[“AdventureWorks”].ConnectionString);
cn.Open();

SqlCommand cmd = new SqlCommand(“SELECT DISTINCT LastName + ‘, ‘ +
FirstName AS Name,
Person.Contact.ContactID ” +
“FROM Sales.SalesOrderHeader ” +
“INNER JOIN Person.Contact ” +
“ON Sales.SalesOrderHeader.ContactID =
Person.Contact.ContactID ” +
“ORDER BY LastName + ‘, ‘ + FirstName”, cn);
SqlDataReader dr = cmd.ExecuteReader();

ddlCustomer.DataSource = dr;
ddlCustomer.DataTextField = “Name”;
ddlCustomer.DataValueField = “ContactId”;
ddlCustomer.DataBind();

CrystalReportViewer1.Visible = false;
}
else
{
if (CrystalReportViewer1.Visible == true)
{
BindReport();
}
}

Esse código carrega o DropDownList com os customers do banco.Você precisa adicionar a ConnectionString do seu banco no Web.Config pra esse código funcionar.Na seção “AppSettings” você deve adicionar o seguinte:

<connectionStrings>

<add name="AdventureWorks" connectionString="Data Source=YOURSERVER;User
  ID=aspalliance;Password=aspalliance;Initial Catalog=AdventureWorks;"/>
</connectionStrings>

Esse código assume que você tenha um Login “aspalliance” com a senha “aspalliance” e as devidas permissões no banco.Seu SQL precisa estar configurado para o modo “Mixed Authentication” pros logins serem permitidos.

Adicione o seguinte código no evento de click do botão preview:

protected void btnPreview_Click(object sender, EventArgs e)
{
BindReport();
CrystalReportViewer1.Visible = true;
}

Esse código chama o método “BindReport()” e depois mostra o controle Report Viewer.

Agora adicione os seguintes métodos:

private void BindReport()
{
ReportDocument report = new ReportDocument();
report.Load(Server.MapPath(“Invoice.rpt”));

SetTableLocation(report.Database.Tables);

CrystalReportViewer1.ReportSource = report;

report.DataDefinition.RecordSelectionFormula =
“{SalesOrderHeader.ContactID} = ” + ddlCustomer.SelectedItem.Value;
}

private void SetTableLocation(Tables tables)
{
ConnectionInfo connectionInfo = new ConnectionInfo();

connectionInfo.ServerName = @”LTMTI30\SQL2008″;
connectionInfo.DatabaseName = “AdventureWorks”;
connectionInfo.UserID = “aspalliance”;
connectionInfo.Password = “aspalliance”;

foreach (CrystalDecisions.CrystalReports.Engine.Table table in tables)
{
TableLogOnInfo tableLogOnInfo = table.LogOnInfo;
tableLogOnInfo.ConnectionInfo = connectionInfo;
table.ApplyLogOnInfo(tableLogOnInfo);
}
}

O primeiro método cria a instância da classe ReportDocument.Ela representa o relatório que você criou anteriormente e permite manipula-lo em tempon de execução.O método SetTableLocation seta a “table location” de cada tabela do relatório.De novo,isso assume que você criado o Login “aspalliance” no SQL e tenha dado acesso a ele.A fonte (source) do Crystal Reports Viewer é depois setada para o objeto do relatório.Você cria uma string simples como uma clausula where de comando SQL.Você tem que usar “{}” em volta de campos referenciados do relatório.

Você pode rodar o relatório agora.Se você selecionar “Abel,Catherine” no DropDownList e clicar no botão preview,você deve ver a seguinte página:

É isso!Elaboramos nosso relatório,nas Partes 1,2 e 3 e nesta última parte vimos como visualiza-lo na página .aspx.

Espero que essa série de posts tenha sido útil pra quem está começando com relatórios ,e que percebam que não é nenhum bicho de 7 cabeças.

Mais sobre o Crystal Reports com ASP.NET.

Até a próxima!

Criando relatórios com Crystal Reports e ASP.NET – Parte 3

Esta é a continuação da série sobre relatórios com Crystal Reports e ASP.NET,nasParte 1 e Parte 2 criamos o cabeçalho do relatório.Nesse post agora estaremos exibindo os dados principais.

Quando o relatório for mostrado,todos os registros de SalesOrderDetail (Detalhes do pedido),devem ser mostrados para o SalesOrderNumber (Numero da fatura) atual.Para isso você pode criar um grupo baseado no campo SalesOrderNumber,e depois adicionar uma quebra de página  depois da seção “Group Footer”.Quando você adiciona um grupo no Crystal Reports,você automaticamente tem uma seção “Group Header” e “Group Footer Section”.Você pode formatar essas seções dinamicamente pra quebra de página,resetar o número da página,e muitas outras coisas.Para o nosso relatório nós queremos quebrar a página,depois da sessão “Group Footer”,então a próxima fatura começa na próxima página e nós queremos resetar o número da página,então você pode imprimir as  faturas em grande quantidades  mas  envia-las individualmente:

  1. Clique com o direito em qualquer espaço em branco do relatório e selecione “Insert Group…”
  2. Selecione o campo SalesOrderHeader.SalesOrderNumber no DropDownList e clique em OK.

  1. Você vai notar que duas novas seções foram adicionadas ao relatório:”Group Header#1″ e “Group Footer #1”.Por padrão,o Crystal adiciona o  “Special Field” chamado “Group #1”.Esse irá mostrar o valor pra qualquer campo que você estaja agrupando.Para este relatório você não vai precisar do nome do grupo,porque este é o campo SalesOrderNumber e é imprimido no cabeçalho do relatório.Você pode remover este campo clicando nele e pressionando delete.
  2. Nós não precisamos da seção “Group Header #1”,então você pode esconde-la,clicando com o botão direito no seu titulo e selecionando “Suppress(No-Drill-Down)” no pop-up.
  3. O próximo passo é dizer ao Crystal para quebrar a página depois da seção “Group Footer” e resetar o número da página.Clique com o direito no titulo “Group Footer #1” e selecione “Section Expert” no menu popUp.
  4. Marque as checkboxs “NewPageAfter”,”Reset Page Number After” e clique em OK.
  5. O próximo passo é adicionar os itens para a fatura.A seção “Details” irá se repetir,para cada registro na tabela SalesOrderDetail.Expanda  a tabela Products no FieldExplorer.Arraste o campo ProductNumber para a seção “Details”.Note que quando fizer isso,o Crystal automaticamente adiciona um campo “Column Header” na seção “Page Header”.O “Column Header” é simplesmente  um “Text Object”,que você pode editar para um nome mais amigavel.Mude o nome para “Número do produto”.
  6. Arraste o campo Product.Name para a seção “Details”.Ajuste sua largura.
  7. Arraste o campo SalesOrderDetail.OrderQty para a seção “Details”.Mude a column header para “Qtd”.
  8. Arraste o campo SalesOrderDetail.UnitPrice para a seção “Details”.Mude a column header para “Preço”.
  9. Arraste o campo SalesOrderDetail.UnitPriceDiscount para a seção “Details”.Ajuste sua largura.Mude a column header para “Desc”.
  10. Arraste o campo SalesOrderDetail.LineTotal para a seção “Details”.Mude a column header para “Total Itens”.
  11. O próximo passo é adicionar um “Box”,assim os Columns Header e os detalhes,ficam contornados e destacados no relatório.Clique com o direito em um espaço em branco no relatório e selecione “Insert Box”.Arraste a caixa em volta dos Column Headers e abaixo da seção “Group Footer”

  1. De um preview no relatório.

O último passo é criar os totais na seçãoo “Group Footer”.A soma dos campos “LineTotal”  (Total de cada item) corresponde ao subTotal da fatura.Tem um campo na tabela SalesOrderHeader chamado “Subtotal”,mas por algum motivo ele não corresponde a soma dos detalhes.Para contornar isso nós iremos criar nosso próprio Subtotal no relatório.Nós iremos depois adicionar o Freight(Frete) e Tax(taxa) para calcular a fatura total.

  1. Clique com o direiro no campo Line Total na seção “Details”.Selecione “Insert Summary”.
  2. O dropdown “Field to Summarize” deve estar por padrão setado para SalesOrderDetail.LineTotal e o “Calculate this summary” deve estar em Sum.Mude o dropdown  “Summary Location” para “Group #1:SalesOrderHeader.SalesOrderNumber – A.Clique em OK.

  1. Isso irá automaticamente criar o “Summary field” na seção “Group Footer” abaixo do campo  “LineTotal”.Você pode precisar aumentar a altura da seção “Group Footer” pra que os dados apareçam corretamente.
  2. Clique com o direito no campo e selecione “Formar Object”.Clique na aba “Font” e mude o “Style” para regular.Clique na aba “Number” e marque o checkbox “Display Currency Symbol”.Clique em Ok.’
  3. Clique nos campos  “Summary Field”  e “Line Total” enquanto pressiona a tecla CTRL.Deixe-os do mesmo tamanho e os alinhe a direita.
  4. Clique em um espaço em branco no “Summary Field” e selecione “Insert Text Object”.Mude o texto para “SubTotal:”.Essa é a label para o “SummaryField”.
  5. Agora adicione o campo “Tax”.Expanda o “DataBase Fields” no Field Explorer.Expanda a tabela SalesOrderHeader.Arraste o campo Tax para a seção “Group Footer” logo abaixo do Summary Field “Line Total”.
  6. Clique em um espaço e em branco e selecione “Insert Text object”.Mude o texto para “Taxa:”.E coloque como label do campo “Tax”.
  1. Agora arraste o campo “Freight” abaixo do campo “Tax”.
  2. Clique em um espaço e em branco e selecione “Insert Text object”.Mude o texto para “Frete:”.E coloque como label do campo “Freight”.
  3. Clique nos campos  “Tax”  e “Freight” enquanto pressiona a tecla CTRL.Deixe-os do mesmo tamanho e os alinhe a direita.
  4. Agora você tem que criar uma formula para o total da fatura.Clique no Formula Fields no Field Explorer e selecione “New…”.De o nome de “InvoiceTotal” e clique em Use Editor.
  5. Entre com o seguinte código.
Sum ({SalesOrderDetail.LineTotal}, {SalesOrderHeader.SalesOrderNumber}) +
{SalesOrderHeader.TaxAmt} + {SalesOrderHeader.Freight}
  1. Clique no botão Save and Close.
  2. Arraste o Formula Field “InvoiceTotal” para a seção “Group Footer” logo abaixo do campo freight.Deixe esses campos do mesmo tamanho e alinhe-os a direita.
  3. Como esse é um campo de Total nós iremos adicionar uma linha acima do campo e duas abaixo.Pra fazer isso clique com o direito no campo “InvoiceTotal” e selecione “Formar Object”.
  4. Clique na aba “Border”,e selecione a linha superior (top) como Single,e a inferior (Bottom) como double.
  5. Agora insira um label a esquerda do campo “InvoiceTotal”.Clique com o direito em um espaço em branco campo e selecione “Insert text object”.Mude o texto para “Fatura Total:”.

O relatório deve estar parecido com a figura abaixo:

As Seções “Report Header” e Report Footer” não são usadas nesse relatório e podem ser escondidas.Clique no titulo delas e selecione “Supress(No-Drill-Down)”.

Nosso relatório está praticamente pronto,agora precisamos criar o rodapé,e depois mostra-lo na página ASP.NET,coisas que estarei mostrando nos próximos posts desta série.

Até lá!

SEO para ASP.NET – Parte 2

Continuando o artigo sobre SEO para programadores ASP.NET.Veja a parte 1

SEO Urls amigáveis:Reescrita de URL

“Spiders”(motores de busca) web não gostam de querystrings nas URLs.Se você está trazendo dados de banco é muito comum usar querystrings como ShowProduct.aspx?id=2445.Apesar dessa URL parecer muito lógica para programadores,ela não é amigavel para usuarios e geralmente não é bem rankeada nos sites de busca.Você precisa usar URLs separadas por hifens.Então ao invés de ShowProduct.aspx?id=2445 deveria ser algo como:,em>My-ProductName.aspx.Urls que contenham palavras-chave,são faceis de ser lidas por humanos e são melhores rankeadas nos mecanismos de busca.Site com URLs SEO amigaveis,são mais seguros porque você pode esconder os IDs ou mesmo as extensões do arquivo.
Reescrita de URL em ASP.NET,pode ser implementada de várias maneiras,diretamente na página,no arquivo Global.asax,usando Custom HTTP Handlers ou HTTP Modules,diretamente no servidor etc
Reescrita de URL no código da página é uma maneira dificil,mas pode ser util em alguns cenários.Para página com URL amigável,use o método Server.Transfer, para chamar a página real.Então nesse caso,você deve na verdade ter uma página com URL amigável como um arquivo e colocar somente uma linha de código para a execução da transferência:
Reescrita de URL no Global.asax usa o método RewritePath no evento Application_BeginRequest.A implementação pode ser assim:

void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
if (app.Request.Url.AbsolutePath.StartsWith(“http://www.example.com/Friendly-Page/&#8221;))
{
app.Context.RewritePath(“/UnfriendlyPage.aspx?id=423874”);
}
}

Se você estiver interessado em reescrita de URL com HTTP Modules ou HTTP Handlers,de uma olhada no tutorial URL Rewriting in ASP.NET, onde ambos os métodos são explanados.
Para atingir resultados rapidamente você pode tentar http://urlrewriter.net .É um Rewriter URL open source para ASP.NET escrito em C#,fácil de usar e usado em sites grandes e pequenos.

ViewState e SEO no ASP.NET

Existe uma especulação de que motores de busca lêem somente um número limitado de bytes para cada página (os primeiros 100k da página).O valor do ViewState é uma string apresentada como HiddenField no lado cliente.Se você tiver um ViewState grande no inicio da página,então é possível que os spiders evitem o conteúdo real da sua página.Isso pode prejudicar sua posição nos rankings de busca.Uma solução simples é desativar o ViewState se você não precisar dele,ou pelo menos não usa-lo para cada controle da página.Se você realmente precisa do ViewState há uma nova opção no web.config para colocar na página:

Seguindo a mesma idéia,você deve remover qualque HTML,JavaScript,CSS desnecessário para fazer com que a página fique menor.Você deve e pode usar o Javascript e o CSS quando necessário,mas chame-os de um arquivo externo.Isso também reduz trabalho repetitivo.
Entretanto,essa conversa sobre limitação de leitura das páginas,é somente especulação,pessoalmente eu não acredito que isso seja inteiramente verdade.Mas os motores de busca,com certeza tentam agradar seus usuários e usuários gostam de páginas rápidas.Páginas que carregam rapidamente serão melhores rankeadas.Tempo de carregamento é um dos fatores de ranking.Removendo ou reduzindo ViewStates,deletanto HTML sem uso,e comentários HTML,movendo javascripts e CSS para arquivos externos e deixando na sua página somente conteúdo útil,irá aprimorar seu ranking direta e indiretamente.O último passo seria validar se HTML em http://validator.w3.org.

SEO Paging Amigável com GridView,Repeater e outros controles de dados

Paging padrões do ASP.NET usam postback e javascript.Spiders checam os links e geralmente evitam JavaScript,então usar os Pagings padrões não é uma opção de SEO amigável.A solução poderia ser usar custom paging para o gridView,repeater e outros controles.

Novas caracterisitcas SEO no ASP.NET 4.0

Manipulação direta das tags Description e Keyword
ASP.NET 4.0 tem novas opções para mudar as tags meta Keywords e description.Claro,que você já pode fazer isso em qualquer versão mais antiga do ASP.NET adicionando a tag “runat=server” para a tag meta description ou meta keyword e depois acessando-as no código do servidor,a maneira do ASP.NET 4.0 é mais simples e rápida,foram introduzidas as novas propriedades MetaDescription e MetaKeyWords no objeto Page,usadas como no código abaixo:

Page.MetaDescription = “This is my great page”;
Page.MetaKeywords = “great,page”;

Response.Redirect Permanent para redirecionamento permanente 301
ASP.NET 4.0 inclue outra interessante caracteristica SEO.O método Response.Redirect retorna “302 Temporay Redirection”.Para usar redirecionamento 301 com antigas versões do ASP.NET eram mais complicado,com o ASP.NET 4.0 ficou bem mais simples:

Response.RedirectPermanent(“New-Page.aspx”, true);

Lidando com http://www.subdominio

Esse é um problema comum.Como www é apenas um subdominio,motores de busca podem enxergar conteúdo duplicado e dividir a reputação entre http://www.exemplo.com/Sua-Pagina.aspx e exemplo.com/Sua_Pagina.aspx. É muito melhor ter um único link na primeira página,do que dois na trigésima.Permita somente um link para cada conteúdo.Se você descobrir que visitantes podem navegar para a mesma página por diferentes URLs,use o redirecionamento 301 para focar todo o ranking para somente uma URL.

AJAX e SEO

Ajax usa JavaScript e motores de busca não gosta de JavaScript.Então,seu site em AJAX tem um grande potencial para problemas.Possivelmente seu conteúdo não será indexado.Você pode desativar Javascript no seu browser e tentar acessar todo o conteúdo do site.Se você não puder visualiza-lo sem Javascript,os spiders também não poderão.
Possiveis soluções são SiteMap com links para todo o conteúdo,ou caminhos adicionais de navegação que usem links estáticos,ou fazer seu conteúdo inicialmente ser carregado sem JavaScript.

SEO Problemas de sessão

Por padrão,ASP.NET usa cookies para armazenar sessões.Como spiders web geralmente não aceitam cookies é possível que algo de seu conteúdo seja invisivel se variaveis de sessões forem requiridas para mostra-lo.Você pode mudar as configurações para armazenar sessões na URL(você pode fazer isso no web.config setando o parâmetro cookieless de sessionState para true)mas é ainda pior porque a popularidade do link será dividida em muitas URL diferentes com conteúdo duplicado.Tem uma opção pra setar o parâmetro cookieless para “AutoDetect”.Isso significa que o ASP.NET irá usar cookies se o browser suportar,então isso também não resolve o problema do SEO.
A solução poderia ser,setar o parâmetro cookieless para false,e disponilizar uma maneira de os spiders encontrarem todo o conteúdo através de simples links.

Conclusão

Como você viu,é muito fácil fazer um site em ASP.NET invisivel para os motores de busca .Só use buttons ou linkbuttons para navegação e ninguém irá encontrar seu site pelo google .Por outro lado,para receber o máximo de tráfego dos motores de busca,você precisa seguir sua regras e ser mais amigavel para os motores de busca.Eu espero ter explicado bem alguns conceitos básicos de SEO.

Finalmente,todas essas técnicas e truques são irrelevantes se você não tiver conteúdo de qualidade dentro de sua tag .Se o seu conteúdo for bom,pessoas irão linkar para sua página naturalmente.Links de outros sites para sua página são o fator mais importante para o ranking.Até a próxima!

SEO para ASP.NET – Parte 1

Todo desenvolvedor ASP.NET (ou pelo menos a maioria deles) deseja ter muitos visitantes em seu site.Google,Yahoo e outros mecanismos de busca podem lhe conseguir muitos visitantes especialmente se seu site for mostrado nas primeiras páginas.E vice-versa,se o seu site é mostrado na trigésima página ou nem for indexado você não vai ter nenhum resultado dos motores de busca.Como todo mundo quer ganhar  a primeira página há uma concorrência forte e você tem que se preocupar com cada fator que afeta o quanto sua página será amigável para os mecanismos de busca.

Existem mais de 100 importantes fatores usados pelos mecanismos de buscas para rankear as páginas.A maioria deles são somente especulações,uma vez que o Google,Yahoo e outros não querem revelar seus algoritmos de busca.Além,disso seus algoritmos são mudados frequentemente,(centenas de vezes anualmente),para aprimorar  a experiência do usário e melhorar os resultados das buscas.Nem mesmo o Google tem capacidade de manualmente mudar o ranking de uma página se ela achar que alguma deveria ser melhor ou pior rankeada.Por isto,SEO(Search Engine Optimization) é uma área muito dinâmica,mas basicamente as coisas mais importantes são sempre as mesmas.

Crie títulos únicos para as páginas

Toda página de seu site,deve ter um título único.O título deve ser pequeno,descritivo,significativo,conter palavras-chave e relevantes ao conteúdo da página.Não coloque frases repetidas,como o nome da empresa no inicio de cada título.Deixe suas informações mais relevantes aparecerem primeiro.A tag title,pode ser editada em tempo de design,mas você pode edita-lo usando a propriedade Page.Title com um código como este:

MyPageHeader.InnerText = “This Is My Catchy Header”;

Quando alguém usa a busca do Google,os termos da pesquisa são mostrados em negrito nos resultados da busca.Por isto,você precisa colocar palavras-chave no título para ter notoriedade e assim receber mais cliques.Claro,para atrair visitantes humanos seu título deve agrada-los também,não somente aos motores de busca.Você não deve somente listar palavras-chave sem sentido no título.Ao invés disso,deixe seus títulos com descrição precisa de cada página e você estará bem tanto com motores de buscas quanto com internautas.Não use títulos longos porque os motores de busca irão corta-los de qualquer maneira.Mantenha o título com menos de 65 caracteres.

Use as meta tags description e keyword

As tags description e keyword foram muito importantes para o SEO no passado,mas elas foram amplamente abusadas.Hoje em dia a meta tag keyword está praticamente em desuso,mas a meta tag description ainda é importante.Apesar de esta tag não melhorar suas perfomance no ranking de busca diretamente,indiretamente ela traz beneficios.Google geralmente usa a tag meta description quando mostra as curtas descrições do site nos resultados da busca.Então,se você criou alguma tag description,você pode atrair mais visitantes mesmo se você não estiver nos primeiros resultados da busca.Coloque descrições únicas para cada página.Assim como o título,você pode mudar a tag description em tempo de design ou via código do servidor:

protected void Page_Init(object sender, EventArgs e)
{HtmlMeta metaDescription = new HtmlMeta();
metaDescription.Name = “Description”;
metaDescription.Content = “Short, unique and keywords rich page description.”;
Page.Header.Controls.Add(metaDescription);

HtmlMeta metaKeywords = new HtmlMeta();
metaKeywords.Name = “Keywords”;
metaKeywords.Content = “selected,page,keywords”;
Page.Header.Controls.Add(metaKeywords);
}

Também funcionará se você usar master pages.

Uso da tag H1,

A tag H1 é muito importante, e ao mesmo tempo muito útil para melhorar seus resultados nas buscas.É melhor ainda se esta tag tiver o mesmo conteúdo da tag title.Apenas coloque o mesma palavra-chave,curta e relevante tanto na tag title quanto na H1 e este simples esforço vai aumentar significativamente seu ranking nas buscas.Como qualquer outra tag HTML,você pode pode mudar a tag H1 em tempo de design ou via código do servidor:

<h1 runat=”server” id=”MyPageHeader” ></h1>

Agora você pode manipular a tag H1 com código ASP.NET

MyPageHeader.InnerText = “This Is My Catchy Header”;

É importante lembrar,que as tags <h2> e <h3>
podem sem usadas para sub-cabeçalhos,e a tag <strong> pode ser usada para tornar algumas palavras-chave mais signficantes nos textos.

ASP.NET SEO Redirecionamento de URL

As vezes você precisa mover uma página para outra URL, ou mover o site inteiro para outro dominio.Um exemplo comum,se você atualizar seu site criado em ASP antigo para ASP.NET você precisará mudar as extensões dos arquivos de .asp para .aspx.Se algum visitante vier para o seu link antigo através de mecanismos de busca ou diretamente,ele deve ser direcionado para a nova URL.Há dois possíveis redirecionamentos:

  1. Redirecionamento temporário,retorna a mensagem “302  Found” .Esse redirecionamento deve ser usado somente quando necessário.
  2. Redirecionamento permanente,retorna a mensagem “301 Moved Permanently”,.Esse redirecionamento é usado pelo SEO para tranferir links para novos endereços.

Response.Redirect irá retornar o redirecionamento 302 ,então este não pode ser usado pelo SEO no ASP.NET.Para redirecionar permanentemente use o seguinte código:

Response.Status = “301 Moved Permanently”;
Response.AddHeader(“Location”, “/your-new-url/”);
Response.End();

Esse código é suficiente se você precisar mover uma única página.Mas se você precisa mover o site inteiro é melhor fazer isso no IIS.Vá até as propriedades do antigo site e selecione Home Directory Tab.Escolha,”A redirection to a URL”, e escreva a nova URL no textbox abaixo,como mostra a imagem:

Não esqueça de checar o checkbox, “A permanent redirection for this resource”,para receber o redirecionamento “301”.

Evite usar PostBacks

Alguns programadores,colocam Botões ou LinkButtons no webform e usam Response.Redirect,para navegar para outras páginas no evento de clique.Isto é um problema,porque os controles ASP.NET usam JavaScript para fazer PostBacks.Como “spiders”(motores de busca) web não trabalham com JavaScript muitas páginas não podem ser indexadas,e não irão aparecer nos resultados de busca.Para tornar um página visivel para mecanismos de buscas,tente evitar o uso de PostBacks.Ao invés de Buttons ou Linkbuttons ,coloque uma simples tag <a>.Textos nos links devem ser descritivos,evite links sem sentido como “Leia mais”,”Clique aqui” etc.

Se você precisar usar PostBack,então disponibilize alternativas de navegação,com simples Hyperlinks.Isso pode ser implementado no formulário do SiteMap.Sitemap pode ser uma página que contenha links para todas as páginas do seu site.Quando “spiders” visitarem seu sitemap,eles irão encontrar todas as outras facilmente.

Em breve continuarei com a Parte 2,aguarde.