Code First with Complex Types, when doing Scaffolding Complex Types properties are not found in the views

4

I'm following the presentation of Sergey Barskiy in link , where he demonstrates the approach of Entity FrameWork with Code First.

I loved it, but I had a problem.

In the presentation, it demonstrates that I can use Complex Types for the properties of my POCO class, and how tables are generated in the database. Success there. His presentation goes there.

But then I could not get these complex type created in views when doing Scaffolding with the class. And that's my problem.

I created two POCO classes called Enterprise and Person, both of which 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 it was time to do the Scaffolding. I was creating a Controller for the Company, I used the MVC 5 Controller with views, using Entity Framework template, and I chose Model% as the% class. But when generating the views they do not have the properties of the Address and Audit classes:

Below the view created 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")
}

In order to include the address and the audit I had to add in the hand, as shown below, where I added the Street of the Address property and the Created property of the Audit:

@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 was able to sort out in the hand, but is there any way the T4 template already includes the Address and Audit properties?

    
asked by anonymous 04.02.2014 / 15:30

2 answers

2

Change your class this way:

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 found the EnderecoID property and will automatically create a foreign key for this field, by default all property with class name ended with ID it tried to create a foreign key [classID].

The virtual property is to actually be able to navigate the properties of the object.

Set the other classes to 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.

    
06.02.2014 / 20:36
2

In this way you have modeled the classes, no.

In MVC, classes within Models are practically considered as tables in a relational database or non-relational collections. So your complex types would be like separate tables, not as an extension of the attributes of the Pessoa template, as you're trying to do.

If you want to understand how Scaffolding works, try running these commands in the Package Manager Console :

Scaffold CustomTemplate View _CreateOrEdit
Scaffold CustomTemplate View Create
Scaffold CustomTemplate View Edit
Scaffold CustomTemplate View Delete
Scaffold CustomTemplate View Index
Scaffold CustomTemplate View Details

A directory will be created in your solution called CodeTemplates . Inside it there is another directory called Scaffolders , containing all the T4 templates used to generate the Views.

    
06.02.2014 / 22:05