Arquivo da tag: ASP.NET

Iniciando em Single Page Application – SPA

SPASPA – Single Page Application é uma novo modelo de desenvolvimento de aplicações Web e mobile que vem ganhando destaque em grandes empresas como Microsoft, Google, Twitter, Facebook, etc.

SPA basicamente significa codificar menos no server-side e mais no client-side. Ou seja, a aplicação estará contida toda ou quase toda no cliente (dentro do navegador Web). É praticamente uma aplicação Desktop rodando sob o navegador.

Vantagem:

1 – balanceamento da responsabilidade da execução entre cliente e servidor (agora não é só mais responsabilidade do servidor);
2 – menos código do servidor, e mais responsabilidade no cliente;
3 – melhorar a experiência ao usuário (UX) criando interface com usabilidade moderna e de fácil entendimento do usuário;
4 – menor consumo de banda, pois as cargas de dados são feitas por demanda e por AJAX.

O grande ator de app SPA é o código Javascript executado no cliente. Toda a aplicação pode ser construída simplesmente manipulando o DOM – Document Object Model de forma nativa, ou com o uso de bibliotecas e frameworks Javascript que auxiliam na construção da aplicação. Estas bibliotecas e frameworks fornecem recursos para manipulação dinâmica do DOM, definição de templates de tela, chamadas assincronas ao servidor, organização do código Javascript, etc. Dentres as diversas bibliotecas JS que surgem a todo momento, as mais difundidas na comunidade de progamadores estão: BACKBONE, EMBER, ANGULARJS e KNOCKOUT.

No lado servidor, temos a execução das linguagens tradicionais como PHP, ASP.NET, JSP, etc, trabalhando também de forma tradicional, servindo arquivos, acessando a banco de dados, tratando as regras de negócios que não podem estar no código JS por questões de segurança. E é neste lado (servidor) que podemos utilizar a arquitetura REST – Representational State Transfer para fornecer serviços do servidor para nossa aplicação SPA. É comum encontrar aplicação SPA utilizando serviços RESTFul. Uma aplicação no servidor que utiliza a arquitetura REST para servir serviços, então é chamada de RESTFul.

Ao construir uma aplicação utilizando a arquitetura REST, o protocolo HTTP é usado em sua essência, utilizando os verbos (ou métodos de requisição ao servidor): GET, POST, PUT e DELETE (estes são os mais comuns), e cada um deles indica uma determinada ação a ser executada em um recurso específico do servidor.

  • GET: Está requisitando ao serviço um determinado recurso, por exemplo, uma listagem de dados;
  • POST: Indica ao serviço que a ele deve receber o recurso que está sendo enviado e adicionar em algum repositório;
  • PUT: Indica que ao serviço que o recurso que está sendo enviado deve ser alterado se ele já existir, ou ainda, pode ser adicionado caso ele ainda não exista;
  • DELETE: Indica que o serviço deve excluir o recurso.

Pensando em banco de dados, temos o seguinte entendimento:

  • GET: Recupera dados [select];
  • POST: Realiza a inserção de dados [insert];
  • PUT: Realiza a alteração de dados [update];
  • DELETE: Realiza a exclusão de dados [delete].

WebAPI é o nome dado a solução da Microsoft dentro do .NET Framework para o desenvolvimento de serviços que utilizam o conceito REST.

Criando o projeto

No VisualStudio 2013, ao criar um projeto Web, está disponível opção para seleção do template WebAPI, como é a ideia deste post é relatar a criação de app SPA, então o template selecionado deverá ser Single Page Application, que é um projeto WebAPI preparado para receber as programações SPA:

projeto_tipo_spa

Sugestão da arquitetura do projeto:

spa_webapi_arqproj

 

  • pasta app: contém os arquivos que formam a aplicação que rodará no cliente, de fato a Single Page Application;
  • pasta app\controllers: controllers do angularjs;
  • pasta app\view: views do angularjs;
  • app\app.js: configuração da aplicação no cliente;
  • pasta App_Start: classes de configuração da aplicação no servidor;
  • pasta Content: CSS da aplicação utilizando nas views (app\views);
  • pasta Controllers: Classes controladoras a nível de servidor. É de fato os serviços RESTful;
  • pasta Script: Arquivos JS da aplicação;
  • index.html: Raiz da aplicação. Será o único arquivo HTML enviado do servidor ao cliente.

No arquivo WebApiConfig.cs (da pasta App_Start) contém a configuração das rotas da aplicação:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

Toda chamada a um método terá a URL assim: http://www.meusite.com.br/api/metodohttp/parametro.

Na configuração da api é importante padronizar o tipo de entrada e saída de dados. Para padronizar como JSON fica assim:

//padronizar JSON como retorno
config.Formatters.Remove(config.Formatters.XmlFormatter);

// Use camel case para serializar/deserializar JSON data.
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));

Um projeto WebAPI ou SPA segue praticamente a mesma estrutura do projeto MVC. A diferença está na herança das classes Controllers, pois ao invés de ser herdadas da classe Controller, são herdadas da classe abstrata ApiController.

Esta classe dispõem dos recursos necessários para o desenvolvimento de serviços RESTful. Nela estarão os métodos implementados para receber requisições de acordo com os verbos HTTP: GET, POST, PUT e DELETE.

Criando um controller

Toda classe controller deve estar na pasta Controllers e deve ter como sufixo a palavra “controller”:

  • ClienteController
  • PessoaController
  • ProdutoController

Para usar o assistente para criar a classe controller, basta adicionar a classe a partir do menu de contexto (botão direito do mouse) da pasta Controller:

spa_webapi_controller

Exemplo de classe gerada pelo assistente (o método GET foi alterado):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace SPAWebAPI.Controllers
{
    public class ClienteController : ApiController
    {
        // GET api/cliente
        public object Get()
        {
            return new { a = 1, b = 2};
        }

        // GET api/cliente/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/cliente
        public void Post([FromBody]string value)
        {
        }

        // PUT api/cliente/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/cliente/5
        public void Delete(int id)
        {
        }
    }
}

Invocando um método da classe ClienteController com AngularJS

var req = $http({
    url: '/api/Cliente'
});

req.success(function (data, status, headers, config, statusText) {

    console.log(data.a);
    console.log(data.b);

});

req.error(function (data, status, headers, config, statusText) {
    console.log(status);
});

Consumindo WebServices sem adicionar referências no VisualStudio

aspnet-tutorial1Olá pessoal.

Recentemente precisei consumir vários WebServices num mesmo projeto, sendo não queria criar uma referência estática pelo VS com cada um deles.
Pesquisando sobre essa necessidade, me deparei com o código abaixo. É uma classe capaz e invocar WebServices manualmente, montando a mensagem SOAP (inclusive com parâmetros) e enviando ao servidor e recuperando o retorno.

    internal class WebService
    {
        public string Url { get; set; }
        public string MethodName { get; set; }
        public Dictionary<string, string> Params = new Dictionary<string, string>();
        public XDocument ResultXML;
        public string ResultString;

        public WebService()
        {

        }

        public WebService(string url, string methodName)
        {
            Url = url;
            MethodName = methodName;
        }

        /// <summary>
        /// Invokes service
        /// </summary>
        public void Invoke()
        {
            Invoke(false);
        }

        /// <summary>
        /// Invokes service
        /// </summary>
        /// <param name="encode">Added parameters will encode? (default: true)</param>
        public void Invoke(bool encode)
        {
            string soapStr =
                @"<?xml version=""1.0"" encoding=""utf-8""?>
                  <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
                     xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
                     xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                     <soap:Body>
                         <{0} xmlns=""http://tempuri.org/"">
                          {1}
                        </{0}>
                     </soap:Body>
                  </soap:Envelope>";

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
            req.Headers.Add("SOAPAction", "\"http://tempuri.org/" + MethodName + "\"");
            req.ContentType = "text/xml;charset=\"utf-8\"";
            req.Accept = "text/xml";
            req.Method = "POST";

            using (Stream stm = req.GetRequestStream())
            {
                string postValues = "";
                foreach (var param in Params)
                {
                    if (encode)
                        postValues += string.Format("<{0}>{1}</{0}>", HttpUtility.UrlEncode(param.Key), HttpUtility.UrlEncode(param.Value));
                    else
                        postValues += string.Format("<{0}>{1}</{0}>", param.Key, param.Value);
                }

                soapStr = string.Format(soapStr, MethodName, postValues);
                using (StreamWriter stmw = new StreamWriter(stm))
                {
                    stmw.Write(soapStr);
                }
            }

            using (StreamReader responseReader = new StreamReader(req.GetResponse().GetResponseStream()))
            {
                string result = responseReader.ReadToEnd();
                ResultXML = XDocument.Parse(result);
                ResultString = result;
            }
        }

    }

Na hora de usar fica assim:

WebService ws = new WebService("service_url", "method_name");
ws.Params.Add("param1", "value_1");
ws.Params.Add("param2", "value_2");
ws.Invoke();
Response.Write(ws.ResultString);

Após invocar o WS basta acessar as propriedades ResultString ou ResultXML para recuperar o retorno no formato desejado.

Achei bem bacana a solução, ainda mais por dispensar a criação de referências diretamente no VisualStudio.

Fonte: http://stackoverflow.com/questions/9482773/web-service-without-adding-a-reference

ASP.NET Routing

aspnet-tutorial1O uso de URL amigáveis nos sites vem aumentando, principalmente após o surgimento do SEO – Search Engine Optimization. Este tipo de URL facilita a indexação pelos motores de busca e também para o usuário relembrar a URL que acessou.

Em ASP.NET a construção de URL amigaveis se dá por meio de Routings. Numa aplicação Web sem mapeamento de rotas, normalmente a solicitação de um navegador ocorre para um arquivo físico (página aspx): http://www.meusite.com.br/produtos.aspx?categoria=1001, sendo que a programação contida na página recupera o parâmetro por QueryString para tratar de forma dinâmica o conteúdo a ser enviado ao cliente.

Ao trabalhar com rotas, define-se padrões na organização da URL, não especificando o nome da página física que tratará a requisição, diferente do citado acima.

Uma sugestão de URL amigável para a URL tratada acima: http://www.meusite.com.br/produtos/categoria/informatica/smartphone, onde o padrão é http://www.meusite.com.br/produtos/categoria/{nome da categoria}/ {nome da subcategoria}. Desta forma, não é identificado o arquivo físico e a URL ainda fica mais agradável aos olhos do usuário.

Para implementar rotas em ASP.NET, o primeiro passo é a inclusão do arquivo global.asax ao projeto. O global.asax é uma classe que trata eventos a nível de aplicação e sessão, como por exemplo: quando a aplicação é iniciada ou finalizada, quando um sessão é criada ou destruída etc…

Os padrões de rotas devem ser especificados no evento Application_Start no global.asax, evento que ocorre quando a aplicação é iniciada.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;

namespace ExemploRouting
{
    public class Global : System.Web.HttpApplication
    {

       protected void Application_Start(object sender, EventArgs e)
       {

       }

    }
}

No global.asax temos acesso ao objeto RouterTable que expõe a propriedade Routes, é nesta propriedade que é realizado os registro das rotas da aplicação através do método MapPageRoute.

O método MapPageRoute dá suporte a várias sobrecargas, a mais simples, recebe por parâmetro (1) o nome da rota, (2) o formato/regra da rota, (3) a página física que tratará a requisição da rota, (4) e a indicação se haverá verificação de permissões de segurança para rota (se false, todos os usuários tem acesso e se true, apenas os usuários identificados no web.config).

Um exemplo para criar a rota http://www.meusite.com.br/produtos/categoria/subcategoria:

RouteTable.Routes.MapPageRoute(&quot;rotaprodutos&quot;, &quot;produtos/categoria/{categoria}/{subcategoria}&quot;, &quot;~/produtos.aspx&quot;, false);

A expressão {categoria} e {subcategoria} indicam que a rota terá dois valores dinâmicos (espécie parâmetros) que poderão ser recuperados pela página física.

Na regra acima, a requisição para http://www.meusite.com.br/produtos/categoria/informatica/smartphone será direcionada para a página produtos.aspx que receberá como parâmetro os valores “informatica” e “smartphone”, indicando a categoria e subcategoria.

Na página, os parâmetros são recuperados pela propriedade Values do objeto global RouteData, desta forma:

Response.Write(RouteData.Values[&quot;categoria&quot;]);
Response.Write(RouteData.Values[&quot;subcategoria&quot;]);

Para finalizar, podemos adicionar um quinto parâmetro ao método MapPageRoute, que define o valor padrão dos parâmetros da rota quando não fornecidos:

RouteTable.Routes.MapPageRoute(&quot;rotaprodutos&quot;, &quot;produtos/categoria/{categoria}/{subcategoria}&quot;, &quot;~/produtos.aspx&quot;, false, new RouteValueDictionary { { &quot;categoria&quot;, &quot;geral&quot; }, { &quot;subcategoria&quot;, &quot;todas&quot; } });

Neste exemplos, os valores padrões para categoria e subcategoria será “geral” e “todas”, respectivamente.

Também é posível criar regras de rotas diretamente no IIS (http://www.iis.net/learn/extensions/url-rewrite-module/creating-rewrite-rules-for-the-url-rewrite-module).

Fontes:

  • ASP.NET 4.5 – Curso Completo – Luís Abreu
  • http://msdn.microsoft.com/en-us/library/vstudio/cc668177(v=vs.100).aspx

Chamadas XMLHttpRequest (AJAX) enviando JSON para páginas aspx ou GenericHandler – Deserialização manual

json160 csharplogoOlá pessoal,

Realmente é muito simples realizar uma chamada XMLHttpRequest (AJAX) para um WebMethod ASP.NET. E mais fácil ainda é enviar dados no formato JSON para o WebMethod, pois por padrão o WebMethod deserealizada a string JSON conforme seus parâmetros.

Mas quando não temos um WebMethod para receber os dados no formato JSON e fazer todo o trabalho de sujo de deserialização? Por exemplo, ao fazer chamadas XMLHttpRequest para uma página ou um Generic Handler passando dados no formato JSON. Nesta situação é necessário realizar a deserialização dos dados manualmente, vamos a um exemplo.

Chamada XMLHttpRequest no lado cliente:

var request = $.ajax({
type: &quot;POST&quot;,
dataType: &quot;json&quot;,
url: &quot;/meusite/processa.ashx&quot;,
cache: false,
data: JSON.stringify({ p1: &quot;oi&quot;, p2: 1000, vet: [{ vp1: {vp2: &quot;xxxx&quot;}},2] })

});

request.done(function (r) {
console.log(r);
});

request.fail(function () {
alert(&quot;Não foi possível processar sua requisição.&quot;);
});

O código acima utiliza a biblioteca jQuery para encapsular o uso da biblioteca javascript XMLHttpResquest e enviar dados ao servidor. Em sua configuração, a propriedade “URL” indica um GenericHandler no servidor (processa.ashx), mas que também pode ser substituído por uma página aspx. E a propriedade “data” foi configurada com um objeto literal com propriedades simples e complexas, que antes de ser enviado ao servidor será transformando numa string JSON pelo método JSON.stringify.

No lado servidor (no GenericHandler ou no método page_load da página), a recepção dos dados fica assim:

JavaScriptSerializer jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();

Dictionary&lt;string, object&gt; values = jss.Deserialize&lt;Dictionary&lt;string, object&gt;&gt;(json);

string p1 = values[&quot;p1&quot;].ToString();
int p2 = Convert.ToInt32(values[&quot;p2&quot;]);

var vet = (ArrayList)values[&quot;vet&quot;];
var vp1 = ((Dictionary&lt;string, object&gt;)vet[0])[&quot;vp1&quot;];
var vp2 = ((Dictionary&lt;string, object&gt;)vp1)[&quot;vp2&quot;];

No código de servidor acima, a propriedade InputStream do objeto Request representa o conteúdo do corpo de entrada de conteúdo HTTP vindo do cliente, portanto, representa a string JSON enviada pelo cliente.

O inputString é recuperado e deserializado em um objeto Dictionary (espécie de lista indexada por chaves). Cada propriedade da string JSON torna-se uma chave do dicionário, sendo facilmente acessada:

int p1 = values[&quot;p1&quot;].ToString();
int p2 = Convert.ToInt32(values[&quot;p2&quot;]);

E também podemos acessar estruturas JSON mais complexas, como é o caso da propriedade “vet”, que mantém um vetor, cujo seu índice 0 (zero) contém outro objeto JSON.

vet: [{ vp1: {vp2: &quot;xxxx&quot;}},2]

Após recuperação do vetor, foi necessário converte o objeto de índíce 0 (zero) em outro Dictionary, desta forma, as propriedades do objeto contido no índice 0 (zero) da propriedade “vet” são acessadas por chaves do Dictionary.

var vp1 = ((Dictionary&lt;string, object&gt;)vet[0])[&quot;vp1&quot;];
var vp2 = ((Dictionary&lt;string, object&gt;)vp1)[&quot;vp2&quot;];

E fim.

ASP.NET MVC: Dica de site

Olá pessoal.

Estou passando para deixar os links abaixo. São dicas sobre o ASP.NET MVC que vão direto ao ponto. Vale a pena conferir.

 

Espero que seja útil. Para mim foi!!!

O poder de usar Visões Parciais (partial views) com JQuery

Estou tentando aprender como criar página Web usando o Pattnern MVC 3 que acompanha o VisualStudio 2010. E hoje aprendi algo que me fascinou (pois no ASP.NET tradicional não é tão simples), invocar WebUserControls em chamadas AJAX. Vamos lá.

Uma Partial View é uma espécie de WebUserControl do MVC, ou seja, é possível criar pedaços de código a serem reaproveitados posteriormente em outras páginas.

Com o MVC é possível invocar via chamadas AJAX (neste caso com JQuery) Partial Views, ou seja, de forma simples posso via Ajax trazer o conteúdo da View que está no servidor.

A primeira coisa é criar a referência para biblioteca JQuery numa View normal ou MasterPage. E depois criar a Partial View e seu respectivo Action Controller.

Partial View OutroCurso.ascx:


&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;width: 608px&quot;&gt;
    &lt;tr&gt;
        &lt;td style=&quot;width: 288px&quot;&gt;
            Se sim, qual curso?&lt;br /&gt;
            &lt;%:Html.TextBox(&quot;txtQualCurso&quot;, &quot;&quot;, new { maxlength = &quot;10&quot;, style = &quot;width:264px&quot; })%&gt;
        &lt;/td&gt;
        &lt;td&gt;
            Em qual instituição?&lt;br /&gt;
            &lt;%:Html.TextBox(&quot;txtQualInstituicao&quot;, &quot;&quot;, new { maxlength = &quot;10&quot;, style = &quot;width:264px&quot; })%&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;

Action Controller da Partial View OutroCurso.ascx:


public ActionResult OutroCurso()
{
    return PartialView();
}

E por fim, falta fazer a chamada AJAX para a Partial View acima dentro de uma View normal ou MasterPage.

A ideia do código abaixo é que o usuário ao selecionar o radiobutton SIM, apareçam outros campos a serem preenchidos (a Partial View). Observe que cada radionbutton em seu evento onclick chama a função JavaScript loadPartialViewOutroCurso, responsável por usar o método Load disponível na biblioteca JQuery para invocar a Partial View no servidor.

Possui outro curso superior?&lt;br /&gt;
&lt;%:Html.RadioButton(&quot;rblOutroCurso&quot;, &quot;N&quot;, false, new { onclick = &quot;loadPartialViewOutroCurso('N')&quot; })%&gt; Não
&lt;%:Html.RadioButton(&quot;rblOutroCurso&quot;, &quot;S&quot;, false, new { onclick = &quot;loadPartialViewOutroCurso('S')&quot; })%&gt; Sim
&lt;div id=&quot;divOutroCurso&quot;&gt;&lt;/div&gt;

&lt;script type=&quot;text/javascript&quot;&gt;

    function loadPartialViewOutroCurso(opcao) {

        if (opcao == 'S')
            $('#divOutroCurso').load('/Solicitacao/OutroCurso');
        else $('#divOutroCurso').html(&quot;&quot;);
    }

&lt;/script&gt;

A URL a “/Solicitacao/OutroCurso” é a rota para o Action (OutroCurso) do Controller (Solicitacao) que mantém a Partial View.

Bom né?

Abraço e até a minha próxima descoberta no mundo MVC.

Mantendo o estado em páginas ASP.NET

Protocolo HTTP é um protocolo que não armazena informações entre suas requisições e resposta (stateless).

Não há implementações no protocolo HTTP que requisite que o browser identifique a si mesmo em cada requisição. Também não há nenhuma conexão estabelecida entre o browser e o servidor que persista entre uma página e a próxima, ou entre requisições para a mesma página, ou seja, o servidor envia os dados requisitados pelo cliente e não armazena nenhuma informação de estado. Se o cliente solicita a mesma informação, mesmo em um período de tempo pequeno, o servidor envia novamente sem nenhum critério.

Em qualquer desenvolvimento de sistemas Web pode ser aplicado técnicas de persistência de informações entre as requisições do usuário, como session e cookie. Além desta duas formas, no ASP.NET é possível usar um novo recurso chamado de VIEWSTATE.

Session

  • São informações armazenadas no servidor web para cada usuário de um determinado site;
  • Cada usuário possui suas próprias variáveis de sessão;
  • São destruídas ao fechar o navegador, ou no seu timeout, ou ainda quando solicitado pela aplicação;
  • As variáveis de sessões são globais dentro da sessão do usuário (qualquer página do servidor Web pode acessá-las).

Armazenando

Session.Add("INFORMACAO","Valor a ser armazenado");

Recuperando

if (Session["INFORMACAO"] != null) //testando a existência da session
    string x = Session["INFORMACAO"].ToString();

É importante testar a existência da session antes de tentar recuperar seu valor. Caso ela não exista, é disparado um erro ao tentar recuperar o valor.

Destruindo

Session.Remove("INFORMACAO");

Cookie

  • Trata-se de um pequeno arquivo de texto que é armazenado na máquina do usuário;
  • Cada site possui suas próprias cookies no computador do usuário;
  • Usado, por exemplo, em sites de comércio eletrônico, para exibir as  preferências e características do usuário;
  • São destruídas ao fechar o navegador, ou quando seu tempo de vida expira, ou ainda quando solicitado pela aplicação;
  • Pode identificar o usuário mesmo dias depois de seu acesso a página;
  • O grande problema dos cookies é que o usuário simplesmente pode desabilitar este recurso em seu navegador.

Armazenando

HttpCookie cookie = new HttpCookie("INFORMACAO");
cookie.Value = "Valor a ser armazenado";

//Envia a cookie ao cliente
Response.Cookies.Add(cookie);

É possível manipular o tempo de vida da cookie no cliente. No exemplo abaixo a cookie tem um tempo de vida de 7 dias.

cookie.Expires = DateTime.Now.AddDays(7);

//Envia a cookie ao cliente
Response.Cookies.Add(cookie);

Recuperando

if (Request.Cookies["INFORMACAO"] != null)
{
    string x = Request.Cookies["INFORMACAO"].Value;
}

É importante testar a existência da cookie antes de tentar recuperar seu valor. Caso ela não exista, é disparado um erro ao tentar recuperar o valor.

Destruindo
Para destruir a cookie é necessário definir um tempo de vida menor que o atual. Depois é só enviá-la ao cliente.

if (Request.Cookies["INFORMACAO"] != null)
{
    HttpCookie cookie = Request.Cookies["INFORMACAO"];
    cookie.Expires = DateTime.Now.AddDays(-1);

    //Envia a cookie ao cliente
    Response.Cookies.Add(cookie);
}

Para confirmar a operação criação/definição de valores e destruição da cookie é requerido seu envio ao browser cliente. Observe nos exemplos acima o uso do Response.Cookie.Add para enviá-la ao cliente.

ViewState

  • Mantêm automaticamente os valores de controles de servidor entre um postback e outro;
  • Internamente funciona como um campo oculto (hidden) um pouco mais sofisticado (__VIEWSTATE);
  • O ViewState é mantido somente na página, ao sair da página ele é perdido;
  • Ao rodar uma aplicação ASP.NET sem qualquer controle verá que é criado um campo oculto para o armazenamento do ViewState;
  • Os dados não são exibidos em texto plano, por questões de segurança;
  •  Pode-se ainda adicionar manualmente valores a um ViewState.

Armazenando

ViewState.Add("INFORMACAO","Valor a ser armazenado");

Recuperando

if (ViewState["INFORMACAO"] != null) //testando a existência do viewstate
    string x = ViewState["INFORMACAO"].ToString();

É importante testar a existência do viewstate antes de tentar recuperar seu valor. Caso ele não exista, é disparado um erro ao tentar recuperar o valor.

Destruindo

ViewState.Remove("INFORMACAO");

Até o próximo post.

Segurança em aplicações ASP.NET

Pessoal.

O link abaixo é para um artigo da Microsoft que dá dicas de como proteger seus aplicativos ASP.NET contra ataques de XSS usando validação de entrada e codificação de saída apropriadas. Ele também descreve vários outros mecanismos de proteção que podem ser usados, além dessas duas medidas importantes.

http://msdn.microsoft.com/library/ms998274.aspx

E a Microsoft disponibiliza uma DLL chamada “Microsoft Anti-Cross Site Scripting Library V4.0” que fornece meios para validar a entrada de dados em aplicação ASP.NET.

http://www.microsoft.com/download/en/details.aspx?id=5242

Até mais…

DataList com paginação

O controle DataList do ASP.NET é uma mão da roda para exibir listagem de dados usando um layout menos “tabular”. Infelizmente o DataList não possui de forma nativa (como no GridView, FormView e DetailsView) uma opção para definir páginas de dados (paginação). Mas isso não é problema, pois podemos implementar “na unha” esse recurso.

Vamos lá.

Neste exemplo usei a tabela Products do banco de dados de exemplo Northwind que acompanha o SQL Server Express 2008. E a paginação é de 10 registros por página.

A seguir segue o código de definição de um DataList para listagem de registros vindos da tabela Products. Observe que adicionei ao FooterTemplate dois LinkButton para representar a navegação da paginação.

&lt;asp:DataList ID=&quot;DataList1&quot; runat=&quot;server&quot;&gt;
    &lt;FooterTemplate&gt;
        [&lt;asp:LinkButton ID=&quot;lkbtnAnterior&quot; runat=&quot;server&quot; onclick=&quot;lkbtnAnterior_Click&quot;&gt;&amp;lt;&amp;lt; Anterior&lt;/asp:LinkButton&gt;]
        [&lt;asp:LinkButton ID=&quot;lkbtnProximo&quot; runat=&quot;server&quot;  onclick=&quot;lkbtnProximo_Click&quot;&gt;Próximo &amp;gt;&amp;gt;&lt;/asp:LinkButton&gt;]
    &lt;/FooterTemplate&gt;
    &lt;ItemTemplate&gt;
        ProductID: &lt;%#DataBinder.Eval(Container.DataItem, &quot;ProductID&quot;).ToString()%&gt;
        &lt;br /&gt;
        ProductName: &lt;%#DataBinder.Eval(Container.DataItem, &quot;ProductName&quot;).ToString()%&gt;
        &lt;br /&gt;
        UnitPrice: &lt;%#DataBinder.Eval(Container.DataItem, &quot;UnitPrice&quot;, &quot;{0:C}&quot;).ToString()%&gt;
        &lt;hr /&gt;
    &lt;/ItemTemplate&gt;
&lt;/asp:DataList&gt;

O código C# abaixo representa um método criado na página para tratar a listagem dos dados, inclusive por fazer a paginação. O código por ser adaptado para qualquer realidade.

protected void ListarDados(string tipo)
{
    int tamanhoPagina = 10;
    int registroInicio = 0;

    if (ViewState[&quot;registroInicio&quot;] != null)
        registroInicio = (int)ViewState[&quot;registroInicio&quot;];

    if (tipo == &quot;proximo&quot;)
        registroInicio += tamanhoPagina;
    else if (tipo == &quot;anterior&quot;)
        registroInicio -= tamanhoPagina;

    if (registroInicio &lt; 0)
        registroInicio = 0;

    SqlConnection con = new SqlConnection(@&quot;Data Source=localhostSQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True&quot;);
    SqlCommand cmd = con.CreateCommand();
    cmd.CommandText = &quot;SELECT PRODUCTID, PRODUCTNAME, UNITPRICE FROM PRODUCTS &quot;;

    con.Open();

    SqlDataAdapter da = new SqlDataAdapter();
    da.SelectCommand = cmd;
    DataTable dt = new DataTable();

    //Preenchendo o DataTable com a quantidade de registro que se pretende mostrar.
    da.Fill(registroInicio, tamanhoPagina, dt);

    //Tratando o fim da navegação
    if (tipo == &quot;proximo&quot; &amp;&amp; dt.Rows.Count == 0 &amp;&amp; registroInicio &gt; 0)
    {
        registroInicio -= tamanhoPagina;
        da.Fill(registroInicio, tamanhoPagina, dt);
    }

    DataList1.DataSource = dt;
    DataList1.DataBind();
    con.Close();

    ViewState.Add(&quot;registroInicio&quot;, registroInicio);
}

O código abaixo implementa os botões de navegação.

protected void lkbtnAnterior_Click(object sender, EventArgs e)
{
    ListarDados(&quot;anterior&quot;);
}

protected void lkbtnProximo_Click(object sender, EventArgs e)
{
    ListarDados(&quot;proximo&quot;);
}

Para listar os dados e mostrar a primeira página, chame o método ListarDados sem informar as opções de navegação. Desta forma:


    ListarDados(&quot;&quot;);

Baixe aqui o exemplo.

Para deixar mais eficiente o recurso de paginação, recursos do próprio banco de dados como a funções TOP, FIRST, LAST e etc podem ser utilizados.

Hospedagem de aplicações ASP.NET

Olá pessoal.

 A Microsoft disponibiliza um site que facilita a vida quando o assunto é encontrar um serviço de hospedagem para nossa aplicações Web. A URL do site é http://www.microsoft.com/web/Hosting/Home.

Infelizmente não há nenhum grátis, mas há serviços a menos de 20 Reais por mês.

Abração.