ASP.NET Core - CRUD com Master-Detail - III


  Hoje vamos iniciar uma série de artigos onde veremos como realizar as operações CRUD em um contexto mestre-detalhes em uma aplicação ASP.NET Core.

Continuando a segunda parte do artigo vamos criar o controller MembrosController e seus métodos Actions para realizar as operações CRUD na tabela Membros.

Criando o controlador MembrosController

Vamos agora criar um controlador chamado MembrosController na pasta Controllers que será responsável por realizar o CRUD na tabela Membros.

Iniciamos injetando uma instância do contexto no construtor do controlador e definindo o método Action List :

public class MembrosController : Controller
{
  
private readonly AppDbContext db;
  
public MembrosController(AppDbContext db)
   {
    
this.db = db;
   }

   [HttpPost]
  
public IActionResult List(int timeId)
   {
     MasterDetailViewModel model =
new()
     {
       Times = db.Times.ToList(),
       SelectedTime = db.Times.Find(timeId),
       EntradaDados = EntradaDados.Membros,
       ModoExibicao = ModoExibicao.Read
     };
     db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
    
return View("Main", model);
}

Neste código criamos um objeto MasterDetailViewModel e preenchemos suas propriedades onde definimos EntradaDados como Membros. Assim ao clicar no botão - Gerenciar Membros -  a action List será acionada e teremos o resultado abaixo :

Observe que no código estamos carregando explicitamente as entidades Membro para o time selecionado usando o método Load(),  essas entidades são usadas durante a renderização da tabela de detalhes no arquivo de visualização.

A seguir vamos criar a Action Select que será usada para selecionar um membro quando o usuário clicar no botão - Gerenciar Membro :

[HttpPost]
public IActionResult Select(int timeId, int membroId)
{
   MasterDetailViewModel model =
new()
   {
     Times = db.Times.ToList(),
     SelectedTime = db.Times.Find(timeId),
     SelectedMembro = db.Membros.Find(membroId),
     EntradaDados = EntradaDados.Membros,
     ModoExibicao = ModoExibicao.Read
   };
   db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
  
return View("Main", model);
}
 

Esta Action recebe o parâmetro de rota membroId e define um objeto MasterDetailViewModel onde estamos agora definindo o time selecionado usando o id do membro recebido e e o método Find() para localizar a entidade.

A seguir vamos criar mais dois métodos Actions InsertEntry e InsertSave para permitir a inclusão de um novo membro.

[HttpPost]
public IActionResult InsertEntry(int timeId)
{
   MasterDetailViewModel model =
new()
   {
      Times = db.Times.ToList(),
      SelectedTime = db.Times.Find(timeId),
      SelectedMembro =
null,
      EntradaDados = EntradaDados.Membros,
      ModoExibicao = ModoExibicao.Insert
   };
   db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
  
return View("Main", model);
}
[HttpPost]
public IActionResult InsertSave(Membro member)
{
   db.Membros.Add(member);
   db.SaveChanges();
   MasterDetailViewModel model =
new()
   {
     Times = db.Times.ToList(),
     SelectedTime = db.Times.Find(member.TimeId),
     SelectedMembro = db.Membros.Find(member.MembroId),
     EntradaDados = EntradaDados.Membros,
     ModoExibicao = ModoExibicao.Read
    };
    db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
   
return View("Main", model);
}

A Action InsertEntry() é invocada quando você clica no botão Inserir Membro da grade principal. A seguir, definimos a EntradaDados como Membros porque estamos adicionando um novo Membro. Também definimos o ModoExibicao como Insert porque queremos renderizar a interface do usuário como esta:

Ao clicar no botão Salva a Action InsertSave será invocada onde usamos o método Add() e SaveChanges() para adicionar um novo membro. Em seguida, definimos o membro recém-adicionada como o item selecionado na grade principal. Isso é feito definindo a propriedade SelectedMembro do objeto MasterDetailViewModel e ModoExibicao é alterado para o valor Read.

A seguir vamos criar duas Actions UpdateEntry() e UpdateSave() para realizar as operações de atualização :

[HttpPost]
public IActionResult UpdateEntry(int timeId, int membroId)
{
   MasterDetailViewModel model =
new()
   {
     Times = db.Times.ToList(),
     SelectedTime = db.Times.Find(timeId),
     SelectedMembro = db.Membros.Find(membroId),
     EntradaDados = EntradaDados.Membros,
     ModoExibicao = ModoExibicao.Update
   };
   db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
  
return View("Main", model);
}

[HttpPost]
public IActionResult UpdateSave(Membro membro)
{
  db.Membros.Update(membro);
  db.SaveChanges();
  MasterDetailViewModel model =
new()
  {
    Times = db.Times.ToList(),
    SelectedTime = db.Times.Find(membro.TimeId),
    SelectedMembro = db.Membros.Find(membro.MembroId),
    EntradaDados = EntradaDados.Membros,
    ModoExibicao = ModoExibicao.Read
  };
  db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
 
return View("Main", model);
}

A Action UpdateEntry() é invocada quando você clica no botão Editar. Passamos o parâmetro de rota membroId para esta Action e a seguir buscamos esse Membro específico e definimos a propriedade SelectedMembro de MasterDetailViewModel. Também definimos o ModoExibicao como Update, pois queremos renderizar a interface do usuário para atualização:

Quando você edita um registro de um Membro e clica no botão Salvar, a Action UpdateSave() é chamada. Nela, usamos os métodos Update() e SaveChanges() para atualizar esse registro do membro. Em seguida, alternamos o ModoExibicao para Read porque a operação de edição acabou.

A seguir vamos definir a Action Delete para deletar um membro selecionado

[HttpPost]
public IActionResult Delete(int timeId, int membroId)
{
   Membro membro = db.Membros.Find(membroId);
   db.Membros.Remove(membro);
   db.SaveChanges();
   MasterDetailViewModel model =
new()
   {
     Times = db.Times.ToList(),
     SelectedTime = db.Times.Find(timeId),
     SelectedMembro =
null,
     EntradaDados = EntradaDados.Membros,
     ModoExibicao = ModoExibicao.Read
    };
    db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
   
return View("Main", model);
}

Neste codigo encontramos o membro a ser deletado e então utilizamos os métodos Remove() e SaveChanges() para deletar aquele registro. Como o registro agora foi excluído, também definimos a propriedade SelectedMembro de MasterDetailViewModel como nula.

Se você decidir cancelar a operação e retornar pode clicar no botão Cancelar que irá acionar a Action CancelEntry() :

[HttpPost]
public IActionResult CancelEntry(int timeId)
{
  MasterDetailViewModel model =
new()
  {
     Times = db.Times.ToList(),
     SelectedTime = db.Times.Find(timeId),
     SelectedMembro =
null,
     EntradaDados = EntradaDados.Membros,
     ModoExibicao = ModoExibicao.Read
  };
  db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
 
return View("Main", model);
}

Aqui definimos SelectedMembro como null.

Para concluir vamos deinir a Action CancelSelection para cancelar a seleção do Membro :

[HttpPost]
public IActionResult CancelSelection(int timeId)
{
  MasterDetailViewModel model =
new()
  {
     Times = db.Times.ToList(),
     SelectedTime = db.Times.Find(timeId),
     SelectedMembro =
null,
     EntradaDados = EntradaDados.Membros,
     ModoExibicao = ModoExibicao.Read
  };
  db.Entry(model.SelectedTime).Collection(time => time.Membros).Load();
 
return View("Main", model);
}

Neste código definimos a propriedade SelectedMembro como null.

Isso concluimos o controller MembrosController; para simplificar não realizamos a validação do modelo e o tratamento de erros. Você pode adicionar esses recursos usando atributos de validação de dados como faria normalmente em qualquer aplicativo ASP.NET Core.

Na próxima parte vamos continuar focando na criação das views para criar a interface com o usuário em nosso projeto.

"O Senhor é o meu rochedo, e o meu lugar forte, e o meu libertador; o meu Deus, a minha fortaleza, em quem confio; o meu escudo, a força da minha salvação, e o meu alto refúgio."
Salmos 18:2

Referências:


José Carlos Macoratti