Neste artigo será apresentado o funcionamento do pacote MvcScaffolding onde conheceremos os conceitos do funcionamento de sua estrutura e em seguida, colocaremos em prática através de seu uso em uma aplicação ASP.NET MVC 4. Através desse pacote podemos automatizar tarefas comuns no desenvolvimento de aplicações web como é o caso dos crudes.

Para simplificar, daremos como exemplo a view engine Razor do MVC, pois com ela se pode criar uma view com toda a estrutura de insert, update e delete já implementada a partir de sua classe model. Já com o MvcScaffolding você pode gerar toda a estrutura de sua aplicação como Controllers, Views (inclusive tabelas) e banco de dados baseado em suas classes model. Entre os seus principais recursos estão:

  • Suporte as linguagens de programação C# e VB.Net
  • Permite total liberdade de personalização da estrutura criada.
  • Permite sua utilização tanto na view engine razor quanto na aspx.
  • Integração com a versão do Entity framework mais atual 6.0

Criando o Projeto

Para demonstrar o funcionamento do pacote criaremos uma aplicação ASP.NET MVC 4 Web Aplicattion usando o template Internet Application com o nome de MvcScaffoldingApplication no visual studio 2010, como mostrado nas Figuras 1 e 2.

Criação do
projeto no visual studio 2010
Figura 1. Criação do projeto no visual studio 2010.
Escolha do Aspx
como View engine
Figura 2. Escolha do Aspx como View engine.

Nota: O versão 4 do MVC não é nativa no visual studio 2010. Para usá-la você deve fazer o download do ASP.NET MVC 4.

Neste exemplo usaremos Aspx como view engine para fins didáticos, pois as versões novas do MVC framework trazem recursos de criação templates de views com crudes básicos e também, para o caso de, por alguma regra de infraestrutura, o razor não puder ser utilizado. Nos preocuparemos agora em criar aquilo que será a base da estrutura da nossa aplicação -nossos Models -, como mostrado na Listagem 1.

Listagem 1. Código fonte dos Models Agencias e Pacotes.

  public class Agencia
      {
          [Key]
          public int AgenciaId { get; set; }
   
          [Required]
          public string Endereco { get; set; }
   
          public DateTime DtInauguracao { get; set; }
   
          public virtual ICollection<Pacotes> Pacotes { get; set; }
      }
    
  public class Pacotes
      {
          [Key]
          public int PacotesId { get; set; }
          [Required]
          public string NomePacote { get; set; }
          [Required]
          public string Origem { get; set; }
          [Required]
          public string Destino { get; set; }
   
          public virtual Agencia Agencia { get; set; } 
      }

Note o uso de recursos dos DataAnnotations, como o Required e Key, para indicar quais campos serão de preenchimento obrigatório e que farão a relação de chave primária das nossas duas classes. Note também o uso de objetos para criar a relação de Chave Estrangeira nas tabelas onde cada pacote pertencerá há uma agência e cada agência poderá ter vários pacotes e, por último, vale ressaltar que esse é o momento mais importante e o que requer mais cuidado na criação da aplicação, pois os nossos models serão o espelho da base de dados.

Instalando o Pacote

Vamos agora instalar o MvcScaffolding ao projeto através do Package Manager Console. Para isso, no menu Tools (Ferramentas) clique em Library Package Manager(Gerenciador de Pacotes de bibliotecas) e a seguir em Package Manager Console(Console do gerenciador de pacote). Com o gerenciador aberto digite o comando Install-Package MvcScaffolding e tecle enter, como mostrado na Figura 3.

Instalação do
pacote realizada com sucesso
Figura 3. Instalação do pacote realizada com sucesso.

Caso você não tenha o Package Manager Console instalado no seu visual Studio, pode-se também adicionar através do Nuget no menu Library Package Manager -> Manage Nuget Packages for Solution, como mostrado na Figura 4.

Instalação do
pacote via Nuget
Figura 4. Instalação do pacote via Nuget.

Criaremos agora nossa estrutura para as operações CRUD. Para isso, use o seguinte comando do Scaffolding no Package Manager Console Scaffold Controller Pacotes –Force e Scaffold Controller Agencia –Force, como na Figura 5.

Criação da estrutura pelo Scaffolding
Figura 5. Criação da estrutura pelo Scaffolding.

Podemos checar agora no Solution Explorer a criação dos nossos controllers AgenciasController.cs , PacotesController.cs e também a criação das nossas views básicas que são Create.aspx, Delete.aspx, Details.aspx, Edit.aspx, Index.aspx e CreateOrEdit.aspx. Executarmos nossa aplicação clicando em F5 ou clicando em execute como mostrado nas Figuras 6 e 7.

Estrutura gerada
pelo Scaffolding
Figura 6. Estrutura gerada pelo Scaffolding.
Aplicação
executada com sucesso
Figura 7. Aplicação executada com sucesso.

Personalizando a Aplicação

Antes de percorremos todos os fluxos básicos da aplicação, iremos dar uma incrementada nela, personalizando sua estrutura para dar um tom mais profissional ao aplicarmos padrões de desenvolvimento à mesma. Para isso, desacoplaremos nossos controles e faremos com que o componente crie para nós as classes repositório digitando as seguintes linhas:

>> Scaffold Controller Agencias -Repository

>> Scaffold Controller Pacotes -Repository

Se retornarmos a estrutura do nosso projeto poderemos ver que ela foi alterada com o incremento de mais duas classes que servirão como nossos repositórios. As boas práticas aconselham a programar todas as nossas regras de negócio nelas, como mostra a Listagem 2.

Listagem 2. Codigo fonte PacotesRepository com todos os métodos de negócio.

     public class PacotesRepository : IPacotesRepository
      {
          MvcScanffodingApplicationContext context = new 
           MvcScanffodingApplicationContext();
   
          public IQueryable<Pacotes> All
          {
              get { return context.Pacotes; }
          }
   
          public IQueryable<Pacotes> AllIncluding
           (params Expression<Func<Pacotes, object>>[] includeProperties)
          {
              IQueryable<Pacotes> query = context.Pacotes;
              foreach (var includeProperty in includeProperties) {
                  query = query.Include(includeProperty);
              }
              return query;
          }
   
          public Pacotes Find(int id)
          {
              return context.Pacotes.Find(id);
          }
   
          public void InsertOrUpdate(Pacotes pacotes)
          {
              if (pacotes.PacotesId == default(int)) {
                  // New entity
                  context.Pacotes.Add(pacotes);
              } else {
                  // Existing entity
                  context.Entry(pacotes).State = EntityState.Modified;
              }
          }
   
          public void Delete(int id)
          {
              var pacotes = context.Pacotes.Find(id);
              context.Pacotes.Remove(pacotes);
          }
   
          public void Save()
          {
              context.SaveChanges();
          }
   
          public void Dispose() 
          {
              context.Dispose();
          }
      }
   
      public interface IPacotesRepository : IDisposable
      {
          IQueryable<Pacotes> All { get; }
          IQueryable<Pacotes> AllIncluding
           (params Expression<Func<Pacotes, object>>[] includeProperties);
          Pacotes Find(int id);
          void InsertOrUpdate(Pacotes pacotes);
          void Delete(int id);
          void Save();
      }

Dependendo da versão do Scanffoding que você estiver utilizando, ao compilarmos será lançado o seguinte erro da Figura 8.

Aplicação
executada com sucesso
Figura 8. Aplicação executada com sucesso.

Esse erro acontece pelo fato de o pacote não conseguir implementar a diferença ambígua que existe nas classes System.Data.Entity.EntityState.Modified e System.Data.EntityState.Modified, derivadas das versões do Entity Framework. Para resolvermos isso, basta adicionarmos a referência direta ao System.Data.Entity onde os erros estiverem acontecendo, como mostrado na Listagem 3.

Listagem 3. Fonte do método InsertOrUpdate corrigido.

  public void InsertOrUpdate(Agencia agencia)
          {
              if (agencia.AgenciaId == default(int)) {
                  // New entity
                  context.Agencia.Add(agencia);
              } else {
                  // Existing entity
                  context.Entry(agencia).State = System.Data.Entity.EntityState.Modified;
              }
          }
   
  

Para finalizarmos nossa aplicação, iremos dar uma melhorada na nossa camada de apresentação. Para isso, editaremos nossas views adequando as mesmas ao idioma português, como mostrado na Listagem 4.

Listagem 4. Fonte do método InsertOrUpdate corrigido.

  // View Create
  <html>
  <head runat="server">
      <title>Novo</title>
  </head>
  <body>
      <% using (Html.BeginForm()) { %>
          <%: Html.ValidationSummary(true) %>
          <fieldset>
              <legend>Agencia</legend>
      
               <%: Html.Partial("CreateOrEdit", Model) %>
              <p>
                  <input type="submit" value="Enviar" />
              </p>
          </fieldset>
      <% } %>
      
      <div>
          <%: Html.ActionLink("Voltar", "Index") %>
      </div>
  </body>
  </html>
   
  // View Index
  <body>
      <p>
          <%: Html.ActionLink("Novo", "Create") %>
      </p>
      <table>
          <tr>
              <th></th>
              <th>
                  Endereco
              </th>
              <th>
                 Inauguracao
              </th>
              <th>
                  Pacotes
              </th>
          </tr>
      
      <% foreach (var item in Model) { %>
          <tr>
              <td>
                  <%: Html.ActionLink("Edit", "Editar", 
                    new { id=item.AgenciaId }) %> |
                  <%: Html.ActionLink("Details", "Detalhes", 
                    new { id=item.AgenciaId }) %> |
                  <%: Html.ActionLink("Delete", "Apagar", 
                        new { id=item.AgenciaId }) %>
              </td>
              <td>
                      <%: item.Endereco %>
              </td>
              <td>
                      <%: String.Format("{0:g}", item.DtInauguracao) %>
              </td>
              <td>
                      <%: (item.Pacotes == null ? "None" : 
                        item.Pacotes.Count.ToString()) %>
              </td>
          </tr>  
      <% } %>
      
      </table>
  </body>
  

Colocando nossa aplicação para rodar veremos nossas telas sendo executadas sem nenhum problema e com o idioma português, como mostrado nas Figuras 9 e 10.

 View Create
Agencias
Figura 9. View Create Agencias.
View Index
Agencias
Figura 10. View Index Agencias.