ASP.net Core APP 03 – Cadastro de produtos
O objetivo deste tutorial é construir uma tela de cadastro de produtos, que posteriormente será transformada em uma tela de cadastro complexa (Pai/Filho), permitindo vincular características aos produtos cadastrados. Para isso o primeiro passo é criar dentro da pasta Controllers do projeto uma nova classe chamada ProductController, nela vamos criar duas actions Index e Form.

using Microsoft.AspNetCore.Mvc; namespace myshop.Controllers { public class ProductController : Controller { public IActionResult Index() { return View(); } public IActionResult Form() { return View(); } } }
Agora dentro da pasta Views vamos criar uma nova subpasta chamada Product. Nesta pasta vamos criar as interfaces do controlador Product.

Crie um novo arquivo com o nome Form.cshtml e utilize o código de exemplo abaixo como base.
<!DOCTYPE HTML> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="pragma" content="no-cache" /> <meta http-equiv="cache-control" content="max-age=604800" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="author" content="Bootstrap-ecommerce by Vosidiy"> <title>UI KIT - Marketplace and Ecommerce html template</title> <link href="/images/favicon.ico" rel="shortcut icon" type="image/x-icon"> <!-- jQuery --> <script src="/js/jquery-2.0.0.min.js" type="text/javascript"></script> <!-- Bootstrap4 files--> <script src="/js/bootstrap.bundle.min.js" type="text/javascript"></script> <link href="/css/bootstrap.css" rel="stylesheet" type="text/css"/> <!-- Font awesome 5 --> <link href="/fonts/fontawesome/stylesheets/fontawesome-all.min.css" type="text/css" rel="stylesheet"> <!-- custom style --> <link href="/css/ui.css" rel="stylesheet" type="text/css"/> <link href="/css/responsive.css" rel="stylesheet" media="only screen and (max-width: 1200px)" /> <!-- custom javascript --> <script src="/js/script.js" type="text/javascript"></script> <script type="text/javascript"> /// some script // jquery ready start $(document).ready(function() { // jQuery code }); // jquery end </script> </head> <body> <header class="section-header"> <nav class="navbar navbar-top navbar-expand-lg navbar-dark bg-secondary"> <div class="container"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="http://bootstrap-ecommerce.com">Home <span class="sr-only">(current)</span></a> </li> <li class="nav-item"><a class="nav-link" href="html-components.html"> Documentation </a></li> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown"> Dropdown </a> <ul class="dropdown-menu"> <li><a class="dropdown-item" href="#"> Menu item 1</a></li> <li><a class="dropdown-item" href="#"> Menu item 2 </a></li> </ul> </li> <li class="nav-item"><a class="nav-link" href="http://bootstrap-ecommerce.com"> Download <i class="fa fa-download"></i></a></li> </ul> </div> </div> <!-- container // --> </nav> <section class="header-main shadow"> <div class="container"> <div class="row align-items-center"> <div class="col-lg-3 col-sm-4"> <div class="brand-wrap"> <img class="logo" src="images/logo-dark.png"> <h2 class="logo-text">LOGO</h2> </div> <!-- brand-wrap.// --> </div> <div class="col-lg-6 col-sm-8"> </div> <!-- col.// --> <div class="col-lg-3 col-sm-12"> <a href="#" class="widget-header float-md-right"> <div class="icontext"> <div class="icon-wrap"><i class="flip-h fa-lg fa fa-phone"></i></div> <div class="text-wrap"> <small>Phone</small> <div>+97150 2813773</div> </div> </div> </a> </div> <!-- col.// --> </div> <!-- row.// --> </div> <!-- container.// --> </section> <!-- header-main .// --> </header> <!-- section-header.// --> <!-- ========================= SECTION PAGETOP ========================= --> <section class="section-pagetop bg-secondary"> <div class="container clearfix"> <h2 class="title-page">Produto</h2> </div> <!-- container // --> </section> <!-- ========================= SECTION INTRO END// ========================= --> <!-- ========================= SECTION CONTENT ========================= --> <section class="section-content bg padding-y"> <div class="container"> <div class="row"> <main class="col-sm-9"> <article class="card"> <div class="card-body"> <form action = "/product/save" method="POST"> <div class="form-group"> <label for="inputName">Nome</label> <input type="text" class="form-control" id="inputName" name="name" placeholder="Nome do produto"> </div> <div class="form-group"> <label for="inputDesc">Descrição</label> <textarea rows="5" cols="33" class="form-control" id="inputDesc" name="description" placeholder="Descrição do produto"></textarea> </div> <div class="form-group"> <label for="inputPrice">Preço</label> <input type="number" min="0" max="1000" step="0.25" class="form-control" id="inputPrice" name="price" placeholder="Preço do produto"> </div> <button type="submit" class="btn btn-primary">Salvar</button> </form> </div> <!-- card-body .// --> </article> <!-- card product .// --> </main> <!-- col.// --> </div> </div> <!-- container .// --> </section> <!-- ========================= SECTION CONTENT END// ========================= --> <!-- ========================= FOOTER ========================= --> <footer class="section-footer bg-secondary"> <div class="container"> <section class="footer-top padding-top"> </section> <!-- //footer-top --> </div><!-- //container --> </footer> <!-- ========================= FOOTER END // ========================= --> </body> </html>
Em seguida utilize o comando dotnet run e acesse o endereço https://localhost:5001/product/form para verificar se a interface gráfica abaixo é carregada.

Agora vamos modificar nosso formulário para enviar os dados para o controlador. Para isso vamos utilizar o RAZOR para gerar o código HTML do formulário. No topo do arquivo Form.cshtml inclua o decorator @model para vincular a classe Product como model desta view. IMPORTANTE: caso sua aplicação tenha outro nome substitua myshop pelo nome da sua aplicação.
@model myshop.Models.Product;

Agora procure no código da view pela tag form. Vamos modificar o código dela primeiro substituindo o form tradicional pelo decorator @using e a classe helper Html.BeginForm para que os dados do formulário sejam enviados para o controlador Product na nova action que vamos escrever. Vamos também substituir os tags do formulário pelos helpers do Razor para gerar os campos do formulário.

@using (Html.BeginForm("Form","Product")){ <!--<form action = "/product/save" method="POST">--> @Html.HiddenFor(m => m.Id) <div class="form-group"> @Html.LabelFor(m => m.Name) @Html.EditorFor(m => m.Name, new { htmlAttributes = new { @class = "form-control" }}) @Html.ValidationMessageFor(m => m.Name) </div> <div class="form-group"> @Html.LabelFor(m => m.Description) @Html.EditorFor(m => m.Description, new { htmlAttributes = new { @class = "form-control" }}) @Html.ValidationMessageFor(m => m.Description) </div> <div class="form-group"> @Html.LabelFor(m => m.Price) @Html.EditorFor(m => m.Price, new { htmlAttributes = new { @class = "form-control" }}) @Html.ValidationMessageFor(m => m.Price) </div> <button type="submit" class="btn btn-primary">Salvar</button> <!--</form>--> }
Agora que a nossa interface esta pronta vamos altera nossa classe ProductController para criar as novas actions necessárias para tratar o formulário. Observe que sobre as Actions Index() e Form() incluímos o decorador [HttpGet] para indicar que eles serão chamados quando o controlador receber uma requisição do tipo GET. Criamos uma sobrecarga do método Form(Product product) recebendo a instância da classe produto e anotamos com [HttpPost]. Execute a aplicação acesse o formulário e envie dados, depois verifique no console se o nome do produto é apresentado.

using System; using Microsoft.AspNetCore.Mvc; using myshop.Models; namespace myshop.Controllers { public class ProductController : Controller { [HttpGet] public IActionResult Index() { return View(); } [HttpGet] public IActionResult Form() { return View(); } [HttpPost] public IActionResult Form(Product product){ Console.WriteLine(product.Name); return View(); } } }

Agora devemos construir um novo método em nossa interface IProductService para permitir que os dados do produto sejam salvos no banco de dados.

using System.Collections.Generic; using myshop.Models; namespace myshop.Services { public interface IProductService { List<Product> GetAll(); List<Product> GetAllByName(string name); void save(Product product); } }
Em seguida vamos implementar o código deste método dentro da nossa classe de ProductService. Aproveitando a implementação do método já vamos deixar ele pronto para tanto incluir um novo produto quando enviar uma ação de atualização dos dados de um produto já existente.

using System; using System.Collections.Generic; using MongoDB.Bson; using MongoDB.Driver; using myshop.Models; namespace myshop.Services { public class ProductService : IProductService { MongoClient con; IMongoDatabase db; public ProductService() { con = new MongoClient("mongodb://172.18.0.35:27017"); db = con.GetDatabase("dbwalter"); if(db.GetCollection<Product>("Products") == null) db.CreateCollection("Products"); } public List<Product> GetAll() { var collection = db.GetCollection<Product>("Products"); return collection.Find<Product>(p => true).ToList(); } public List<Product> GetAllByName(string name){ var collection = db.GetCollection<Product>("Products"); return collection.Find<Product>(p => p.Name.ToLower().Contains(name.ToLower())).ToList(); } public void save(Product product) { var collection = db.GetCollection<Product>("Products"); if(product.Id == null | product.Id == String.Empty) collection.InsertOne(product); else{ var filter = Builders<Product>.Filter.Eq("Id", product.Id); var updateDefinition = Builders<Product>.Update .Set(p => p.Name, product.Name) .Set(p => p.Description, product.Description) .Set(p => p.Price, product.Price); collection.UpdateOne(filter,updateDefinition); } } } }
Para concluir, vamos alterar nossa class ProductController para criar um construtor e receber a instância do ProductService por injeção de dependência.

E ainda nesta classe ProductController modificar o método Form(Product product) para verficar se os dados do formulário estão válidos e então chamar o método save do serviço.

using System; using Microsoft.AspNetCore.Mvc; using myshop.Models; using myshop.Services; namespace myshop.Controllers { public class ProductController : Controller { private IProductService productService; public ProductController(IProductService productService) { this.productService = productService; } [HttpGet] public IActionResult Index() { return View(); } [HttpGet] public IActionResult Form() { return View(); } [HttpPost] public IActionResult Form(Product product){ if (ModelState.IsValid) { this.productService.save(product); return RedirectToAction("Index"); } return View(product); } } }