To create the controller and the view corresponding to a particular Viewmodel do:
Viewmodel
namespace WebApplication1.Models
{
public class ExampleViewModel
{
public Produto Produto { get; set; }
public Cliente Cliente { get; set; }
}
public class Produto
{
public int Id { get; set; }
public string Descricao { get; set; }
}
public class Cliente
{
public int Id { get; set; }
public string Nome { get; set; }
}
}
In that Viewmodel (ExampleViewModel
) i have two aggregations of classes Produto
and Cliente
and with them I will create view Leading (Create
) and their respective views for each existing aggregation.
How would it be?
public class ExamplesController : Controller
{
[HttpGet()]
public ActionResult Create()
{
return View();
}
[HttpPost()]
public ActionResult Create(ExampleViewModel exampleViewModel)
{
//ROTINAS DE GRAVAÇÃO
return View();
}
}
In the controller
it’s simple to create a create with verb GET
and another with the verb POST
with a parameter of your ViewModel
(ExampleViewModel
).
Create your view in this format:
View Product: (_Product.cshtml)
@model WebApplication1.Models.ExampleViewModel
<div class="form-horizontal">
<h4>Produto</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Produto.Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Produto.Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Produto.Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Produto.Descricao, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Produto.Descricao, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Produto.Descricao, "", new { @class = "text-danger" })
</div>
</div>
</div>
View Client: (_Client.cshtml)
@model WebApplication1.Models.ExampleViewModel
<div class="form-horizontal">
<h4>Cliente</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Cliente.Id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Cliente.Id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Cliente.Id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Cliente.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Cliente.Nome, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Cliente.Nome, "", new { @class = "text-danger" })
</div>
</div>
</div>
Notice that these two views which are complementary to their view Main has an interesting factor that I put your type in the @model
your Viewmodel ExampleViewModel
, because?
So that the binding
(the information passed in the fields is loaded into your class in a simple and transparent manner) works properly, that is, so that when sending the information to Create
(do verb POST
) it loads the class correctly. Look at the nomenclature of an item:
@Html.EditorFor(model => model.Cliente.Id, new { htmlAttributes = new { @class = "form-control" } })
It was mounted upon its aggregation demonstrated in model.Cliente.Id
, for him to give the binding
correctly of the information.
Main View: (Create.cshtml)
@model WebApplication1.Models.ExampleViewModel
@{ Layout = null; }
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create</title>
</head>
<body>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.Partial("_Cliente", Model)
<hr />
@Html.Partial("_Produto", Model)
<div class="form-horizontal">
<h4>ExampleViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
</body>
</html>
Generated html
<form action="/Examples/Create" method="post"><input name="__RequestVerificationToken" type="hidden" value="Mr207UcvrXamhyWWVqGbKBVZ8wY9ccJoBqcGVCjwg3G_tjHWIymMjfzE5o1XkXaJ8Q0WsL5XWMhq3biQfh7rKmuerIMuMPCgPFEOzA7baNc1" /><div class="form-horizontal">
<h4>Cliente</h4>
<hr />
<div class="form-group">
<label class="control-label col-md-2" for="Cliente_Id">Id</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-number="The field Id must be a number." data-val-required="O campo Id é obrigatório." id="Cliente_Id" name="Cliente.Id" type="number" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="Cliente.Id" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Cliente_Nome">Nome</label>
<div class="col-md-10">
<input class="form-control text-box single-line" id="Cliente_Nome" name="Cliente.Nome" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="Cliente.Nome" data-valmsg-replace="true"></span>
</div>
</div>
</div> <hr />
<div class="form-horizontal">
<h4>Produto</h4>
<hr />
<div class="form-group">
<label class="control-label col-md-2" for="Produto_Id">Id</label>
<div class="col-md-10">
<input class="form-control text-box single-line" data-val="true" data-val-number="The field Id must be a number." data-val-required="O campo Id é obrigatório." id="Produto_Id" name="Produto.Id" type="number" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="Produto.Id" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="Produto_Descricao">Descricao</label>
<div class="col-md-10">
<input class="form-control text-box single-line" id="Produto_Descricao" name="Produto.Descricao" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="Produto.Descricao" data-valmsg-replace="true"></span>
</div>
</div>
</div> <div class="form-horizontal">
<h4>ExampleViewModel</h4>
<hr />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
</form>
In this generation it is easy to see why class aggregations ExampleViewModel
are loaded, the fields for example client name in your tag input
of the kind text
has the name Cliente.Nome
. Client is the classe
and the Name of property, that’s how the MVC can define the information and click on the corresponding classes.
If you ride different it won’t work !!!
Could you add your real templates? Sometimes what you’re looking for doesn’t even need to be by Viewmodel.
– Randrade
@Randrade but would have how to do without being by Viewmodel? Are 5 entities...
– Érik Thiago
If they are related entities (preferably 1:1), you do not need Viewmodel, but rather their relationship.
– Randrade
Even if I need to save everything at once? @Randrade
– Érik Thiago
Yes. For example: If you are saving a Client, where this customer has a Addressee, one User, etc.. You are saving a Client, and from it you get all these values. Generally, it is used
ViewModel
only when yourModel
does not meet all needs.– Randrade
If you notice, in the question you linked (it is my authorship, and was ashamed of it, but seems to be helping more people) not all Models have direct relationship, so a
ViewModel
is the best option.– Randrade
Don’t be ashamed of her no @Randrade.. She’s the one who helped me with my solution! kkkk. But I get the idea, thank you very much!
– Érik Thiago
I said "had" because I didn’t know she had helped anyone else. p
– Randrade