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

Asked

Viewed 442 times

4

I’m following Sergey Barskiy’s presentation on http://www.youtube.com/watch?v=l3WzYZsN0gU, where it 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 databases. Success so far. His presentation goes so far.

But then I couldn’t get these Plex type to be created in the views when doing Scaffolding with the class. And this is 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 time to do the scaffolding. I went to create a Controller for the Company, I used the template MVC 5 Controller with views, using Entity Framework, and chose as Model Class the class Empresa. But when generating 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")
}

To include the address and the audit I had to add in hand, as an example below, where I added the Address Property Street and the Audit Property Creator :

@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 on hand, but there is some way the T4 template already include the Address and Audit properties?

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 property Enderecoid and will automatically create a Foreign key for this field, by default every property with class name terminated with ID it will attempt to create a Foreign key [classeID].

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

Adjust the other classes try the scaffolding again, a dropdown list will be generated in the view. for more information recommend:Steven Sanderson’s blog It’s about MVC3 but the whole base is the same.

2

This way you have shaped the classes, no.

In MVC, the classes within Models are practically considered as tables in a relational database or collections in non-relationships. Therefore, their complex types would be as separate tables, and not as extension of model attributes Pessoa, like you’re trying to do.

If you want to understand how Scaffolding works, try running these commands on 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 is another directory called Scaffolders, containing all T4 templates used to generate Views.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.