Question:
I'm following Sergey Barskiy's presentation at http://www.youtube.com/watch?v=l3WzYZsN0gU , where he demonstrates the Entity FrameWork approach with Code First.
I loved it, but I had a problem.
In the presentation, he demonstrates that I can use Complex Types for the properties of my POCO class, and how tables are generated in the database. Success so far. His presentation goes there.
But then I couldn't get these complex types to be created in the views when doing Scaffolding with the class. And that's my problem.
I created two POCO classes called Company and Person, both have an Address property and an Audit property (which are complex types).
Below my POCO classes:
public class Empresa
{
public int EmpresaId { get; set; }
public string Nome { get; set; }
public Endereco Endereco { get; set; }
public Auditoria Auditoria { get; set; }
public virtual ICollection<Pessoa> Pessoas { get; set; }
}
public class Pessoa
{
public int PessoaId { get; set; }
public String Nome { get; set; }
public DateTime DataNascimento { get; set; }
public Endereco Endereco { get; set; }
public Auditoria Auditoria { get; set; }
public int EmpresaId { get; set; }
public Empresa Empresa { get; set; }
}
public class Endereco
{
public string Rua { get; set; }
public string Cidade { get; set; }
public string UF { get; set; }
}
public class Auditoria
{
public string CriadoPor { get; set; }
public DateTime CriadoEm { get; set; }
public string ModificadoPor { get; set; }
public DateTime? ModificadoEm { get; set; }
}
The problem was when doing the Scaffolding. I went to create a Controller for the Company, I used the MVC 5 Controller with views, using Entity Framework
, and I chose the Empresa
class as Model Class. However, when generating the views they do not have the properties of the Address and Audit classes:
Below the created view Create.cshtml:
@model CodeFirstSample.Data.Empresa
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Empresa</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.Nome, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Nome)
@Html.ValidationMessageFor(model => model.Nome)
</div>
</div>
<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>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
To include the address and the audit I had to add it by hand, as shown below, where I added the Street of the Address property and the CriePor of the Audit property:
@model CodeFirstSample.Data.Empresa
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Empresa</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.Nome, new { @class="label-control col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Nome, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Nome)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Endereco.Rua, new { @class="label-control col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Endereco)
@Html.ValidationMessageFor(model => model.Endereco.Rua)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Auditoria.CriadoPor, new { @class="label-control col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Auditoria.CriadoPor)
@Html.ValidationMessageFor(model => model.Auditoria.CriadoPor)
</div>
</div>
<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>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
I managed to solve it by hand, but is there any way for the T4 template to already include the Address and Audit properties?
Answer:
Change your class like this:
public class Empresa
{
public int EmpresaId { get; set; }
public string Nome { get; set; }
public int EnderecoID { get; set; }
public virtual Endereco Endereco { get; set; }
public int AuditoriaID {get; set}
public virtual Auditoria Auditoria { get; set; }
public virtual ICollection<Pessoa> Pessoas { get; set; }
}
When performing the scaffolding it will find the property AddressID and will automatically create a foreign key for this field, by default every property with a class name ending with ID it will try to create a foreign key [classeID].
The virtual property is to actually be able to browse the object's properties.
Adjust the other classes try scaffolding again, a dropdown list will be generated in the view. for more information I recommend: Steven Sanderson's blog It's about MVC3 but the whole base is the same.