domingo, 8 de março de 2015

MVC 3 - Atributo Bind e o método TryUpdateModel

Quem já utiliza o MVC3 sabe que é possível criarmos views tipadas, e isso é ótimo quando os campos contidos nos formulários são referentes a uma única classe.
Mas e quando os valores coletados nos campos são referentes a classes distintas. O que fazer? Neste caso podemos utilizar o atributo Bind junto com o método TryUpdateModel.
Vamos utilizar como exemplo duas classes uma classe Pessoa e uma classe Doenca. Se em um mesmo formulário tivéssemos que pegar o valores de Pessoa e de Doenca a View que contém estes campos não poderia ser tipada pois trata-se de classes distintas. A solução mais comum seria criar uma outra classe que contenha propriedades referentes a Pessoa e a Doenca e tipar a view com essa nova classe.
Mas, existe uma alternativa. Vamos resolver esse problema utilizando o atributo Bind e da classe FormCollection
Crie as classes Pessoa e Doenca conforme exemplo abaixo:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Pessoa
{
    public string Nome {getset; }
    public string Sexo { getset; }
    public string Observacao { getset; }
}
public class Doenca
{
    public string Nome { getset; }
    public string TipoDoenca { getset; }
    public string Observacao { getset; }
}
Insira o seguinte código abaixo na View
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
    @Html.TextBox("Pessoa.nome", "Pessoa")
    <br />
    <text>Masculino</text>
    @Html.RadioButton("Pessoa.sexo", "masculino")
    <br />
    <text>Feminino</text>
    @Html.RadioButton("Pessoa.sexo", "Feminino")
    <br />
    @Html.TextArea("Pessoa.observacao")
    <br />
    @Html.TextBox("Doenca.nome", "Doenca")
    <br />
    <text>Ossea</text>
    @Html.RadioButton("Doenca.tipoDoenca", "ossea")
    <br />
    <text>Cancer</text>
    @Html.RadioButton("Doenca.tipoDoenca", "cancer")
    <br />
    @Html.TextArea("Doenca.observacao")
    <input type="submit" name="submit" value="submeter" />
}
Insira este código no Controller
?
1
2
3
4
5
6
7
8
9
10
[HttpPost]
public ActionResult Index([Bind(Prefix = "Pessoa,Doenca")]FormCollection collection)
{
    Pessoa pessoa = new Pessoa();
    TryUpdateModel(pessoa, "Pessoa", collection.ToValueProvider());
    Doenca doenca = new Doenca();
    TryUpdateModel(doenca, "Doenca",collection.ToValueProvider());
    return View();
}

O detalhe neste código é o parâmetro passado ao método. Como a View não é fortemente tipada estamos utilizando a classa FormCollection para capturar os valores dos campos e o atributo Bind com sua propriedade Prefix.
A propriedade  Prefix associa uma marcação – Campo de formulário com um parâmetro de um método do Controller.
Observe que coloquei os id’s dos campos do formulário da seguinte forma “Prefix.PropriedadeDaClasse“. Analise o seguinte campo:
@Html.TextBox(“Pessoa.nome”, “Pessoa”)
O id deste TextBox é “Pessoa.nome”, ou seja, Pessoa é a string que foi definida na propriedade Prefix e nome é um dos atributos definidos na Classe Pessoa. Adicionando um prefixo é possível saber a qual classe pertence o valor contido no campo do formulário.
O nome após o prefixo deve ser idêntico ao nome da propriedade da classe
Utilizamos o método TryUpdateModel passando os respectivos parâmetros: Objeto, Prefixo e o  Parâmetro do FormCollection seguido do método ToValueProvider.

Nenhum comentário:

Postar um comentário