Temple Coding

  • Home
  • Open Source
  • Sobre
    • Livros que estou lendo
    • Sobre
RSS
Category Archives: ASPNET MVC

Injeção de Dependência em Atributos/Filtros do MVC

Posted on 26/09/2011 by vintem
No Comments

É muito comum termos dropdowns/combos que contém o mesmo tipo de dados em páginas diferentes. Por exemplo digamos que seja necessário um combo com status em diferente páginas do projeto e que esses diferentes status tenham que vir do banco de dados.

Uma forma de mostrar isso na página, é salvar uma lista com os status que você pega do banco de dados na propriedade ViewData e exibir na página.

Como não devemos repetir esse código sempre, o que eu fiz foi criar um filtro do ASP.Net MVC e decorar as actions que precisam desses dados com esse filtro. Essa classe ficou assim:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
public class ListaStatusAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var repository = new NHibernateRepository();
        var tiposDocumento = repository.FindAll().OrderBy(t => t.Descricao);
        var controllerBase = filterContext.Controller;
        controllerBase.ViewData.Add("Status", tiposDocumento);
    }
}

Ótimo, agora é só decorar as actions com esse atributo. No ViewData teremos um item chamado Status com todos os status ordenados pela descricao. Um código feito uma vez só. Mas o que eu não gosto do código acima é que eu crio dentro da método uma instância da classe NHibernateRepository. Eu gostaria que isso fosse resolvido sem que uma dependência direta fosse criada para essa classe, afinal eu sei que essa classe implementa a interface IRepository, portanto eu posso ter uma dependência para a interface, o que é muito mais elegante.

Ultimamente eu tenho usado o Windsor para resolver todas as minhas dependências. E nesse caso vou usá-lo em conjunto com o ServiceLocator da Microsoft Enterprise Library. Se você já usa o Windsor é bem fácil de resolver, se não usa, dê uma olhada no tutorial no site do projeto e verá como é fácil usá-lo junto com o MVC.

Uma vez com seus componentes registrados, adicione uma referência para Microsoft.Practices.ServiceLocation.dll e no global.asax faça o seguinte:

?View Code CSHARP
1
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));

Isso vai adicionar ao ServiceLocator um provedor de serviços que será implementado usando o Windsor.
 A classe WindsorServiceLocator pode ser encontrada para download aqui.

Pronto, agora dentro do meu atributo eu posso trocar o código para:

?View Code CSHARP
1
2
3
4
5
6
7
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    var repository = ServiceLocator.Current.GetInstance();
    var tiposDocumento = repository.FindAll().OrderBy(t => t.Descricao);
    var controllerBase = filterContext.Controller;
    controllerBase.ViewData.Add("Tipos", tiposDocumento);
}

E aquela dependência feia foi removida.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, windsor

Globalização de validação do jQuery com o ASP.NET MVC 3

Posted on 17/09/2011 by vintem
3 Comments

O Asp.Net MVC 3 tem uma ótima funcionalidade que é a validação no cliente usando o plugin do jQuery validations e usando um script da própria Microsoft a validação é feita sem que seja necessário nenhum codificação especial. Basta usar os atributos do namespace System.ComponentModel.DataAnnotations.

Pra quem não sabe, para fazer essa validação basta adicionar os seguintes scripts (que já estão no template padrão de um novo site Asp.Net Mvc 3):

<script src=”/Scripts/jquery-1.6.2.min.js” type=”text/javascript”></script>
<script src=”/Scripts/jquery.validate.min.js” type=”text/javascript”></script>
<script src=”/Scripts/jquery.validate.unobtrusive.min.js” type=”text/javascript”></script>

Muito simples de verdade! Mas existe um problema, esse script não é globalizado, então digamos que você tenha que usar uma data na sua classe e você gostaria de validá-la, por exemplo eu tinha uma classe que entre outras coisas tinha que salvar uma data, para simplificar, algo como isso:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
public class Pessoa
{
    public string Nome { get; set; }
    public string Sexo { get; set; }
    public string Rg { get; set; }
 
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }
 
    [DataType(DataType.Date)]
    public DateTime? DataNascimento { get; set; }
}

Quando eu informava a data 16/09/1980, por exemplo, automaticamente era detectado uma data inválida, já que o esperado é que a data estivesse no padrão mm/dd/aaaa, mas é claro que no Brasil o padrão é outro.

Então como corrigir?

Primeiro fazer uso do plugin Globalize do jQuery, adicione referências a dois scripts (que é claro, podem ser baixados no site do projeto):

<script type=”text/javascript” src=”@Url.Content(“~/Scripts/globalize.js”)”></script>
<script type=”text/javascript” src=”@Url.Content(“~/Scripts/cultures/globalize.culture.pt-BR.js”)”></script>

Depois disso, tudo o que precisa ser feito é determinar qual a cultura que quer usar e indicar o parser do globalize para validar a data:

?View Code JAVASCRIPT
1
2
3
4
Globalize.culture("pt-BR");
$.validator.methods.date = function(value, element) {
    return this.optional(element) || Globalize.parseDate(value);
};

Não podia ser mais simples!

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC, JavaScript, jQuery | Tags: asp.net mvc, globalizacao, javascript, jquery

Localização de mensagem de erro no ASP.NET MVC

Posted on 22/07/2010 by vintem
No Comments

Sabe quando você preenche uma data inválida em uma página usando o ASP.NET MVC e o erro vem em inglês assim:

ErroIngles

Isso acontece porque o DefaultModelBinder do MVC não conseguiu converter essa data, no caso acima, é óbvio porque não existe um mês 15. A questão é, como traduzir essa mensagem?

Um jeito que achei foi adicionando uma pasta App_GlobalResources e dentro dessa pasta adicionar um arquivo de resources, que no caso, chamei de CustomMvcResources.resx.

ArquivoResources

Nesse arquivo de resources adicione a seguinte linha:

ItemResource

No global.asax altere o método Application_Start para que fique assim:

?View Code CSHARP
1
2
3
4
5
6
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    DefaultModelBinder.ResourceClassKey = "CustomMvcResources";
    RegisterRoutes(RouteTable.Routes);
}

O importante é que o valor informado à propriedade ResourceClassKey tenha o nome do arquivo de resource criado.

Agora o erro será apresentado do jeito que foi configurado no arquivo de resources.

ErroTraduzido

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc

ASP.NET MVC e o Grid do MvcContrib

Posted on 05/07/2010 by vintem
1 Comment

Uma das coisas que eu sempre gostei do ASP.NET Web Forms era a produtividade que a gente ganhava com os controles, entre eles, um dos que eu mais usava sempre foi o GridView. E devo admitir que esse foi também um fator de resistência para eu começar a usar o ASP.NET MVC.

Resistência vencida, toda a vez que eu precisava de um Grid, ou seja, de dados tabulares, eu usava o bom e velho e um loop através dos meus objetos da collection.

Isso é claro, até eu me aventurar com o Grid do MvcContrib. O MvcContrib é um projeto open source que, entre outras coisas, possui esse Grid que é muito prático e simples.

Pra começar é só baixar o assembly do site do projeto e adicionar uma referência para o assembly MvcContrib.dll

Eu fiz uma action bem simples que retorna uns dados estáticos para a página:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public ViewResult Index()
{
	var produtos = new List
	{
		new Produto
		{
			Id = 1,
			Nome = "Chaveiro",
			Valor = 11.50m,
			Categoria = new Categoria {Id = 1, Nome = "Utilitários"}
		},
		new Produto
		{
			Id = 2,
			Nome = "Mouse",
			Valor = 100m,
			Categoria = new Categoria {Id = 2, Nome = "Informática"}
		},
		new Produto
		{
			Id = 3,
			Nome = "Pen-Drive 8GB",
			Valor = 150.99m,
			Categoria = new Categoria {Id = 2, Nome = "Informática"}
		}
	};
 
	return View(produtos);
}

E na view é muito simples também:

?View Code ASP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ Import Namespace="MvcContrib.UI.Grid" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	Lista de Produtos
</asp:Content>
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
 
	<h2>Lista de Produtosh2>
 
	<%= Html.Grid(Model).Columns(coluna =>
	{
		coluna.For(x => x.Nome);
		coluna.For(x => x.Valor);
		coluna.For(x => x.Categoria.Nome);
	})
	%>
 
</asp:Content>

Isso gera um grid simples na página:

ScreenHunter_01 Jul. 05 11.55

Agora vamos permitir uma ordenação, primeiro eu altero a view para exibir os links de ordenação:

?View Code ASP
1
2
3
4
5
6
7
8
9
<%= Html.Grid(Model)
	.Sort(ViewData["sort"] as GridSortOptions)
	.Columns(coluna =>
	{
		coluna.For(x => x.Nome);
		coluna.For(x => x.Valor);
		coluna.For(x => x.Categoria.Nome).Named("Categoria");
	})
%>

E na action do controller eu faço seguinte:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
using MvcContrib.Sorting;
// ...
public ViewResult Index(GridSortOptions sort)
{
	var produtos = GetProdutos();
	if (sort.Column == null)
		sort.Column = "Nome";
 
	produtos = produtos.OrderBy(sort.Column, sort.Direction);
	ViewData["sort"] = sort;
 
	return View(produtos);
}

Para ficar mais claro eu movi a inicialização dos produtos para um outro método. Mas como você pode ver no código acima, é muito simples adicionar ordenação.

Por fim, para paginar alteramos a action:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
using MvcContrib.Pagination;
// ...
public ViewResult Index(GridSortOptions sort, int? pagina)
{
    var produtos = GetProdutos();
    if (sort.Column == null)
        sort.Column = "Nome";
 
    produtos = produtos.OrderBy(sort.Column, sort.Direction);
    ViewData["sort"] = sort;
 
    return View(produtos.AsPagination(pagina ?? 1, 10));
}

E na view usamos um helper para exibir as páginas:

?View Code ASP
1
2
3
4
5
6
7
8
9
10
11
<%= Html.Grid(Model)
    .Sort(ViewData["sort"] as GridSortOptions)
    .Columns(coluna =>
    {
        coluna.For(x => x.Nome);
        coluna.For(x => x.Valor);
        coluna.For(x => x.Categoria.Nome).Named("Categoria");
    })
%>
 
<%= Html.Pager((IPagination)Model).Format("Exibindo {0} - {1} de {2}") %>

Conclusão

Fazer paginação e ordenação manualmente em grids pode ser bem complicado às vezes. Pela simplicidade da solução hoje o Grid do MvcContrib é a minha primeira opção.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, mvccontrib

Publicando um site em ASP.NET MVC no IIS 6

Posted on 18/05/2010 by vintem
No Comments

Publicar um site feito usando o ASP.NET MVC no servidor IIS não é tão simples como apenas copiar os arquivos, algumas configurações são necessárias:

1) Dentro do IIS abra as propriedades no seu site e na aba Home Directory, clique no botão Configuration. Dentro de Application Extensions, selecione a extensão .aspx e clique em Edit. Copie o conteúdo da caixa Executable como na figura abaixo e clique em Cancel.

Extension

2) Clique no botão INSERT e cole o texto na caixa Executable e desmarque a opção Verify that file exists como na figura abaixo.

Adicionar Extension

3) Por último temos que “adicionar uma extensão” para as urls já que o IIS 6 exite que exista uma extensão. O jeito mais fácil de fazer é isso dentro do Global.asax.cs. Altere a rota padrão e suas outras rotas para que fiquem assim:

?View Code CSHARP
1
2
3
4
5
6
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute("Default", "{controller}.mvc/{action}/{id}",
        new {action = "Index", id = ""});
}

Veja que depois do controller adicionei a extensão .mvc, agora todas as rotas funcionarão com o caminho /controler.mvc/action. É importante que para isso não existam urls fixas em suas páginas, apenas urls criadas usando os html helpers.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, iis

CodeTemplates com ASP.NET MVC

Posted on 03/05/2010 by vintem
No Comments

Toda a vez que você vai adicionar uma View usando o assistente do Visual Studio

Uma nova página é adiciona com um código pré-definido e baseado na opção que você escolheu  em “View Content”, o que muita gente não sabe é que dá para customizar todos esses modelos de página e é muito simples fazer isso.

Adicionando os arquivos ao projeto

Primeiro vá em C:Program FilesMicrosoft Visual Studio 9.0Common7IDEItemTemplatesCSharpWeb

Obs.: Veja que esse caminho vai variar de acordo com sua instalação e com a linguagem escolhida.

Se você tiver o ASP.NET MVC 1 e 2 instalados você deve encontrar duas pastas ali dentro chamadas respectivamente MVC e MVC2. Entre na pasta da versão escolhida copie a pasta CodeTemplates e cole na raíz do seu projeto web. Você deve acabar com um projeto assim:


O Visual Studio sempre vai procurar por esses arquivos localmente no projeto e se não encontrar buscará os arquivos na pasta informada acima.

Configurando os arquivos

Você já deve ter percebido não é? Existe um arquivo para cada template. Todas com uma extensão .tt que é a extensão do T4 (Text Template Transformation Toolkit).

O T4 é uma ferramenta de geração de código baseada em templates que vem nativa junto com o Visual Studio desde a versão 2005. Aliás, vale para o T4 um investimento de estudos já que é uma ferramenta muito útil.

A primeira coisa que precisa ser feita é selecionar todos os arquivos .tt ir na janela de propriedades e limpar o campo Custom Tool. Deixe em branco.

Alterando um template

Agora vamos realmente alterar um template. Vamos supor que eu queira, ao exibir o detalhe de uma classe que ela fosse exibida dentro de uma tabela. Originalmente, as propriedades são exibidas em divs ao invés de tabelas (que na minha opinião, é a melhor opção).

Veja como ficou o arquivo Details.tt

Outra modificação que eu fiz na modelo de Details, foi, ao invés de exibir o título dentro de uma tag h2, eu exibo dentro da tag h1.

Pronto! Agora toda vez que for adiciona uma View com base no modelo Details ele seguirá esse padrão.

Uma outra coisa que pode ser feita é salvar um novo modelo dentro daquela pasta com outro nome, por exemplo, eu fiz essas alterações e salvei o arquivo como DetailsVintem.tt. Agora quando eu tento adicionar uma View essa opção fica disponível para mim.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, code templates

Postando um objeto JSON para uma Action MVC2 com jQuery

Posted on 26/04/2010 by vintem
No Comments

Há um tempo atrás eu postei uma versão desse artigo utilizando o Asp.Net MVC1.Agora, o MVC2 está no ar e com isso ficou mais fácil postar um objeto Json para uma action.

Para começar, baixe o ASP.NET MVC2 Futures e adicione uma referência no seu projeto para Microsoft.Web.Mvc.dll e no Global.asax.cs registre a chamada para o provedor do json, dessa forma:

?View Code CSHARP
1
2
3
4
5
6
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}

Do lado do Asp.Net é só isso. Faça sua Action normalmente esperando um objeto, no meu caso eu segui o exemplo anterior com o caso do cliente:

Fiz uma classe Cliente

?View Code CSHARP
1
2
3
4
5
public class Cliente
{
    public string Nome { get; set; }
    public string Cnpj { get; set; }
}

E minha action ficou assim:

?View Code CSHARP
1
2
3
4
public JsonResult Criar(Cliente cliente)
{
    return Json(cliente);
}

Obviamente, essa não é uma action muito criativa, simplesmente está recebendo um objeto da classe Cliente e retornando como Json, mas aqui poderia ser feito qualquer coisa, não é necessário retornar um objeto json.

Por fim, para enviar um objeto json pelo jquery precisamos de um plugin, já que o jquery não faz isso nativamente. Eu usei o jquery-json, que tem um método toJSON para converter um objeto javascript para json.

Veja como ficou meu script:

Mas uma vez, um script sem muito segredo, estou pegando os valores de caixas de texto e montando meu objeto, depois convertendo a variável cliente para um objeto json armazenado na variável encoded e passando essa variável na chamada ajax para a action.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, jquery, json

Nova sintaxe para fazer Html Encoding com Asp.Net 4 e Asp.Net MVC 2

Posted on 19/04/2010 by vintem
No Comments

Html Encoding faz parte de todo desenvolvimento web, principalmente para previnir ataques de Cross Site Scripting (XSS) – quem não sabe o que é, recomendo ler esse artigo.

Até a versão 3.5 no Asp.Net para fazer Html Enconding tinhamos que fazer algo assim:

?View Code ASP
1
<%= Server.HtmlEncode(algum_valor) %>

E no Asp.Net MVC algo assim:

?View Code ASP
1
<%= Html.Encode(model.Valor) %>

Isso sempre funcionou, mas agora existe uma nova possibilidade, que na minha opinião torna isso ainda mais simples:

?View Code ASP
1
<%: mode.Valor %>

É só trocar o sinal de = pelo sinal : e automaticamente o encoding será realizado.

E isso vale também para os outros Html helpers do MVC, por exemplo:

?View Code ASP
1
<%: Html.TexboxFor(m => m.Valor) %>

No código acima, o texto dentro do textbox já sairá codificado.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, encoding

Customizando Templates no Asp.Net MVC2

Posted on 06/03/2010 by vintem
No Comments

Customizar os templates padrão do Asp.Net MVC2 é muito fácil. Já mostrei antes como usar os templates, agora vou mostrar como customizar.

A primeira coisa que é preciso saber para customizar é que quando o MVC2 busca por customizações ele busca nas seguintes pastas:

  • ~/Areas/NomeDaArea/Views/NomeDoController/DisplayTemplates/TemplateName.aspx & .ascx
  • ~/Areas/NomeDaArea/Views/Shared/DisplayTemplates/TemplateName.aspx & .ascx
  • ~/Views/NomeDoController/DisplayTemplates/TemplateName.aspx & .ascx
  • ~/Views/Shared/DisplayTemplates/TemplateName.aspx & .ascx
  • ~/Areas/NomeDaArea/Views/NomeDoController/EditTemplates/TemplateName.aspx & .ascx
  • ~/Areas/NomeDaArea/Views/Shared/EditTemplates/TemplateName.aspx & .ascx
  • ~/Views/NomeDoController/EditTemplates/TemplateName.aspx & .ascx
  • ~/Views/Shared/EditTemplates/TemplateName.aspx & .ascx

Veja que são principalmente duas pastas DisplayTemplates para os templates de exibição e EditTemplates para os de edição dispostas em alguns locais específicos.

Só para facilitar vou continuar o exemplo feito no post anterior que tinha as views Index.aspx e Edit.aspx e classe de model Cliente.cs como mostrados abaixo:

Index

Edit

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Cliente
{
    public string Nome { get; set; }
    public string Email { get; set; }
    public bool Ativo { get; set; }
    [DisplayName("Data de Nascimento")]
    public DateTime DataNascimento { get; set; }
    public decimal Credito { get; set; }
 
    public static Cliente Criar()
    {
        return new Cliente {
             Nome = "Thiago Temple",
             Ativo = true,
             Credito = 1000, 
             DataNascimento = new DateTime(1981, 10, 15)
        };
    }
}

Existem alguns templates pré-definidos no MVC2, são eles: String, Html, Boolean, Decimal, EmailAddress, HiddenInput, Html, Object, String, Text, Url e DateTime. Então para se customizar um desses campos tudo o que temos que fazer é criar um arquivo com o nome do template na pasta específica. Vamos imaginar que a idéia fosse que toda que vez que tivéssemos uma propriedade do tipo DateTime e ela fosse editável nós gostaríamos que o textbox fosse exibido com uma classe css específica e ao lado do campo aparecesse uma imagem para que o usuário pudesse clicar e selecionar a data de um calendário em javascript, por exemplo.

Temos então que criar um arquivo DateTime.ascx na pasta ~/Views/Shared/EditTemplates/ assim esse template estará disponível para todas as propriedades DateTime do nosso projeto. Veja como ficaria esse arquivo:

DataTime Edit

Isso vale para todos os tipos de templates pré-definidos. Seguindo o exemplo do post passado, se quisermos modificar a exibição da nossa classe cliente para que ela fique dentro de uma tabela, veja como ficará o template do arquivo ~/Views/Shared/DisplayTemplates/Object.ascx

Display Object

Dentro do objeto ViewData agora temos um objeto ModelMetadata que contém informações sobre a classe do Model que está sendo usada na view. Entre outras informações o que temos ali é uma coleção com todas as propriedades do model.

No exemplo acima primeiro exibimos o nome do model e depois fazemos um loop entre as propriedades do model exibindo as que estão marcadas com a opção ShowForDisplay = true, que é o padrão. Isso deve gerar uma página assim:

Cliente Display

Para o template de edit não é muito diferente, veja o arquivo ~/Views/Shared/EditTemplates/Object.ascx:

Object Edit

Da mesma forma fazemos um loop nas propriedades do objeto ModelMetada que estão marcados com a propriedade ShowForEdit = true, novamente, esse é o padrão. Além disso, verifiquei se a propriedade é obrigatória e coloquei um * na frente do label. Veja o resultado:

Client Edit

Veja também que a modificação feita para o campo DateTime continuou valendo para a propriedade Data de Nascimento que foi exibida com a imagem do calendário ao lado do campo.

Conclusão

Os templates do MVC2 são uma forma simples e prática de exibir dados. Mas, o mais importante, são também muito poderosos para que sejam customizados da melhor forma possível para as necessidades específicas de cada projeto.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, templates

Validação com Asp.Net MVC2 parte 3 – Input vs Model validation

Posted on 22/02/2010 by vintem
1 Comment

Obs.: Esse post está baseado na versão RC2 do Asp.Net MVC2.

O Asp.Net MVC 1 já possuía uma forma de realizar validações, como as validações Required ou Regular Expression que eu já mostrei aqui em outros posts, além dessa validação o framework também avisaria/perceberia erros ao submeter um formulário com dados inválidos, exemplo: enviar uma string com “xxxxx” para uma propriedade de data ou não enviar um valor para um campo que não fosse nullable, como, por exemplo, um campo int.

Vamos olhar uma classe de modelo como a classe Cliente abaixo:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Cliente
{
    public int IdCliente { get; set; }
    [Required(ErrorMessage = "Preencha o nome")]
    public string Nome { get; set; }
    [Required(ErrorMessage = "Preencha a idade")]
    [Range(0, 150, ErrorMessage="Idade inválida")]
    public int? Idade { get; set; }
    [Required(ErrorMessage = "Preencha o email")]
    [RegularExpression(@"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}$", ErrorMessage = "Email inválido")]
    public string Email { get; set; }
    [Required(ErrorMessage="Preencha o Cpf")]
    public string Cpf { get; set; }
}

E um formuário como o abaixo:

?View Code ASP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<%: Html.ValidationSummary() %>
<fieldset>
  <legend>Fields</legend>
  <div class="editor-label">
    <%: Html.LabelFor(model => model.Nome) %>
  </div>
  <div class="editor-field">
    <%: Html.TextBoxFor(model => model.Nome) %>
    <%: Html.ValidationMessageFor(model => model.Nome) %>
  </div>
  <div class="editor-label">
    <%: Html.LabelFor(model => model.Idade) %>
  </div>
  <div class="editor-field">
    <%: Html.TextBoxFor(model => model.Idade) %>
    <%: Html.ValidationMessageFor(model => model.Idade) %>
  </div>
  <div class="editor-label">
    <%: Html.LabelFor(model => model.Email) %>
  </div>
  <div class="editor-field">
    <%: Html.TextBoxFor(model => model.Email) %>
    <%: Html.ValidationMessageFor(model => model.Email) %>
  </div>
  <p>
    <input type="submit" value="Create" />
  </p>
</fieldset>

Repare que o modelo tem uma propriedade Cpf decorada com o atributo Required e no formulário essa propriedade não existe. No MVC1 ou até o RC1 do MVC2, se submetêssemos esse formulário, o campo Cpf não seria exigido. Isso é o que é conhecido como Input validation, ou seja, apenas os dados que são submetidos pelo formulário são validados. A partir do MVC RC2, esse campo também é validado, e isso é conhecido como Model validation.

Vou alterar a classe Cliente para ter um Endereco, como abaixo:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Cliente
{
    public int IdCliente { get; set; }
    [Required(ErrorMessage = "Preencha o nome")]
    public string Nome { get; set; }
    [Required(ErrorMessage = "Preencha a idade")]
    [Range(0, 150, ErrorMessage="Idade inválida")]
    public int? Idade { get; set; }
    [Required(ErrorMessage = "Preencha o email")]
    [RegularExpression(@"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}$", ErrorMessage = "Email inválido")]
    public string Email { get; set; }
    [Required(ErrorMessage="Preencha o Cpf")]
    public string Cpf { get; set; }
    public Endereco Endereco { get; set; }
}
 
public class Endereco
{
    [Required]
    public string Logradouro { get; set; }
    [Required]
    public string Cidade { get; set; }
    [Required]
    public string Bairro { get; set; }
}

Veja que a propriedade Endereco não é obrigatória na classe Cliente. O que isso quer dizer? Que no Model Validation, se eu não informar nenhum atributo da classe Endereco, o endereço pode ser nulo.

Se eu mantiver o formulário como estava e não adicionar nenhuma outra caixa de texto ao enviar o formulário ele não vai validar o endereço. Agora vou alterar o formulário para que ele tenha o Cpf e a Cidade do Cliente. Assim:

?View Code ASP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<%= Html.ValidationSummary()%>
<fieldset>
  <legend>Fields</legend>
  <div class="editor-label">
    <%= Html.LabelFor(model => model.Nome)%>
  </div>
  <div class="editor-field">
    <%= Html.TextBoxFor(model => model.Nome)%>
    <%= Html.ValidationMessageFor(model => model.Nome)%>
  </div>
  <div class="editor-label">
    <%= Html.LabelFor(model => model.Idade)%>
  </div>
  <div class="editor-field">
    <%= Html.TextBoxFor(model => model.Idade)%>
    <%= Html.ValidationMessageFor(model => model.Idade)%>
  </div>
  <div class="editor-label">
    <%= Html.LabelFor(model => model.Email)%>
  </div>
  <div class="editor-field">
    <%= Html.TextBoxFor(model => model.Email)%>
    <%= Html.ValidationMessageFor(model => model.Email)%>
  </div>
  <div class="editor-label">
    <%= Html.LabelFor(model => model.Cpf)%>
  </div>
  <div class="editor-field">
    <%= Html.TextBoxFor(model => model.Cpf)%>
    <%= Html.ValidationMessageFor(model => model.Cpf)%>
  </div>
  <div class="editor-label">
    <%= Html.LabelFor(model => model.Endereco.Cidade)%>
  </div>
  <div class="editor-field">
    <%= Html.TextBoxFor(model => model.Endereco.Cidade)%>
    <%= Html.ValidationMessageFor(model => model.Endereco.Cidade)%>
  </div>
  <p>
    <input value="Create" type="submit" />
  </p>
</fieldset>

Apenas o campo Cidade foi adicionada, mas ao submeter o formulário as propriedades Logradouro e Bairro também são validados.

Ou seja, agora a validação é feita sempre no Model e não mais de acordo com os dados que são informados.

Por que isso é importante? Principalmente porque alguém mal intensionado poderia tentar enviar um request de post com apenas parte dos dados. Nas versões anteriores do MVC isso não seria validado automaticamente.

Um ponto importante a se considerar são os atributos que não podem ser nulos como no caso do Int. Imagine que na nossa classe Cliente a propriedade Idade não fosse decorada com o atributo Required. Nas versões anteriores do MVC se o campo Idade não fosse preenchido um erro “A value is required” seria retornado, isso acontece no momento do model-binding, quando framework tenta identificar se existe um valor submetido para uma propriedade, no caso idade, que por padrão não pode ser nula.

A partir do MVC RC2 essa propriedade seria preenchida com o seu valor padrão, que no caso do int é 0.

Tweet
government,politics news,politics news,politics
Categories: ASPNET MVC | Tags: asp.net mvc, templates
Previous Entries
  • Categorias

    • .NET (1)
    • ASP.NET (1)
    • ASPNET MVC (15)
    • Blog (1)
    • Controle de Versões (2)
    • Desenvolvimento (10)
    • Java (1)
    • JavaScript (2)
    • jQuery (1)
    • Leitura (5)
    • Ruby (2)
    • Ruby on Rails (1)
    • Sem categoria (23)
    • Testes (4)
  • Language

    • English
    • Português
  • Tags

    agilidade asp.net asp.net mvc asp.net vc automapper blog code templates controle de versoes css dataaccess dependency injection ebook encoding eventos excecoes firebug git globalizacao hibernate iis ironruby jasypt java javascript jquery json leitura less mvccontrib qcon rails ruby selenium simpledata snippet stored procedures structuremap tdc templates testes testes integrados visualstudio vraptor windsor
© Temple Coding. Proudly Powered by WordPress | Nest Theme by YChong