Following the previous hook, if you have the ratio of Aba
to Tela
, the selection made here already contemplates the lazy load of Tela
and TelaFuncao
:
var abaQuery = _sigconEntities.Aba
.Where(a => a.idEmpresa == idEmpresa);
return abaQuery.ToList();
@model
of your View , so it needs to be:
@model IEnumerable<Sigcon.Model.Aba>
@{
ViewBag.Title = "Cadastrar";
}
And the fill:
@foreach (var aba in Model)
{
<h1>Aba: @aba.Nome</h1>
foreach (var tela in aba.Telas)
{
<h2>Tela: @tela.Nome</h1>
foreach (var permissao in tela.TelaFuncoes)
{
<p>Permissão: @permissao.Nome</p>
}
}
}
But since you want a creation and editing form, the solution will necessarily be more complex. I will try to make a succinct answer covering all points.
First of all, we are dealing with a screen with multiple cardinalities. My suggestion is that you first make a screen whose Model is Tela
, and for it you can deal with N Models of type TelaFuncao
. Starting with Aba
will make the solution very complex for you that is starting.
So, I've taken some liberties and I'm going to reimplement your system with a couple of adjustments, starting with the Models :
public class TelaFuncao
{
[Key]
public Guid TelaFuncaoId { get; set; }
public Guid TelaId { get; set; }
[Required]
public string Nome { get; set; }
public virtual Tela Tela { get; set; }
}
public class Tela
{
[Key]
public Guid TelaId { get; set; }
public Guid AbaId { get; set; }
[Required]
public string Nome { get; set; }
public virtual Aba Aba { get; set; }
public virtual ICollection<TelaFuncao> TelaFuncoes { get; set; }
}
public class Aba
{
[Key]
public Guid AbaId { get; set; }
public Guid EmpresaId { get; set; }
[Required]
public string Nome { get; set; }
public virtual Empresa Empresa { get; set; }
public virtual ICollection<Tela> Telas { get; set; }
}
public class Empresa
{
[Key]
public Guid EmpresaId { get; set; }
[Required]
public string Nome { get; set; }
public virtual ICollection<Aba> Abas { get; set; }
}
Note also that I'm using Guid
of purpose, to the detriment of int
, in setting the keys. There are some advantages to using that can be found here .
I did this because I want to use the Entity Framework naming conventions and automatically generate everything using Scaffolding . Once this is done, we can generate Controllers and Views through the IDE.
To do this, once you have set the 4 Models , right-click on the Controllers
directory and choose the Add > Controller ... :
Onthenextscreen,chooseMVC5ControllerwithViews,usingEntityFramework:
Next,definetheModelclass,thedatacontextclass,andtheControllername.HereImadeittoEmpresa
.Itlookslikethis:
ByclickingAdd,theresultshouldbe:
Notethatnotonlytheselection,drill-down,inclusion,edit,anddeletelogicweregenerated,butalsothecorrespondingViewsofeachoperation.
Repeattheprocessfortabs,screens,andscreenfunctions.
Oncethisisdone,youwillneedtoinstallapackagecalled BeginCollectionItem . I've told you a lot about it here , so I'll skip some parts.
Open the Package Manager Console ( View > Other Windows > Package Manager Console ) and install -O.
OpenTelasController
(I'massumingyou'vealreadygeneratedit)andViews/Telas/Create.cshtml
.Let'sstartwithView.Mineislikethis:
@modelMeuProjeto.Models.Tela@{ViewBag.Title="Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Tela</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.AbaId, "AbaId", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("AbaId", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.AbaId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
</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")
}
Between the "Create" button and the last field, Nome
, place a Partial call declaration like this:
<div class="form-group">
@Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
</div>
</div>
@Html.Partial("_Permissoes", Model.TelaFuncoes)
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
That is, we are sending to another View (in this case, a partial View ) only TelaFuncoes
. There we will build our whitelist.
Create a Partial named "_Permissoes":
Putthefollowingintoit:
@modelIEnumerable<MeuProjeto.Models.TelaFuncao><divclass="actions">
<a class="btn btn-default btn-sm" id="adicionar-nova-permissao">
Adicionar Nova Permissão
</a>
<script type="text/javascript">
$("#adicionar-nova-permissao").click(function () {
$.get('/Telas/NovaLinhaPermissao', function (template) {
$("#area-permissoes").append(template);
});
});
</script>
</div>
<div id="area-permissoes">
@if (Model != null)
{
foreach (var permissao in Model)
{
@Html.Partial("_LinhaPermissao", permissao);
}
}
</div>
Well, if you read the code, you'll notice that we'll need another Partial named _LinhaPermissao
. Create this Partial and put the following into it:
@model MeuProjeto.Models.TelaFuncao
@using (Html.BeginCollectionItem("TelaFuncoes"))
{
<div class="form-group">
@Html.HiddenFor(model => model.TelaFuncaoId)
@Html.HiddenFor(model => model.TelaId)
<label class="col-md-1 control-label">Nome</label>
<div class="col-md-5">
@Html.TextBoxFor(model => model.Nome, new { @class = "form-control", placeholder = "Nome" })
@Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })
</div>
<div class="col-md-2">
<a class="btn red" onclick="$(this).parent().parent().remove();">Excluir</a>
</div>
</div>
}
If you did everything right, the screen should look like this:
Ifyounoticed,inourTelasController
,weneedtoaddamethodcalledNovaLinhaPermissao
.Itlookslikethis:
publicActionResultNovaLinhaPermissao(){returnPartialView("_LinhaPermissao", new TelaFuncao { TelaFuncaoId = Guid.NewGuid() });
}
And now we can add and delete permissions.
Andwhenweadd3permissionsandsendtoCreate
ofTelasController
,wehavethe3permissionsthere.
As an exercise, edit now. If you need help, open another question (this one is already too big).
PS: Delete a repository of your architecture. The Entity Framework is already a repository.