Versão
Idioma

Tutorial do ASP.NET Core MVC - Parte I

Sobre este tutorial

Nesta série de tutoriais, você criará um aplicativo usado para gerenciar uma lista de livros e seus autores. O Entity Framework Core (EF Core) será usado como o provedor ORM, pois é o provedor de banco de dados padrão.

Esta é a primeira parte da série de tutoriais do ASP.NET Core MVC. Veja todas as peças:

Você pode acessar o código fonte do aplicativo no repositório GitHub .

Você também pode assistir a este curso em vídeo preparado por um membro da comunidade ABP, com base neste tutorial.

Criando o projeto

Crie um novo projeto chamado Acme.BookStore, crie o banco de dados e execute o aplicativo seguindo o documento Introdução.

Estrutura da solução

É assim que a estrutura da solução em camadas cuida da criação:

livraria-visual-studio-solução

Você pode ver o documento do modelo de aplicativo para entender a estrutura da solução em detalhes. No entanto, você entenderá o básico com este tutorial.

Criar a entidade do livro

A camada de domínio no modelo de inicialização é separada em dois projetos:

  • Acme.BookStore.Domaincontém suas entidades , serviços de domínio e outros objetos principais de domínio.
  • Acme.BookStore.Domain.Shared contém constantes, enumerações ou outros objetos relacionados ao domínio que podem ser compartilhados com os clientes.

Defina entidades na camada de domínio ( Acme.BookStore.Domainprojeto) da solução. A entidade principal do aplicativo é a Book. Crie uma classe, chamada Book, no Acme.BookStore.Domainprojeto, como mostrado abaixo:

using System;
using Volo.Abp.Domain.Entities.Auditing;

namespace Acme.BookStore
{
    public class Book : AuditedAggregateRoot<Guid>
    {
        public string Name { get; set; }

        public BookType Type { get; set; }

        public DateTime PublishDate { get; set; }

        public float Price { get; set; }
    }
}
  • O ABP possui duas classes base fundamentais para entidades: AggregateRoote Entity. A raiz agregada é um dos conceitos de DDD (Domain Driven Design) . Consulte o documento da entidade para obter detalhes e melhores práticas.
  • Bookentidade herda AuditedAggregateRootque adiciona algumas propriedades de auditoria ( CreationTime, CreatorId, LastModificationTime... etc.) no topo da AggregateRootclasse.
  • Guidé o tipo de chave primária da Bookentidade.

BookType Enum

Defina a BookTypeenumeração no Acme.BookStore.Domain.Sharedprojeto:

namespace Acme.BookStore
{
    public enum BookType
    {
        Undefined,
        Adventure,
        Biography,
        Dystopia,
        Fantastic,
        Horror,
        Science,
        ScienceFiction,
        Poetry
    }
}

Adicionar entidade de livro ao seu DbContext

O EF Core exige que você relacione entidades com seu DbContext. A maneira mais fácil de fazer isso é adicionar uma DbSetpropriedade à BookStoreDbContextclasse no Acme.BookStore.EntityFrameworkCoreprojeto, conforme mostrado abaixo:

    public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
    {
        public DbSet<Book> Books { get; set; }
		...
    }

Configure sua entidade do livro

Abra o BookStoreDbContextModelCreatingExtensions.csarquivo no Acme.BookStore.EntityFrameworkCoreprojeto e adicione o seguinte código ao final do ConfigureBookStoremétodo para configurar a entidade Livro:

builder.Entity<Book>(b =>
{
    b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema);
    b.ConfigureByConvention(); //auto configure for the base class props
    b.Property(x => x.Name).IsRequired().HasMaxLength(128);
});

Adicionar nova migração e atualizar o banco de dados

O modelo de inicialização usa as primeiras migrações do código principal EF para criar e manter o esquema do banco de dados. Abra o Gerenciador de Console Package (PMC) (sob as Ferramentas / Gerente Nuget Package menu), selecione o Acme.BookStore.EntityFrameworkCore.DbMigrationscomo o projeto padrão e execute o seguinte comando:

livraria-pmc-add-book-migration

Isso criará uma nova classe de migração dentro da Migrationspasta. Em seguida, execute o Update-Databasecomando para atualizar o esquema do banco de dados:

PM> Update-Database

Adicionar dados de amostra

Update-DatabaseO comando criou a AppBookstabela no banco de dados. Abra seu banco de dados e insira algumas linhas de amostra, para que você possa mostrá-las na página:

livraria-livros-mesa

Crie o serviço de aplicativo

O próximo passo é criar um serviço de aplicativo para gerenciar (criar, listar, atualizar, excluir ...) os livros. A camada de aplicativo no modelo de inicialização é separada em dois projetos:

  • Acme.BookStore.Application.Contracts contém principalmente seus DTOs e interfaces de serviço de aplicativo.
  • Acme.BookStore.Application contém as implementações dos seus serviços de aplicativo.

BookDto

Crie uma classe DTO denominada BookDtono Acme.BookStore.Application.Contractsprojeto:

using System;
using Volo.Abp.Application.Dtos;

namespace Acme.BookStore
{
    public class BookDto : AuditedEntityDto<Guid>
    {
        public string Name { get; set; }

        public BookType Type { get; set; }

        public DateTime PublishDate { get; set; }

        public float Price { get; set; }
    }
}
  • As classes DTO são usadas para transferir dados entre a camada de apresentação e a camada de aplicativo . Consulte o documento Objetos de transferência de dados para obter mais detalhes.
  • BookDto é usado para transferir dados do livro para a camada de apresentação para mostrar as informações do livro na interface do usuário.
  • BookDtoé derivado do AuditedEntityDto<Guid>que possui propriedades de auditoria exatamente como a Bookclasse definida acima.

Será necessário converter Bookentidades em BookDtoobjetos enquanto retorna os livros para a camada de apresentação. A biblioteca do AutoMapper pode automatizar essa conversão quando você define o mapeamento adequado. O modelo de inicialização é fornecido com o AutoMapper configurado, para que você possa definir o mapeamento na BookStoreApplicationAutoMapperProfileclasse no Acme.BookStore.Applicationprojeto:

using AutoMapper;

namespace Acme.BookStore
{
    public class BookStoreApplicationAutoMapperProfile : Profile
    {
        public BookStoreApplicationAutoMapperProfile()
        {
            CreateMap<Book, BookDto>();
        }
    }
}

CreateUpdateBookDto

Crie uma classe DTO denominada CreateUpdateBookDtono Acme.BookStore.Application.Contractsprojeto:

using System;
using System.ComponentModel.DataAnnotations;

namespace Acme.BookStore
{
    public class CreateUpdateBookDto
    {
        [Required]
        [StringLength(128)]
        public string Name { get; set; }

        [Required]
        public BookType Type { get; set; } = BookType.Undefined;

        [Required]
        public DateTime PublishDate { get; set; }

        [Required]
        public float Price { get; set; }
    }
}
  • Essa classe DTO é usada para obter informações do livro a partir da interface do usuário ao criar ou atualizar um livro.
  • Ele define atributos de anotação de dados (como [Required]) para definir validações para as propriedades. Os DTOs são validados automaticamente pela estrutura ABP.

Em seguida, adicione um mapeamento BookStoreApplicationAutoMapperProfiledo CreateUpdateBookDtoobjeto à Bookentidade:

CreateMap<CreateUpdateBookDto, Book>();

IBookAppService

Defina uma interface nomeada IBookAppServiceno Acme.BookStore.Application.Contractsprojeto:

using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;

namespace Acme.BookStore
{
    public interface IBookAppService :
        ICrudAppService< //Defines CRUD methods
            BookDto, //Used to show books
            Guid, //Primary key of the book entity
            PagedAndSortedResultRequestDto, //Used for paging/sorting on getting a list of books
            CreateUpdateBookDto, //Used to create a new book
            CreateUpdateBookDto> //Used to update a book
    {

    }
}
  • A definição de interfaces para serviços de aplicativos não é requerida pela estrutura. No entanto, é sugerido como uma prática recomendada.
  • ICrudAppServicedefine comuns CRUD métodos: GetAsync, GetListAsync, CreateAsync, UpdateAsynce DeleteAsync. Não é necessário estendê-lo. Em vez disso, você pode herdar da IApplicationServiceinterface vazia e definir seus próprios métodos manualmente.
  • Existem algumas variações de ICrudAppServiceonde você pode usar DTOs separados para cada método.

BookAppService

Implemente IBookAppServicecomo nomeado BookAppServiceno Acme.BookStore.Applicationprojeto:

using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace Acme.BookStore
{
    public class BookAppService :
        CrudAppService<Book, BookDto, Guid, PagedAndSortedResultRequestDto,
                       CreateUpdateBookDto, CreateUpdateBookDto>,
        IBookAppService
    {
        public BookAppService(IRepository<Book, Guid> repository)
            : base(repository)
        {

        }
    }
}
  • BookAppServiceé derivado do CrudAppService<...>qual implementa todos os métodos CRUD definidos acima.
  • BookAppServiceinjeta IRepository<Book, Guid>qual é o repositório padrão da Bookentidade. O ABP cria automaticamente repositórios padrão para cada raiz (ou entidade) agregada. Veja o documento do repositório .
  • BookAppServiceusa IObjectMapperpara converter Bookobjetos em BookDtoobjetos e CreateUpdateBookDtoobjetos em Bookobjetos. O modelo de inicialização usa a biblioteca AutoMapper como o provedor de mapeamento de objetos. Você definiu os mapeamentos antes, para que funcionem conforme o esperado.

Controladores de API automática

Você normalmente cria controladores para expor serviços de aplicativos como pontos de extremidade da API HTTP . Assim, permite que navegadores ou clientes de terceiros os chamem via AJAX. O ABP pode configurar automaticamente seus serviços de aplicativo como controladores de API MVC por convenção.

UI do Swagger

O modelo de inicialização está configurado para executar a interface do usuário do swagger usando a biblioteca Swashbuckle.AspNetCore . Execute o aplicativo e insira https://localhost:XXXX/swagger/(substitua XXXX por sua própria porta) como URL no seu navegador.

Você verá alguns pontos de extremidade de serviço internos, bem como o Bookserviço e seus pontos de extremidade no estilo REST:

livraria-arrogância

O Swagger tem uma ótima interface para testar APIs. Você pode tentar executar a [GET] /api/app/bookAPI para obter uma lista de livros.

Proxies dinâmicos de JavaScript

É comum chamar pontos de extremidade da API HTTP via AJAX do lado do JavaScript . Você pode usar $.ajaxou outra ferramenta para chamar os pontos de extremidade. No entanto, o ABP oferece uma maneira melhor.

O ABP cria dinamicamente proxies JavaScript para todos os pontos de extremidade da API. Portanto, você pode usar qualquer terminal, assim como chamar uma função JavaScript .

Testando no console do desenvolvedor do navegador

Você pode testar facilmente os proxies JavaScript usando o Console do desenvolvedor do seu navegador favorito agora. Execute o aplicativo, abra as ferramentas de desenvolvedor do navegador (atalho: F12), vá para a guia Console , digite o seguinte código e pressione enter:

acme.bookStore.book.getList({}).done(function (result) { console.log(result); });
  • acme.bookStoreé o espaço para nome do BookAppServiceconvertido em camelCase .
  • booké o nome convencional para o BookAppService(postfix do AppService removido e convertido em camelCase).
  • getListé o nome convencional para o GetListAsyncmétodo definido na AsyncCrudAppServiceclasse base (postfix assíncrono removido e convertido em camelCase).
  • {}O argumento é usado para enviar um objeto vazio ao GetListAsyncmétodo que normalmente espera um objeto do tipo PagedAndSortedResultRequestDtousado para enviar opções de paginação e classificação ao servidor (todas as propriedades são opcionais, para que você possa enviar um objeto vazio).
  • getListA função retorna a promise. Portanto, você pode passar um retorno de chamada para a função done(ou then) para obter o resultado do servidor.

A execução desse código produz a seguinte saída:

livraria-teste-js-proxy-getlist

Você pode ver a lista de livros retornada do servidor. Você também pode verificar a guia de rede das ferramentas do desenvolvedor para ver a comunicação do cliente com o servidor:

livraria-teste-js-proxy-getlist-rede

Vamos criar um novo livro usando a createfunção:

acme.bookStore.book.create({ name: 'Foundation', type: 7, publishDate: '1951-05-24', price: 21.5 }).done(function (result) { console.log('successfully created the book with id: ' + result.id); });

Você deve ver uma mensagem no console, algo assim:

successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7

Verifique a Bookstabela no banco de dados para ver a nova linha do livro. Você pode tentar get, updatee deletefunciona mesmo.

Crie a página de livros

É hora de criar algo visível e utilizável! Em vez do MVC clássico, usaremos a nova abordagem de interface do usuário do Razor Pages, recomendada pela Microsoft.

Crie uma nova Bookspasta na Pagespasta do Acme.BookStore.Webprojeto e adicione uma nova página Razor denominada Index.cshtml:

livraria-add-index-page

Abra Index.cshtmle altere o conteúdo, como mostrado abaixo:

@page
@using Acme.BookStore.Web.Pages.Books
@model IndexModel

<h2>Books</h2>
  • Verifique se o IndexModel( Index.cshtml.cs) possui o Acme.BookStore.Pages.Booksespaço para nome ou atualize-o no Index.cshtml.

Adicionar página de livros ao menu principal

Abra a BookStoreMenuContributorclasse na Menuspasta e adicione o seguinte código ao final do ConfigureMainMenuAsyncmétodo:

context.Menu.AddItem(
    new ApplicationMenuItem("BooksStore", l["Menu:BookStore"])
        .AddItem(new ApplicationMenuItem("BooksStore.Books", l["Menu:Books"], url: "/Books"))
);

Localizando os itens de menu

Os textos de localização estão localizados na Localization/BookStorepasta do Acme.BookStore.Domain.Sharedprojeto:

arquivos de localização de livraria

Abra o en.jsonarquivo e adicione textos de localização Menu:BookStoree Menu:Bookschaves ao final do arquivo:

{
  "culture": "en",
  "texts": {
    "Menu:BookStore": "Book Store",
    "Menu:Books": "Books"
  }
}
  • O sistema de localização da ABP é construído no sistema de localização padrão do ASP.NET Core e o estende de várias maneiras. Consulte o documento de localização para obter detalhes.
  • Os nomes das chaves de localização são arbitrários. Você pode definir qualquer nome. Preferimos adicionar Menu:prefixo aos itens de menu para distinguir de outros textos. Se um texto não estiver definido no arquivo de localização, ele recuará para a chave de localização (comportamento padrão do ASP.NET Core).

Execute o aplicativo e veja se o novo item de menu foi adicionado à barra superior:

itens-menu-livraria

Quando você clica no item de menu Livros, você é redirecionado para a nova página Livros.

Lista de livros

Usaremos o plug-in Datatables.net JQuery para mostrar a lista de tabelas na página. As tabelas de dados podem funcionar completamente via AJAX, são rápidas e oferecem uma boa experiência ao usuário. O plug-in Datatables está configurado no modelo de inicialização, para que você possa usá-lo diretamente em qualquer página sem incluir nenhum estilo ou arquivo de script em sua página.

Index.cshtml

Altere o Pages/Books/Index.cshtmlseguinte:

@page
@model Acme.BookStore.Web.Pages.Books.IndexModel
@section scripts
{
    <abp-script src="/Pages/Books/index.js" />
}
<abp-card>
    <abp-card-header>
        <h2>@L["Books"]</h2>
    </abp-card-header>
    <abp-card-body>
        <abp-table striped-rows="true" id="BooksTable">
            <thead>
                <tr>
                    <th>@L["Name"]</th>
                    <th>@L["Type"]</th>
                    <th>@L["PublishDate"]</th>
                    <th>@L["Price"]</th>
                    <th>@L["CreationTime"]</th>
                </tr>
            </thead>
        </abp-table>
    </abp-card-body>
</abp-card>
  • abp-script O auxiliar de marca é usado para adicionar scripts externos à página. Possui muitos recursos adicionais em comparação com a scripttag padrão . Ele lida com minificação e controle de versão, por exemplo. Consulte o documento de compactação e redução para obter detalhes.
  • abp-carde abp-tablesão auxiliares de tags para o componente de cartão do Twitter Bootstrap . Existem muitos auxiliares de tag no ABP para usar facilmente a maioria dos componentes de autoinicialização . Você também pode usar tags HTML regulares em vez desses auxiliares de tag, mas o uso de tag reduz o código HTML e evita erros com a ajuda do intellisense e da verificação do tipo de tempo de compilação. Consulte o documento auxiliares da tag .
  • Você pode localizar os nomes das colunas no arquivo de localização, como fez nos itens de menu acima.
Adicionar um arquivo de script

Crie um index.jsarquivo JavaScript na Pages/Books/pasta:

arquivo-index-js-bookstore

index.js o conteúdo é mostrado abaixo:

$(function () {
    var dataTable = $('#BooksTable').DataTable(abp.libs.datatables.normalizeConfiguration({
        ajax: abp.libs.datatables.createAjax(acme.bookStore.book.getList),
        columnDefs: [
            { data: "name" },
            { data: "type" },
            { data: "publishDate" },
            { data: "price" },
            { data: "creationTime" }
        ]
    }));
});
  • abp.libs.datatables.createAjax é uma função auxiliar para adaptar os proxies dinâmicos da API JavaScript da ABP ao formato do Datatable.
  • abp.libs.datatables.normalizeConfigurationé outra função auxiliar. Não há necessidade de usá-lo, mas simplifica a configuração das tabelas de dados, fornecendo valores convencionais para as opções ausentes.
  • acme.bookStore.book.getList é a função para obter a lista de livros (você já viu isso antes).
  • Consulte a documentação do Datatable para obter mais opções de configuração.

A interface do usuário final é mostrada abaixo:

livraria-lista-de-livros

Próxima parte

Veja a próxima parte deste tutorial.

Esta página foi útil?
Por favor, faça uma seleção.
Obrigado pelo seu valioso feedback!

Observe que, embora não possamos responder aos comentários, nossa equipe usará seus comentários para melhorar a experiência.

Neste documento
Mastering ABP Framework Book
Dominando a estrutura ABP

Este livro o ajudará a obter uma compreensão completa da estrutura e das técnicas modernas de desenvolvimento de aplicativos da web.