Mais acessados

sexta-feira, 30 de agosto de 2013

ASP.NET MVC - Postando Listas ou Coleções de objetos sem alterar o ModelBinder padrão

Uma das maiores mudanças ocorridas no ASP.NET MVC desde a sua criação, pelo menos em minha opinião, foi a incorporação do ModelBinder. O ModelBinder é responsável pela construção do modelo no server baseado no parâmetro da Action e os nomes dos inputs que foram postados em um formulário. Dessa forma, não é preciso iterar sobre um FormCollection para recuperar as informações enviadas, basta apenas colocar como parâmetro o modelo que deseja receber. Neste breve post vou mostrar como enviar uma coleção qualquer para o servidor sem ter que alterar o ModelBinder padrão do ASP.NET MVC


O problema

Quando criamos um formulário, os HtmlHelpers cuidam do trabalho pesado e já constroem automaticamente todos os atributos necessários nos inputs Html. O principal atributo é o name, que é usado pelo ModelBinder para colocar o valor na propriedade certa quanto o formulário é postado para o server.


Esse attribute name vem direto da Lambda Expression que passamos. Por exemplo, ao criamos um formulário com uma lista usando o foreach , o body da Lambda Exmpression é usado para o name, repare no HtmlHelper e HTML gerado:


View/Task/UpdateMany.cshtml

Html gerado

Isso está errado, quando estamos falando de Listas. O ModelBinder não entenderá que o que será postado é uma coleção de objetos e não conseguirá reconstruir essa lista de novo no server, resultado, você terá um null como abaixo:

Controllers/Task.cs

A solução

Para fazer funcionar basta alterar o foreach por um for, assim os HtmlHelpers vão criar a coisa certa, como abaixo:


View/Task/UpdateMany.cshtml

Html gerado

Veja que agora o name está diferente, parece com um índice de um Array. Quando o form for postado o ModelBinder vai identificar esse padrão dentro da request e reconstruir o formulário como se fosse uma lista, logo você receberá a coisa certa no server.

Controllers/Task.cs

Quando for criar qualquer tipo de formulário com lista, preocupe-se então com o name, mesmo se não estiver usando os HtmlHelpers use sempre esse padrão que o ModelBinder fará todo o trabalho duro para você.

Espero que tenham gostado do post. O exemplo completo pode ser baixado aqui.

Referências:

quarta-feira, 21 de agosto de 2013

ASP.NET MVC - Validação de Datas sem complicação, JQuery Validation + JQuery.Globalize

Recentemente um amigo que começou a desenvolver em um projeto em ASP.NET MVC questionou a respeito da validação de datas. A validação sempre falha em server e client se você usar o campo do tipo DateTime e as DataAnnotations que o MVC traz. Como "paliativo" o pessoal usa um campo string e RegularExpressionAttribute, depois transfere esse valor para o campo DateTime original.


Data Válida, mas falha.



Porém, isso não é necessário, o que acontece é um problema com o localization do JQuery Val que não consegue validar o formato dd/MM/yyyy sem uma "ajuda". Neste post vou mostrar como concertar isso.


Instalando jquery.globalize

O jquery globalize é uma biblioteca de globalization e localization. Vou usá-la para parser da data que será validada.

Para instalar:

  1. Clique com botão direito na Solução->Manage Nuget Packages
  2. Vá em Online e digite na caixa Jquery Globalize


Agora é necessário adicionar o  jquery.globalize ao nosso BundleConfig

App_Start/BundleConfig.cs

Modificando a função de validação de datas do Jquery Val

Agora vem a parte "hardcoding". Com o jquery globalize vamos usar a função parseDate para validar nosso formato.

Views/Task/Create.cshtml

Na função acima estou alterando o método date para que a validação ocorra da forma que eu quero. Veja em Azul o formato que especifiquei. Logo, qualquer coisa diferente disso que for digitado em um campo com validação para data vai falhar.

O ideal é que você crie um arquivo de Script e coloque uma função anônima dentro para reutilizar.

Exemplo

Agora no ASP.NET é possível usar o seu campo com DateTime, sem problemas.

Models/Task.cs

View/Task/Create.cshtml

O campo pode ser criado normalmente. Quando você cria o campo como DateTime, por baixo dos panos o Html Helper já coloca que o campo é para ser validado como Data.

HTML Resultado para o Campo DateTime

Agora a validação funciona:

Espero que tenham gostado, o código fonte do exemplo pode ser baixado aqui.

terça-feira, 13 de agosto de 2013

ASP.NET Web API - Criação de select (DropDownList) em cascata, usando Ajax, JQuery e JSON.

Essa semana estava criando um sistema e me deparei com um problema relacionado a select list (nome da tag HTML, mas conhecido como Drop Down List no mundo Windows) encadeados. O sistema teria vários desses select em cascata.

Como um bom programador, resolvi encapsular a lógica deste em algum lugar, para futuro reuso. Então surgiu a ideia de criar uma extensão do JQuery que já fizesse o trabalho duro. É necessário Visual Studio 2010/2012 com o template do ASP.NET MVC 4 Project instalados.

Criando o projeto Web Api


No Visual Studio, para um novo projeto:
  1. File->New Project-> Templates->Installed Templates->Visual C#->ASP.NET MVC 4 Web Application
  2. Na janela selecione Web API.
Caso já tenha um projeto MVC:
  1. Adicione referência para System.Web.Http.WebHost.
  2. Adicione o arquivo App_Start\WebApiConfig.cs (use como exemplo o código do post).
  3. Adicione using System.Web.Http in Global.asax.cs.
  4. Chame WebApiConfig.Register(GlobalConfiguration.Configuration) na função Start Global.asax.csantes da rota MVC, por causa de sua precedência.

A ideia

O principal objetivo era diminuir a complexidade de criar o cascateamento e também performance, dado que o resultado é em JSON, diminuindo assim, o tráfego de dados. Principalmente porque eu o usaria para mobile.

O cascateamento de componentes é recursivo por natureza. Então resolvi usar os novos padrões HTML5 data-* (chamado de "data dash attribute"), que salva as informações para que o select saiba seu comportamento. A url de origem dos dados, os parâmetros a serem passados, paramName, quem dispararia o evento para ele ser preenchido, o parentSelectId e um texto padrão que este teria vazio ou não selecionado o defatulText.

Chamada do método

A Web API

Criei um objeto SelectOption  que remete ao que é esperado pelo jquery-cascadeselect (esse o nome da extensão que crie :D).  Então nossos métodos devem preencher e retornar esse objeto.

Model/SelectOption.cs


Padrão do JSON gerado

No exemplo eu vou usar Estado, Cidade e Região. Veja que retorno em cada método de API é uma lista de SelectOption. Preste atenção também nos parâmetros. Vamos usá-los mais tarde.

Controller/SearchController.cs


Na configuração do Web API, adicionei a action na rota, porque temos mais de um método GET dentro do mesmo controller, caso contrário  o Routing não irá resolver o endereço requisitado. Além disso, JSON foi colocado como padrão de retorno.

App_Start/WebApiConfig.cs

Uso

O uso é bem simples, basta chamar como se fosse um método do JQuery, dado que é uma extensão. No exemplo abaixo estou usando com ASP.NET Web API, mas não há restrições, o endereço passado só deve garantir que seja retornado JSON no formato correto .

Cascateamento entre Regiões, Estado e Cidades


Lembra-se dos parâmetros da nossa WebAPI? Por exemplo regiaoId, o nome deve ser idêntico para que o GET seja feito corretamente.

HTML exemplo

Resultado

Abaixo está o resultado, o jquery-cascadeselect cuida da parte chata de lógica automaticamente. Ao mudarmos as seleções os select são populados segundo a configuração feita. No exemplo clássico abaixo tenho Região, Estado, e Cidade:

Regiões é o pai de todos, então já vem populado

Mudando a seleção de Região o Estado é populado

Mudando a seleção de Estado vêem as Cidades

Contribua

Eu criei uma entrada no Git Hub para jquery-cascadeselect. Não sou nenhum "expert" em JavaScript, então o código pode estar um pouco "bagunçado" e sem padrão, mas está funcionando que é uma maravilha :D! Se você tem interesse em contribuir acesse. 

Espero que tenham gostado. O exemplo que usei para testar, igual ao das imagens acima, pode ser baixado aqui.


terça-feira, 6 de agosto de 2013

ASP.NET Web API - AutoComplete com imagem usando Web API, Jquery UI e JSON

No último post sobre ASP.NET Web API, ASP.NET Web API - AutoComplete usando Web API, Jquery UI e JSON mostrei como fazer um simples AutoComplete. Nesse artigo vou mostrar como incrementar o que foi feito anteriormente, possibilitando exibir a imagem do que está sendo pesquisado, ou até mais informações para cada item. É necessário uma revisão post mencionado e o Visual Studio 2010/2012 com o template do ASP.NET MVC 4 Project instalados.


AutoComplete com Imagem


Criando o Modelo AutoComplete

No artigo anterior o nosso AutoComplete exibia apenas um texto para o usuário. Nosso modelo então precisa de um pequeno "upgrade" :). Precisamos de um AutoCompleteImageModel, que terá além informações básicas padrão para o Jquery UI AutoComplete , também caminho da imagem de cada item.


 Model/AutoCompleteImageModel.cs

Modificando a View

A versão original do AutoComplete não possui overflow, logo, quando o resultado traz muitos itens fica uma "bagunça". Para solucionar isso basta alterar o css, conforme uma solução como esta: Jquery UI Scrollable Results.

Content/Site.css

Basicamente alterei o css padrão do AutoComplete para ter um tamanho máximo e exibir a scrollbar.

Para nossa Imagem e descrição do AutoComplete, criei o css abaixo:

Content/Site.css

Modificando a função JavaScript

A api do Jquery UI é bem robusta, logo a personalização é algo que estava em mente quando foi construída. É possível então no AutoComplete modificar o template que é exibido para o usuário. Logo, existe o Jquery UI AutoComplete custom data. O exemplo que vou usar é bem parecido com o do site oficial.

Views/Home/Index.cshtml


O item é nosso objeto JSON espelho do AutoCompleteImageModel, logo item.value, item.label e item.image são exatamente o que criamos no servidor.

Resultado JSON para a API

Em amarelo está mudança que fiz ao log. Ao selecionarmos um item o log exibirá o mesmo que está no AutoComplete.


Em azul está o Html personalizado. O AutoComplete é uma tag ul, que passamos por parametro por essa função do proprio Jquery. Na ul é possível adicionar qualquer Html personalizado como eu fiz. Coloquei a imagem, o código e o modelo que vem do nosso JSON. 

É possível colocar praticamente qualquer coisa, o único cuidado é que o conteúdo tem que estar dentro de uma tag a.


Finalizando

Na parte Web API o que foi mudado é que populo o novo modelo já com o caminho da imagem que será exibida de cada item.

O resultado é esse:




Ao selecionar um item este vai para o log:


Espero que tenham gostado, o exemplo pode ser baixado aqui.


sexta-feira, 2 de agosto de 2013

ASP.NET MVC - Criando um HtmlHelper personalizado, CheckBoxList

O ASP.NET MVC dá ao desenvolvedor todo o controle sobre o código HTML que será gerado. De uma forma geral, programar em HTML puro é bem improdutivo. Para  facilitar o desenvolvimento , foram criados os HtmlHelpers, métodos que encapsulam a lógica de como as tags são criadas e facilitam a vida do programador. Neste breve artigo vou mostrar como fazer um HtmlHelper personalizado, mais precisamente um CheckBoxList. É necessário Visual Studio 2010/2012 com o template do ASP.NET MVC Project instalado.


Criando a estrutura do Projeto

No Visual Studio, para um novo projeto:
  1. File->New Project-> Templates->Installed Templates->Visual C#->ASP.NET MVC 4 Web Application
  2. Na janela selecione o projeto que desejar.
Caso já tenha um projeto MVC;
  1. Adicione uma nova classe CheckBoxListHelper que irá encapsular nosso Helper . (Eu criei um diretório Helpers dentro da raiz do projeto para colocar todos os Helpers. Nada impede que você coloque esses Helpers em um projeto separado para utilizar em outro lugares).
  2. Adicione as seguintes referências ao arquivo:

Criando o CheckBoxListHelper

Se você já programou em ASP.NET MVC, já deve ter criado um DropDownList. Para isso deve ter usado SelectList e SelectListItem. Seguindo a mesma lógica, vou criar um CheckBoxItem CheckBoxList que serão usados para gerar o HTML.

Helpers/CheckBoxListHelper.cs

Helpers/CheckBoxListHelper.cs


Agora é só começar o "hardcoding" :). Um HtmlHelper nada mais é que um Extension Method da classe HtmlHelper. Logo, deve ser criada uma classe static, e o método static deve receber como parametro "this HtmlHelper htmlHelper".


Helpers/CheckBoxListHelper.cs

Veja que passo como parâmetro a legenda, que será exibida no topo do fieldset, o CheckBoxList e os objetos htmlAttributes, para o desenvolvedor personalizar as tags geradas

A classe TagBuilder é usada para construir uma tag HTML qualquer, bastando apenas passar o seu nome para o construtor. Ela oferece várias comodidades, como por exemplo, poder setar o InnerHtml e gerenciar os atributos HTML.

Helpers/CheckBoxListHelper.cs

O código é bem simples, uso um fieldset, seto a legenda vindo do parametro e construo uma ul com a lista ChekBoxList. Usei o próprio helper CheckBox para gerar o campo. Perceba que eu concateno coisas. Isso mesmo!!! O que é gerado nada mais é que String, mais especificamente MvcHtmlString.

Usando o Helper


É cômodo adicionar a referência no Web.config. Dessa forma não é necessário importa o namespace em todas as Views que você criar.

Views/Web.config
Agora basta utilizar o Helper:

O resultado gerado por esse Helper é esse:
Html
Espero que tenham gostado do artigo. O código de exemplo pode ser baixado aqui.

quinta-feira, 1 de agosto de 2013

ASP.NET Web API - AutoComplete usando Web API, Jquery UI e JSON

ASP.NET Web API é um framework para construir APIs web em cima do .NET Framework. Neste tutorial, vou mostrar com fazer um simples AutoComplete usando WebApi retornando JSON e Jquery UI. É necessário Visual Studio 2010/2012 com o template do ASP.NET MVC 4 Project instalados.

Criando o projeto Web Api

No Visual Studio, para um novo projeto:
  1. File->New Project-> Templates->Installed Templates->Visual C#->ASP.NET MVC 4 Web Application
  2. Na janela selecione Web API.
Caso já tenha um projeto MVC:
  1. Adicione referência para System.Web.Http.WebHost.
  2. Adicione o arquivo App_Start\WebApiConfig.cs (use como exemplo o código do post).
  3. Adicione using System.Web.Http in Global.asax.cs.
  4. Chame WebApiConfig.Register(GlobalConfiguration.Configuration) na função Start Global.asax.csantes da rota MVC, por causa de sua precedência.

Criando o Modelo AutoComplete

Para criar o nosso resultado JSON vou usar um modelo que pode ser reutilizado toda vez que precisarmos da funcionalidade, chamado AutoCompleteModel. Esse modelo possui os campos padrão que a função do Jquery UI utiliza. Segundo a documentação oficial pode ser de duas maneiras:
  • Lista de Strings: [ "Choice1", "Choice2" ]
  • Array de objetos com as propriedades label evalue:[ { label: "Choice1", value: "value1" }, ... ]

Neste exemplo vou trabalhar com o Array de objetos, que será representado pelo objeto AutoComplete. Na maioria dos casos o desenvolvedor trabalha neste modelo, dado que é necessário usar o Value, que pode representar uma chave primária ou outra informação que será essencial para executar alguma lógica ao submeter o form.

     Model/AutoCompleteModel.cs

Criando nossa API

Nossa API será bem simples, vamos criar uma Action que retorne uma lista de AutoComplete passando como parametro uma string com nome term. Fica como observação que term é o nome padrão que o Jquery UI AutoComplete usa na requisição, logo seu método action deve receber exatamente esse nome nesse caso.


Controller/AutoCompleteController.cs


Especificando AcceptVerbs na Action nos permite que chamemos nosso método como api/AutoComplete/Cars. Mas fazendo isso se faz necessário especificar também o método, no nosso caso é um GET, então HttpGet. Isso é somente perfumaria, para que fique mais legível a url.


Configurando a API

A configuração de rotas que vou usar é a que vem por padrão no projeto. Uma coisa que deve ser mudada está relacionado com o Formatter. Por padrão, o Formatter utilizado no Web Api é o XML, mas no nosso caso queremos JSON. Outra coisa está relacionada ao nome das propriedades, dado que em nosso modelo elas estão em case diferente do que é requerido pela função (está Value, precisa ser value).

App_Start/WebApiConfig.cs

Nossa Api já está funcionando, podemos acessá-la pelo próprio browser.


Criando os campos View

Na View haverão dois campos: um input que será usado para autocomplete e um div de log que receberá o que for selecionado. Eu usei basicamente o mesmo html que está no site de referência do Jquery UI Autocomplete.

  Views/Home/Index.cshtml

Esse HTML nos dá como resultado o seguinte:


Criando a função JavaScript

Para o auto complete foi usado o Jquery UI AutoComplete. O exemplo é simples, vamos consultar remotamente nosso caminho de API, retornar um JSON já no formato esperado e ao selecionarmos um elemento esse será colocado no campo Result. A função foi baseada no exemplo do site oficial do Jquery, fiz algumas alterações apenas para adequar o source a nosso local e os nomes dos campos que mudei.


 Views/Home/Index.cshtml

Finalizando

Já com tudo pronto é possível utilizar nosso autocomplete. Ao digitar dois ou mais caracteres o campo exibe as opções de busca.


Ao selecionar um registro, é adicionado ao Log.


Web API e JSON trazem benéfícios impressionantes em relação a banda. A requisição dessa lista auto complete por exemplo não passou de 502 bytes. Espero que tenham gostado, o exemplo pode ser baixado aqui.