Browse Source

solve merge conflict

pull/1768/head
mehmet-erim 7 years ago
parent
commit
66b71d60c6
  1. 6
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  2. 9
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  3. 3
      docs/pt-BR/Aspect-Oriented-Programming.md
  4. 3
      docs/pt-BR/Audit-Logging.md
  5. 3
      docs/pt-BR/Authorization.md
  6. 3
      docs/pt-BR/AutoMapper-Integration.md
  7. 3
      docs/pt-BR/Background-Jobs-Hangfire.md
  8. 3
      docs/pt-BR/Background-Jobs-RabbitMq.md
  9. 149
      docs/pt-BR/CLI.md
  10. 3
      docs/pt-BR/Caching.md
  11. 60
      docs/pt-BR/Contribution/Index.md
  12. 3
      docs/pt-BR/CorrelationId.md
  13. 3
      docs/pt-BR/Data-Filtering.md
  14. 3
      docs/pt-BR/Data-Seeding.md
  15. 3
      docs/pt-BR/Data-Transfer-Objects.md
  16. 3
      docs/pt-BR/Distributed-Event-Bus.md
  17. 3
      docs/pt-BR/Domain-Services.md
  18. 3
      docs/pt-BR/Dynamic-Proxying-Interceptors.md
  19. 3
      docs/pt-BR/Emailing.md
  20. 3
      docs/pt-BR/Event-Bus.md
  21. 3
      docs/pt-BR/Extension-Methods-And-Helpers.md
  22. 126
      docs/pt-BR/Getting-Started-Angular-Template.md
  23. 183
      docs/pt-BR/Getting-Started-AspNetCore-Application.md
  24. 102
      docs/pt-BR/Getting-Started-AspNetCore-MVC-Template.md
  25. 182
      docs/pt-BR/Getting-Started-Console-Application.md
  26. 3
      docs/pt-BR/Guid-Generation.md
  27. 31
      docs/pt-BR/Index.md
  28. 3
      docs/pt-BR/Integration-Tests.md
  29. 3
      docs/pt-BR/Local-Event-Bus.md
  30. 195
      docs/pt-BR/Localization.md
  31. 27
      docs/pt-BR/Nightly-Builds.md
  32. 3
      docs/pt-BR/Object-To-Object-Mapping.md
  33. 3
      docs/pt-BR/SMS-Sending.md
  34. 3
      docs/pt-BR/Settings.md
  35. 3
      docs/pt-BR/Specifications.md
  36. 275
      docs/pt-BR/Startup-Templates/Application.md
  37. 7
      docs/pt-BR/Startup-Templates/Index.md
  38. 161
      docs/pt-BR/Startup-Templates/Module.md
  39. 3
      docs/pt-BR/Testing.md
  40. 661
      docs/pt-BR/Tutorials/Angular/Part-I.md
  41. 582
      docs/pt-BR/Tutorials/Angular/Part-II.md
  42. 181
      docs/pt-BR/Tutorials/Angular/Part-III.md
  43. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-actions-buttons.png
  44. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-angular-file-tree.png
  45. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-backend-solution-v2.png
  46. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-book-list.png
  47. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-confirmation-popup.png
  48. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-creating-book-list-terminal.png
  49. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-creating-books-module-terminal.png
  50. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-edit-modal.png
  51. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-empty-new-book-modal.png
  52. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-final-actions-dropdown.png
  53. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-initial-book-list-page.png
  54. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page-with-layout.png
  55. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page.png
  56. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form-v2.png
  57. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form.png
  58. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-service-terminal-output.png
  59. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-swagger-api.png
  60. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-test-explorer.png
  61. BIN
      docs/pt-BR/Tutorials/Angular/images/bookstore-test-projects-v3.png
  62. 462
      docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-I.md
  63. 466
      docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-II.md
  64. 182
      docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-III.md
  65. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png
  66. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-edit-dialog.png
  67. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png
  68. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png
  69. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list-2.png
  70. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list.png
  71. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table-actions.png
  72. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table.png
  73. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog-2.png
  74. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog.png
  75. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-template.png
  76. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-homepage.png
  77. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png
  78. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png
  79. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-menu-items.png
  80. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-new-book-button.png
  81. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png
  82. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration.png
  83. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-swagger.png
  84. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist-network.png
  85. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist.png
  86. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png
  87. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-user-management.png
  88. BIN
      docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png
  89. 3
      docs/pt-BR/Unit-Of-Work.md
  90. 3
      docs/pt-BR/Validation.md
  91. 3
      docs/pt-BR/Value-Objects.md
  92. 328
      docs/pt-BR/docs-nav.json
  93. BIN
      docs/pt-BR/images/MonthlyProfitWidgetFiles.png
  94. BIN
      docs/pt-BR/images/bookstore-apis.png
  95. BIN
      docs/pt-BR/images/bookstore-create-template.png
  96. BIN
      docs/pt-BR/images/bookstore-homepage.png
  97. BIN
      docs/pt-BR/images/bookstore-swagger-ui-host.png
  98. BIN
      docs/pt-BR/images/bookstore-user-management-v2.png
  99. BIN
      docs/pt-BR/images/bookstore-visual-studio-solution-for-spa.png
  100. BIN
      docs/pt-BR/images/bookstore-visual-studio-solution-tiered.png

6
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -21,6 +21,10 @@
"Modules": "Modules",
"LicenseExtendMessage": "Your license end date is extended to {0}",
"LicenseUpgradeMessage": "Your license is upgraded to {0}",
"LicenseAddDeveloperMessage": "{0} developers added to your license"
"LicenseAddDeveloperMessage": "{0} developers added to your license" ,
"Volo.AbpIo.Commercial:010004": "Can not find the specified user! The user must have already registered.",
"MyOrganizations": "My organizations",
"ApiKey": "API key",
"UserNameNotFound": "There is no user with username {0}"
}
}

9
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json

@ -18,6 +18,13 @@
"Manage": "Yönet",
"StartDate": "Başlangıç tarihi",
"EndDate": "bitiş tarihi",
"Modules": "Modüller"
"Modules": "Modüller",
"Volo.AbpIo.Commercial:010004": "Kullanıcı bulunamadı! İlgili kullanıcının daha önceden sisteme kayıt olmuş olması gerekiyor.",
"LicenseExtendMessage": "Lisans bitiş tarihiniz {0} tarihine kadar uzatıldı",
"LicenseUpgradeMessage": "Lisansınız {0} lisansa yükseltildi",
"LicenseAddDeveloperMessage": "Lisansınıza {0} geliştirici eklendi",
"MyOrganizations": "Organizasyonlarım",
"ApiKey": "API anahtarı",
"UserNameNotFound": "{0} kullanıcı adı ile bir kullanıcı yok"
}
}

3
docs/pt-BR/Aspect-Oriented-Programming.md

@ -0,0 +1,3 @@
## Dynamic Proxying / Interceptors
Façam

3
docs/pt-BR/Audit-Logging.md

@ -0,0 +1,3 @@
# Audit Logging
Façam

3
docs/pt-BR/Authorization.md

@ -0,0 +1,3 @@
## Authorization
Façam

3
docs/pt-BR/AutoMapper-Integration.md

@ -0,0 +1,3 @@
## AutoMapper Integration
Façam

3
docs/pt-BR/Background-Jobs-Hangfire.md

@ -0,0 +1,3 @@
# Hangfire Background Job Manager
Façam

3
docs/pt-BR/Background-Jobs-RabbitMq.md

@ -0,0 +1,3 @@
# RabbitMQ Background Job Manager
TODO

149
docs/pt-BR/CLI.md

@ -0,0 +1,149 @@
# ABP CLI
O ABP CLI (Command Line Interface) é uma ferramenta de linha de comando para executar algumas operações comuns para soluções baseadas em ABP.
## Instalação
O ABP CLI é uma [ferramenta global dotnet](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools) . Instale-o usando uma janela de linha de comando:
````bash
dotnet tool install -g Volo.Abp.Cli
````
Para atualizar uma instalação existente:
````bash
dotnet tool update -g Volo.Abp.Cli
````
## Comandos
### Novo
Gera uma nova solução baseada nos [modelos de inicialização](Startup-Templates/Index.md) do ABP .
Uso básico:
````bash
abp new <solution-name> [options]
````
Examplo:
````bash
abp new Acme.BookStore
````
* `Acme.BookStore` é o nome da solução aqui.
* A convenção comum é nomear uma solução como *YourCompany.YourProject* . No entanto, você pode usar nomes diferentes, como *YourProject* (namespacing de nível único) ou *YourCompany.YourProduct.YourModule* (namespacing de três níveis).
#### Opções
* `--template`ou `-t`: especifica o nome do modelo. O nome do modelo padrão é `app`, que gera um aplicativo da web. Modelos disponíveis:
* `app`(padrão): [modelo de aplicativo](https://docs.abp.io/en/abp/latest/Startup-Templates/Application) . Opções adicionais:
* `--ui`ou `-u`: Especifica a UI framework. Framework padrão é `mvc`. Framework disponíveis:
* `mvc`: ASP.NET Core MVC. Existem algumas opções adicionais para este modelo:
* `--tiered`: Cria uma solução em camadas em que as camadas da Web e da API HTTP são fisicamente separadas. Se não especificado, ele cria uma solução em camadas que é menos complexa e adequada para a maioria dos cenários.
* `angular`: Angular. Existem algumas opções adicionais para este modelo:
* `--separate-identity-server`: Separa o aplicativo do servidor de identidade do aplicativo host da API. Se não especificado, você terá um único ponto de extremidade no lado do servidor.
* `--database-provider` Ou `-d`: especifica o provedor de banco de dados. O provedor padrão é `ef`. Fornecedores disponíveis:
* `ef`: Entity Framework Core.
* `mongodb`: MongoDB.
* `module`: [Exemplo de Módulo](Startup-Templates/Module.md). Opções adicionais:
* `--no-ui`: Especifica para não incluir a UI. Isso possibilita a criação de módulos somente de serviço (também conhecidos como microsserviços - sem interface do usuário).
* `--output-folder` ou `-o`: especifica a pasta de saída. O valor padrão é o diretório atual.
* `--version` ou `-v`: Especifica a ABP & versão de exemplo . Pode ser uma [release tag](https://github.com/abpframework/abp/releases) ou um [branch name](https://github.com/abpframework/abp/branches). Usa a versão mais recente, se não especificado. Na maioria das vezes, você desejará usar a versão mais recente.
### add-package
Adiciona um pacote ABP a um projeto por,
- Adicionando pacote de nuget relacionado como uma dependência ao projeto.
- Adicionando `[DependsOn(...)]`atributo à classe de módulo no projeto (consulte o [documento de desenvolvimento](https://docs.abp.io/en/abp/latest/Module-Development-Basics) do [módulo](https://docs.abp.io/en/abp/latest/Module-Development-Basics) ).
> Observe que o módulo adicionado pode exigir uma configuração adicional, geralmente indicada na documentação do pacote relacionado.
Uso básico:
```bash
abp add-package <package-name> [options]
```
Bater
cópia de
Exemplo:
```
abp add-package Volo.Abp.MongoDB
```
- Este exemplo adiciona o pacote Volo.Abp.MongoDB ao projeto.
#### Opções
- `--project`ou `-p`: especifica o caminho do arquivo do projeto (.csproj). Se não especificado, a CLI tenta encontrar um arquivo .csproj no diretório atual.
### add-module
Adiciona um [módulo de aplicativo com vários pacotes](Modules/Index.md) a uma solução, localizando todos os pacotes do módulo, localizando projetos relacionados na solução e adicionando cada pacote ao projeto correspondente na solução.
> Um módulo de negócios geralmente consiste em vários pacotes (devido a camadas, diferentes opções de provedor de banco de dados ou outros motivos). O uso do `add-module`comando simplifica drasticamente a adição de um módulo a uma solução. No entanto, cada módulo pode exigir algumas configurações adicionais, geralmente indicadas na documentação do módulo relacionado.
Uso básico:
```bash
abp add-module <module-name> [options]
```
Exemplo:
```bash
abp add-module Volo.Blogging
```
- Este exemplo adiciona o módulo Volo.Blogging à solução.
#### Opções
- `--solution`ou `-s`: especifica o caminho do arquivo da solução (.sln). Se não especificado, a CLI tenta encontrar um arquivo .sln no diretório atual.
- `--skip-db-migrations`: Para o provedor de banco de dados EF Core, ele adiciona automaticamente um novo código à primeira migração ( `Add-Migration`) e atualiza o banco de dados ( `Update-Database`), se necessário. Especifique esta opção para pular esta operação.
- `-sp`ou `--startup-project`: caminho relativo para a pasta do projeto de inicialização. O valor padrão é a pasta atual.
### atualizar
A atualização de todos os pacotes relacionados ao ABP pode ser entediante, pois existem muitos pacotes da estrutura e dos módulos. Este comando atualiza automaticamente todos os pacotes NuGet e NPM relacionados ao ABP em uma solução ou projeto para as versões mais recentes.
Uso:
```bash
abp update [options]
```
- Se você executar em um diretório com um arquivo .sln, ele atualizará todos os pacotes relacionados ao ABP de todos os projetos da solução para as versões mais recentes.
- Se você executar em um diretório com um arquivo .csproj, ele atualizará todos os pacotes relacionados ao ABP do projeto para as versões mais recentes.
#### Opções
- `--include-previews`ou `-p`: inclui pacotes de visualização, beta e rc enquanto verifica as versões mais recentes.
### Socorro
Grava informações básicas de uso da CLI.
Uso:
```bash
abp help [command-name]
```
Exemplos:
```bash
abp help # Shows a general help.
abp help new # Shows help about the "new" command.
```

3
docs/pt-BR/Caching.md

@ -0,0 +1,3 @@
# Caching
Façam

60
docs/pt-BR/Contribution/Index.md

@ -0,0 +1,60 @@
## Guia de Contribuição
O ABP é um projeto de [código aberto](https://github.com/abpframework) e orientado à comunidade. Este guia tem como objetivo ajudar alguém que queira contribuir com o projeto.
### Contribuição de código
Você sempre pode enviar solicitações pull ao repositório do Github.
- Clone o [repositório ABP](https://github.com/abpframework/abp/) do Github.
- Faça as alterações necessárias.
- Envie uma solicitação de recebimento.
Antes de fazer qualquer alteração, discuta-a sobre os [problemas](https://github.com/abpframework/abp/issues) do [Github](https://github.com/abpframework/abp/issues) . Dessa forma, nenhum outro desenvolvedor trabalhará no mesmo problema e seu PR terá uma chance melhor de ser aceito.
#### Correções de bugs e aprimoramentos
Você pode corrigir um bug conhecido ou trabalhar em uma melhoria planejada. Veja [a lista de problemas](https://github.com/abpframework/abp/issues) no Github.
#### Solicitações de recursos
Se você tem uma ideia de recurso para a estrutura ou módulos, [crie um problema](https://github.com/abpframework/abp/issues/new) no Github ou participe de uma discussão existente. Então você pode implementá-lo se for adotado pela comunidade.
### Tradução de documentos
Você pode traduzir a [documentação](https://abp.io/documents/) completa (incluindo esta) para o idioma materno. Nesse caso, siga estas etapas:
- Clone o [repositório ABP](https://github.com/abpframework/abp/) do Github.
- Para adicionar um novo idioma, crie uma nova pasta dentro da pasta [docs](https://github.com/abpframework/abp/tree/master/docs) . Os nomes das pastas podem ser "en", "es", "fr", "tr" e assim por diante, com base no idioma (consulte [todos os códigos de cultura](https://msdn.microsoft.com/en-us/library/hh441729.aspx) ).
- Obtenha a [pasta "en"](https://github.com/abpframework/abp/tree/master/docs/en) como uma referência para os nomes de arquivos e a estrutura de pastas. Mantenha o mesmo nome se estiver traduzindo a mesma documentação.
- Envie uma solicitação de recebimento (PR) depois de traduzir qualquer documento. Traduza documentos e envie PRs um por um. Não espere para terminar as traduções de todos os documentos.
Alguns documentos fundamentais precisam ser traduzidos antes da publicação de um idioma no [site de documentação](https://docs.abp.io/) da [ABP](https://docs.abp.io/) :
- Documentos de introdução
- Tutoriais
- CLI
Um novo idioma é publicado após a conclusão dessas traduções mínimas.
### Localização de Recursos
A estrutura ABP possui um [sistema de localização](../Localization.md) flexível . Você pode criar interfaces de usuário localizadas para seu próprio aplicativo.
Além disso, os módulos de estrutura e pré-construção já localizaram textos. Como exemplo, veja [os textos de localização para o pacote Volo.Abp.UI](https://github.com/abpframework/abp/blob/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json) . Você pode criar um novo arquivo na [mesma pasta](https://github.com/abpframework/abp/tree/master/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi) para traduzi-lo.
- Clone o [repositório ABP](https://github.com/abpframework/abp/) do Github.
- Crie um novo arquivo para o idioma de destino para um arquivo de texto de localização (json) (próximo ao arquivo en.json).
- Copie todos os textos do arquivo en.json.
- Traduzir os textos.
- Enviar solicitação de recebimento no Github.
ABP é uma estrutura modular. Portanto, existem muitos recursos de texto de localização, um por módulo. Para encontrar todos os arquivos .json, você pode procurar por "en.json" após clonar o repositório. Você também pode verificar [esta lista](https://docs.abp.io/en/abp/latest/Contribution/Localization-Text-Files) para obter uma lista de arquivos de texto de localização.
### Posts e tutoriais do blog
Se você decidir criar alguns tutoriais ou postagens de blog no ABP, informe-nos (criando um [problema no Github](https://github.com/abpframework/abp/issues) ), para que possamos adicionar um link ao seu tutorial / publicação na documentação oficial e podemos anunciá-lo em nossa [conta do Twitter](https://twitter.com/abpframework) .
### Relatório de erro
Se você encontrar algum erro, [crie um problema no repositório do Github](https://github.com/abpframework/abp/issues/new) .

3
docs/pt-BR/CorrelationId.md

@ -0,0 +1,3 @@
# Correlation ID
Façam

3
docs/pt-BR/Data-Filtering.md

@ -0,0 +1,3 @@
# Data Filtering
Façam

3
docs/pt-BR/Data-Seeding.md

@ -0,0 +1,3 @@
# Data Seeding
Façam

3
docs/pt-BR/Data-Transfer-Objects.md

@ -0,0 +1,3 @@
## Data Transfer Objects
Façam

3
docs/pt-BR/Distributed-Event-Bus.md

@ -0,0 +1,3 @@
# Distributed Event Bus
Façam

3
docs/pt-BR/Domain-Services.md

@ -0,0 +1,3 @@
# ABP Documentation
Façam!

3
docs/pt-BR/Dynamic-Proxying-Interceptors.md

@ -0,0 +1,3 @@
## Dynamic Proxying / Interceptors
Façam

3
docs/pt-BR/Emailing.md

@ -0,0 +1,3 @@
# Emailing
Façam!

3
docs/pt-BR/Event-Bus.md

@ -0,0 +1,3 @@
# Event Bus
Façam

3
docs/pt-BR/Extension-Methods-And-Helpers.md

@ -0,0 +1,3 @@
# Extension Methods & Helpers
Façam

126
docs/pt-BR/Getting-Started-Angular-Template.md

@ -0,0 +1,126 @@
## Introdução ao modelo de aplicativo angular
Este tutorial explica como criar um novo aplicativo Angular usando o modelo de inicialização, configurar e executá-lo.
### Criando um novo projeto
Este tutorial usa o **ABP CLI** para criar um novo projeto. Consulte a página [Introdução](https://abp.io/get-started) para outras opções.
Instale a CLI ABP usando uma janela de linha de comando, se você não tiver instalado antes:
```bash
dotnet tool install -g Volo.Abp.Cli
```
Use o `abp new`comando em uma pasta vazia para criar seu projeto:
```bash
abp new Acme.BookStore -u angular
```
> Você pode usar diferentes níveis de namespaces; por exemplo, BookStore, Acme.BookStore ou Acme.Retail.BookStore.
`-u angular`A opção especifica que a estrutura da interface do usuário seja Angular. O provedor de banco de dados padrão é o EF Core. Consulte a [documentação](CLI.md) da [CLI](CLI.md) para todas as opções disponíveis.
#### Pré requisitos
A solução criada requer;
- [Visual Studio 2017 (v15.9.0 +)](https://visualstudio.microsoft.com/tr/downloads/)
- [.NET Core 2.2 ou superior](https://www.microsoft.com/net/download/dotnet-core/)
- [Node v10.16 +](https://nodejs.org/)
- [Yarn v1.17 +](https://yarnpkg.com/)
### A Estrutura da Solução
Abra a solução no **Visual Studio** :
![livraria-visual-studio-solução](images/bookstore-visual-studio-solution-for-spa.png)
A solução possui uma estrutura em camadas (baseada no [Domain Driven Design](Domain-Driven-Design.md) ) e contém projetos de teste de unidade e integração adequadamente configurados para trabalhar com o **banco de** dados de **memória** **EF Core** e **SQLite** .
> Consulte o [documento do modelo do aplicativo](Startup-Templates/Application.md) para entender a estrutura da solução em detalhes.
### Cadeia de Conexão de Banco de Dados
Verifique a **cadeia de conexão** no `appsettings.json`arquivo no `.HttpApi.Host`projeto:
```json
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=BookStore;Trusted_Connection=True"
}
}
```
A solução está configurada para usar o **Entity Framework Core** com o **MS SQL Server** . O EF Core suporta [vários](https://docs.microsoft.com/en-us/ef/core/providers/) provedores de banco de dados, para que você possa usar outro DBMS, se desejar. Mude a cadeia de conexão, se necessário.
### Criar banco de dados e aplicar migrações de banco de dados
Você tem duas opções para criar o banco de dados.
#### Usando o aplicativo DbMigrator
A solução contém um aplicativo de console (nomeado `Acme.BookStore.DbMigrator`nesta amostra) que pode criar banco de dados, aplicar migrações e propagar dados iniciais. É útil no desenvolvimento e no ambiente de produção.
> `.DbMigrator`projeto tem o seu próprio `appsettings.json`. Portanto, se você alterou a cadeia de conexão acima, também deve alterar esta.
Clique com o botão direito do mouse no `.DbMigrator`projeto e selecione **Definir como Projeto de Inicialização** :
![definir como projeto de inicialização](images/set-as-startup-project.png)
Pressione F5 (ou Ctrl + F5) para executar o aplicativo. Terá uma saída como mostrado abaixo:
![definir como projeto de inicialização](images/db-migrator-app.png)
#### Usando o comando EF Core Update-Database
O Ef Core possui um `Update-Database`comando que cria banco de dados, se necessário, e aplica migrações pendentes. Clique com o botão direito do mouse no `.Web`projeto e selecione **Definir como Projeto de Inicialização** :
![definir como projeto de inicialização](images/set-as-startup-project.png)
Abra o **Console do Gerenciador de Pacotes** , selecione o `.EntityFrameworkCore.DbMigrations`projeto como **Projeto Padrão** e execute o `Update-Database`comando:
![pcm-update-database](images/pcm-update-database-v2.png)
Isso criará um novo banco de dados com base na cadeia de conexão configurada.
> O uso da `.Migrator`ferramenta é a maneira sugerida, porque também semeia os dados iniciais para poder executar corretamente o aplicativo Web.
### Executando o aplicativo
#### Execute o host da API (lado do servidor)
Verifique se o `.HttpApi.Host`projeto é o projeto de inicialização e o aplicativo que abrirá uma interface do usuário do Swagger:
![livraria-homepage](images/bookstore-swagger-ui-host.png)
Você pode ver as APIs do aplicativo e testá-las aqui. Obtenha [mais informações](https://swagger.io/tools/swagger-ui/) sobre a interface do usuário do Swagger.
##### Autorização para a interface do usuário do Swagger
A maioria das APIs de aplicativos requer autenticação e autorização. Se você deseja testar APIs autorizadas, vá manualmente para a `/Account/Login`página, digite `admin`como o nome de usuário e `1q2w3E*`a senha para efetuar login no aplicativo. Você também poderá executar APIs autorizadas.
#### Execute o aplicativo angular (lado do cliente)
Vá para a `angular`pasta, abra um terminal de linha de comando, digite o `yarn`comando (sugerimos ao gerenciador de pacotes do [yarn](https://yarnpkg.com/) enquanto o npm install também funcionará na maioria dos casos):
```bash
yarn
```
Depois que todos os módulos do nó estiverem carregados, execute `yarn start`ou `npm start`comando:
```bash
yarn start
```
Abra seu navegador favorito e vá para `localhost:4200`URL. Nome de usuário inicial é `admin`e senha é `1q2w3E*`.
O modelo de inicialização inclui os módulos de **gerenciamento de** **identidade** e **gerenciamento de inquilino** . Após o login, o menu Administração estará disponível, onde você poderá gerenciar **inquilinos** , **funções** , **usuários** e suas **permissões** .
> Recomendamos o [Visual Studio Code](https://code.visualstudio.com/) como editor do projeto Angular, mas você pode usar seu editor favorito.
### Qual é o próximo?
- [Tutorial de desenvolvimento de aplicativos](Tutorials/Angular/Part-I.md)

183
docs/pt-BR/Getting-Started-AspNetCore-Application.md

@ -0,0 +1,183 @@
# Introdução ao ABP com o aplicativo Web MVC AspNet Core
Este tutorial explica como iniciar o ABP do zero com dependências mínimas. Você geralmente deseja começar com o **modelo de inicialização** .
## Criar um novo projeto
1. Crie um novo aplicativo da Web vazio do AspNet Core no Visual Studio:
![img](images/create-new-aspnet-core-application.png)
1. Selecionar modelo vazio
![img](images/select-empty-web-application.png)
Você pode selecionar outro modelo, mas quero mostrá-lo em um projeto claro.
## Instale o pacote Volo.Abp.AspNetCore.Mvc
Volo.Abp.AspNetCore.Mvc é um pacote de integração do AspNet Core MVC para ABP. Então, instale-o no seu projeto:
```
Install-Package Volo.Abp.AspNetCore.Mvc
```
## Criar o primeiro módulo ABP
O ABP é uma estrutura modular e requer uma classe de **módulo de inicialização (raiz)** derivada de `AbpModule`:
```csharp
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.AspNetCore.Modularity;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
namespace BasicAspNetCoreApplication
{
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
public class AppModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvcWithDefaultRoute();
}
}
}
```
`AppModule` é um bom nome para o módulo de inicialização de um aplicativo.
Os pacotes ABP definem as classes do módulo e um módulo pode depender de outro módulo. No código acima, nosso `AppModule`depende `AbpAspNetCoreMvcModule`(definido pelo pacote Volo.Abp.AspNetCore.Mvc). É comum adicionar um `DependsOn`atributo após a instalação de um novo pacote de nuget ABP.
Em vez da classe Startup, estamos configurando o pipeline do ASP.NET Core nesta classe de módulo.
## A classe de inicialização
O próximo passo é modificar a classe Startup para integrar ao sistema do módulo ABP:
```csharp
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace BasicAspNetCoreApplication
{
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddApplication<AppModule>();
return services.BuildServiceProviderFromFactory();
}
public void Configure(IApplicationBuilder app)
{
app.InitializeApplication();
}
}
}
```
`ConfigureServices`Método alterado para retornar em `IServiceProvider`vez de `void`. Essa alteração nos permite substituir a injeção de dependência do AspNet Core por outra estrutura (consulte a seção de integração com Autofac abaixo). `services.AddApplication<AppModule>()`adiciona todos os serviços definidos em todos os módulos a partir do `AppModule`.
`app.InitializeApplication()`O `Configure`método call in inicializa e inicia o aplicativo.
## Olá Mundo!
O aplicativo acima não faz nada. Vamos criar um controlador MVC que faz algo:
```csharp
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace BasicAspNetCoreApplication.Controllers
{
public class HomeController : AbpController
{
public IActionResult Index()
{
return Content("Hello World!");
}
}
}
```
Se você executar o aplicativo, verá um "Olá, mundo!" mensagem na página.
Derivado `HomeController`de em `AbpController`vez de `Controller`classe padrão . Isso não é necessário, mas a `AbpController`classe possui propriedades e métodos base úteis para facilitar seu desenvolvimento.
## Usando Autofac como a estrutura de injeção de dependência
Embora o sistema de Injeção de Dependência (DI) do AspNet Core seja adequado para requisitos básicos, o Autofac fornece recursos avançados, como Injeção de Propriedade e Interceptação de Método, exigidos pela ABP para executar recursos avançados da estrutura de aplicativos.
Substituir o sistema DI do AspNet Core pelo Autofac e integrar ao ABP é bastante fácil.
1. Instale o pacote [Volo.Abp.Autofac](https://www.nuget.org/packages/Volo.Abp.Autofac)
```
Install-Package Volo.Abp.Autofac
```
1. Adicionar `AbpAutofacModule`dependência
```csharp
[DependsOn(typeof(AbpAspNetCoreMvcModule))]
[DependsOn(typeof(AbpAutofacModule))] //Add dependency to ABP Autofac module
public class AppModule : AbpModule
{
...
}
```
1. Altere a `services.AddApplication<AppModule>();`linha na `Startup`classe, como mostrado abaixo:
```csharp
services.AddApplication<AppModule>(options =>
{
options.UseAutofac(); //Integrate to Autofac
});
```
1. Atualize `Program.cs`para não usar o `WebHost.CreateDefaultBuilder()`método, pois ele usa o contêiner DI padrão:
```csharp
public class Program
{
public static void Main(string[] args)
{
/*
https://github.com/aspnet/AspNetCore/issues/4206#issuecomment-445612167
CurrentDirectoryHelpers exists in: \framework\src\Volo.Abp.AspNetCore.Mvc\Microsoft\AspNetCore\InProcess\CurrentDirectoryHelpers.cs
Will remove CurrentDirectoryHelpers.cs when upgrade to ASP.NET Core 3.0.
*/
CurrentDirectoryHelpers.SetCurrentDirectory();
BuildWebHostInternal(args).Run();
}
public static IWebHost BuildWebHostInternal(string[] args) =>
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIIS()
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
```
## Código fonte
Obter código-fonte do projeto de exemplo criada neste tutorial a partir de [aqui](https://github.com/abpframework/abp/tree/master/samples/BasicAspNetCoreApplication) .

102
docs/pt-BR/Getting-Started-AspNetCore-MVC-Template.md

@ -0,0 +1,102 @@
## Introdução ao modelo ASP.NET Core MVC
Este tutorial explica como criar um novo aplicativo Web ASP.NET Core MVC usando o modelo de inicialização, configurá-lo e executá-lo.
### Criando um novo projeto
Este tutorial usa o **ABP CLI** para criar um novo projeto. Consulte a página [Introdução](https://abp.io/get-started) para outras opções.
Instale a CLI ABP usando uma janela de linha de comando, se você não tiver instalado antes:
```bash
dotnet tool install -g Volo.Abp.Cli
```
Use o `abp new`comando em uma pasta vazia para criar seu projeto:
```bash
abp new Acme.BookStore
```
> Você pode usar diferentes níveis de namespaces; por exemplo, BookStore, Acme.BookStore ou Acme.Retail.BookStore.
`new`O comando cria um **aplicativo MVC em camadas** com o **Entity Framework Core** como o provedor de banco de dados. No entanto, possui opções adicionais. Consulte a [documentação](CLI.md) da [CLI](CLI.md) para todas as opções disponíveis.
#### Pré requisitos
A solução criada requer;
- [Visual Studio 2017 (v15.9.0 +)](https://visualstudio.microsoft.com/tr/downloads/)
- [.NET Core 2.2 ou superior](https://www.microsoft.com/net/download/dotnet-core/)
### A Estrutura da Solução
Abra a solução no **Visual Studio** :
![livraria-visual-studio-solução](images/bookstore-visual-studio-solution-v3.png)
A solução possui uma estrutura em camadas (baseada no [Domain Driven Design](Domain-Driven-Design.md) ) e contém projetos de teste de unidade e integração adequadamente configurados para trabalhar com o **banco de** dados de **memória** **EF Core** e **SQLite** .
> Consulte o [documento do modelo de aplicativo](Startup-Templates/Application.md) para entender a estrutura da solução em detalhes.
### Cadeia de Conexão de Banco de Dados
Verifique a **cadeia de conexão** no `appsettings.json`arquivo no `.Web`projeto:
```json
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=BookStore;Trusted_Connection=True"
}
}
```
A solução está configurada para usar o **Entity Framework Core** com o **MS SQL Server** . O EF Core suporta [vários](https://docs.microsoft.com/en-us/ef/core/providers/) provedores de banco de dados, para que você possa usar outro DBMS, se desejar. Mude a cadeia de conexão, se necessário.
### Criar banco de dados e aplicar migrações de banco de dados
Você tem duas opções para criar o banco de dados.
#### Usando o aplicativo DbMigrator
A solução contém um aplicativo de console (nomeado `Acme.BookStore.DbMigrator`nesta amostra) que pode criar banco de dados, aplicar migrações e propagar dados iniciais. É útil no desenvolvimento e no ambiente de produção.
> `.DbMigrator`projeto tem o seu próprio `appsettings.json`. Portanto, se você alterou a cadeia de conexão acima, também deve alterar esta.
Clique com o botão direito do mouse no `.DbMigrator`projeto e selecione **Definir como Projeto de Inicialização** :
![definir como projeto de inicialização](images/set-as-startup-project.png)
Pressione F5 (ou Ctrl + F5) para executar o aplicativo. Terá uma saída como mostrado abaixo:
![definir como projeto de inicialização](images/db-migrator-app.png)
#### Usando o comando EF Core Update-Database
O Ef Core possui um `Update-Database`comando que cria banco de dados, se necessário, e aplica migrações pendentes. Clique com o botão direito do mouse no `.Web`projeto e selecione **Definir como Projeto de Inicialização** :
![definir como projeto de inicialização](images/set-as-startup-project.png)
Abra o **Console do Gerenciador de Pacotes** , selecione o `.EntityFrameworkCore.DbMigrations`projeto como **Projeto Padrão** e execute o `Update-Database`comando:
![pcm-update-database](images/pcm-update-database-v2.png)
Isso criará um novo banco de dados com base na cadeia de conexão configurada.
> O uso da `.Migrator`ferramenta é a maneira sugerida, porque também semeia os dados iniciais para poder executar corretamente o aplicativo Web.
### Executando o aplicativo
Verifique se o `.Web`projeto é o projeto de inicialização. Execute o aplicativo que abrirá a página **inicial** no seu navegador:
![livraria-homepage](images/bookstore-homepage.png)
Clique no botão **Login** , insira `admin`como nome de usuário e `1q2w3E*`senha para acessar o aplicativo.
O modelo de inicialização inclui os módulos de **gerenciamento de** **identidade** e **gerenciamento de inquilino** . Após o login, o menu Administração estará disponível, onde você poderá gerenciar **inquilinos** , **funções** , **usuários** e suas **permissões** . A página de gerenciamento de usuários é mostrada abaixo:
![livraria-gerenciamento de usuários](images/bookstore-user-management-v2.png)
### Qual é o próximo?
- [Tutorial de desenvolvimento de aplicativos](Tutorials/AspNetCore-Mvc/Part-I.md)

182
docs/pt-BR/Getting-Started-Console-Application.md

@ -0,0 +1,182 @@
# Introdução ao ABP com aplicativo de console
Este tutorial explica como iniciar o ABP do zero com dependências mínimas. Você geralmente deseja começar com um **modelo de inicialização** .
## Criar um novo projeto
Crie um novo aplicativo regular .Net Core Console do Visual Studio:
![img](images/create-new-net-core-console-application.png)
## Instale o pacote Volo.Abp
Volo.Abp.Core é o pacote principal de pepitas para criar aplicativos baseados em ABP. Então, instale-o no seu projeto:
```
Install-Package Volo.Abp.Core
```
## Criar o primeiro módulo ABP
O ABP é uma estrutura modular e requer uma classe de **módulo de inicialização (raiz)** derivada de `AbpModule`:
```csharp
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace AbpConsoleDemo
{
public class AppModule : AbpModule
{
}
}
```
`AppModule` é um bom nome para o módulo de inicialização de um aplicativo.
## Inicializar o aplicativo
A próxima etapa é inicializar o aplicativo usando o módulo de inicialização criado acima:
```csharp
using System;
using Volo.Abp;
namespace AbpConsoleDemo
{
class Program
{
static void Main(string[] args)
{
using (var application = AbpApplicationFactory.Create<AppModule>())
{
application.Initialize();
Console.WriteLine("Press ENTER to stop application...");
Console.ReadLine();
}
}
}
}
```
`AbpApplicationFactory`é usado para criar o aplicativo e carregar todos os módulos que tomam `AppModule`como módulo de inicialização. `Initialize()`O método inicia o aplicativo.
## Olá Mundo!
O aplicativo acima não faz nada. Vamos criar um serviço que faça algo:
```csharp
using System;
using Volo.Abp.DependencyInjection;
namespace AbpConsoleDemo
{
public class HelloWorldService : ITransientDependency
{
public void SayHello()
{
Console.WriteLine("Hello World!");
}
}
}
```
`ITransientDependency`é uma interface especial do ABP que registra automaticamente o serviço como transitório (consulte o [documento de injeção de dependência](Dependency-Injection.md) ).
Agora, podemos resolver o problema `HelloWorldService`e dizer olá. Altere o Program.cs como mostrado abaixo:
```csharp
using System;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
namespace AbpConsoleDemo
{
class Program
{
static void Main(string[] args)
{
using (var application = AbpApplicationFactory.Create<AppModule>())
{
application.Initialize();
//Resolve a service and use it
var helloWorldService =
application.ServiceProvider.GetService<HelloWorldService>();
helloWorldService.SayHello();
Console.WriteLine("Press ENTER to stop application...");
Console.ReadLine();
}
}
}
}
```
Embora seja suficiente para este exemplo de código simples, é sempre recomendável criar escopos no caso de resolver diretamente dependências de `IServiceProvider`(consulte a [documentação de Injeção de Dependências](Dependency-Injection.md)).
## Usando Autofac como a estrutura de injeção de dependência
Embora o sistema de Injeção de Dependência (DI) do AspNet Core seja adequado para requisitos básicos, o Autofac fornece recursos avançados, como Injeção de Propriedade e Interceptação de Método, exigidos pela ABP para executar recursos avançados da estrutura de aplicativos.
Substituir o sistema DI do AspNet Core pelo Autofac e integrar ao ABP é bastante fácil.
1. Instale o pacote [Volo.Abp.Autofac](https://www.nuget.org/packages/Volo.Abp.Autofac)
```
Install-Package Volo.Abp.Autofac
```
1. Adicionar `AbpAutofacModule`dependência
```csharp
[DependsOn(typeof(AbpAutofacModule))] //Add dependency to the AbpAutofacModule
public class AppModule : AbpModule
{
}
```
1. Mude o `Program.cs`arquivo como mostrado abaixo:
```csharp
using System;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
namespace AbpConsoleDemo
{
class Program
{
static void Main(string[] args)
{
using (var application = AbpApplicationFactory.Create<AppModule>(options =>
{
options.UseAutofac(); //Autofac integration
}))
{
application.Initialize();
//Resolve a service and use it
var helloWorldService =
application.ServiceProvider.GetService<HelloWorldService>();
helloWorldService.SayHello();
Console.WriteLine("Press ENTER to stop application...");
Console.ReadLine();
}
}
}
}
```
Apenas chamado `options.UseAutofac()`método nas `AbpApplicationFactory.Create`opções.
## Código fonte
Obter código-fonte do projeto de exemplo criada neste tutorial a partir de [aqui](https://github.com/abpframework/abp/tree/master/samples/BasicConsoleApplication) .

3
docs/pt-BR/Guid-Generation.md

@ -0,0 +1,3 @@
## Guid Generation
Façam

31
docs/pt-BR/Index.md

@ -0,0 +1,31 @@
# Documentação ABP
O ABP é um **framework de aplicativos de código aberto** focada no desenvolvimento de aplicativos da Web baseado no ASP.NET Core, mas também suporta o desenvolvimento de outros tipos de aplicativos.
Explore o menu de navegação esquerdo para mergulhar fundo na documentação.
## Status do projeto
ABP é a **próxima geração** de framework de código aberto [ASP.NET Boilerplate](https://aspnetboilerplate.com/). Atualmente, está em fase de pré-visualização e não está pronto para uso na produção. A documentação ainda está em andamento e está longe de estar completa.
Para aplicativos de curto prazo e em nível de produção, é sugerido o uso da estrutura do [ASP.NET Boilerplate](https://aspnetboilerplate.com/) , que possui um rico conjunto de recursos, maduro, mantido ativamente e atualizado.
## Começando
A maneira mais fácil de iniciar um novo projeto com o ABP é usar os modelos de inicialização:
- [Modelo de interface do usuário do ASP.NET Core MVC (Razor Pages)](Getting-Started-AspNetCore-MVC-Template.md)
- [Modelo de interface do usuário angular](Getting-Started-Angular-Template.md)
Se você deseja começar do zero (com um projeto vazio), instale manualmente o ABP Framework e use os seguintes tutoriais:
- [Aplicação de console](Getting-Started-Console-Application.md)
- [Aplicativo da Web principal do ASP.NET](Getting-Started-AspNetCore-Application.md)
## Código fonte
ABP está hospedado no GitHub. Veja [o código fonte](https://github.com/abpframework/abp) .
## Deseja contribuir?
O ABP é um projeto de código aberto orientado pela comunidade. Consulte [o guia de contribuição](Contribution/Index.md) se você quiser fazer parte deste projeto.

3
docs/pt-BR/Integration-Tests.md

@ -0,0 +1,3 @@
# Integration Tests
Façam!

3
docs/pt-BR/Local-Event-Bus.md

@ -0,0 +1,3 @@
# Local Event Bus
Façam

195
docs/pt-BR/Localization.md

@ -0,0 +1,195 @@
# Localização
O sistema de localização da ABP é perfeitamente integrado ao `Microsoft.Extensions.Localization`pacote e compatível com a [documentação de localização da Microsoft](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization) . Ele adiciona alguns recursos e aprimoramentos úteis para facilitar o uso em cenários de aplicativos da vida real.
## Pacote Volo.Abp.Localization
> Este pacote já está instalado por padrão com o modelo de inicialização. Portanto, na maioria das vezes, você não precisa instalá-lo manualmente.
Volo.Abp.Localization é o pacote principal do sistema de localização. Instale-o no seu projeto usando o console do gerenciador de pacotes (PMC):
```
Install-Package Volo.Abp.Localization
```
Em seguida, você pode adicionar a dependência **AbpLocalizationModule** ao seu módulo:
```csharp
using Volo.Abp.Modularity;
using Volo.Abp.Localization;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpLocalizationModule))]
public class MyModule : AbpModule
{
//...
}
}
```
## Criando um recurso de localização
Um recurso de localização é usado para agrupar cadeias de localização relacionadas e separá-las de outras cadeias de localização do aplicativo. Um [módulo](Module-Development-Basics.md) geralmente define seu próprio recurso de localização. O recurso de localização é apenas uma classe simples. Exemplo:
```csharp
public class TestResource
{
}
```
Em seguida, deve ser adicionado usando `AbpLocalizationOptions`como mostrado abaixo:
```csharp
[DependsOn(typeof(AbpLocalizationModule))]
public class MyModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<MyModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
//Define a new localization resource (TestResource)
options.Resources
.Add<TestResource>("en")
.AddVirtualJson("/Localization/Resources/Test");
});
}
}
```
Neste exemplo;
- Adicionado um novo recurso de localização com "en" (inglês) como a cultura padrão.
- Arquivos JSON usados para armazenar as sequências de localização.
- Os arquivos JSON são incorporados ao assembly usando `VirtualFileSystemOptions`(consulte [sistema de arquivos virtual](Virtual-File-System.md) ).
Os arquivos JSON estão localizados na pasta do projeto "/ Localização / Recursos / Teste", como mostrado abaixo:
![localization-resource-json-files](images/localization-resource-json-files.png)
Um conteúdo do arquivo de localização JSON é mostrado abaixo:
```json
{
"culture": "en",
"texts": {
"HelloWorld": "Hello World!"
}
}
```
- Todo arquivo de localização deve definir o `culture`código para o arquivo (como "en" ou "en-US").
- `texts` A seção contém apenas a coleção de valores-chave das sequências de localização (as chaves também podem ter espaços).
### Nome Curto do Recurso de Localização
Os recursos de localização também estão disponíveis no lado do cliente (JavaScript). Portanto, definir um nome abreviado para o recurso de localização facilita o uso de textos de localização. Exemplo:
```csharp
[LocalizationResourceName("Test")]
public class TestResource
{
}
```
Consulte a seção Obtendo teste localizado / lado do cliente abaixo.
### Herdar de outros recursos
Um recurso pode herdar de outros recursos, o que possibilita reutilizar cadeias de localização existentes sem fazer referência ao recurso existente. Exemplo:
```csharp
[InheritResource(typeof(AbpValidationResource))]
public class TestResource
{
}
```
Herança alternativa configurando o `AbpLocalizationOptions`:
```csharp
services.Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<TestResource>("en") //Define the resource by "en" default culture
.AddVirtualJson("/Localization/Resources/Test") //Add strings from virtual json files
.AddBaseTypes(typeof(AbpValidationResource)); //Inherit from an existing resource
});
```
- Um recurso pode herdar de vários recursos.
- Se o novo recurso definir a mesma sequência localizada, ele substituirá a sequência.
### Estendendo o Recurso Existente
Herdar de um recurso cria um novo recurso sem modificar o existente. Em alguns casos, convém não criar um novo recurso, mas estender diretamente um recurso existente. Exemplo:
```csharp
services.Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<TestResource>()
.AddVirtualJson("/Localization/Resources/Test/Extensions");
});
```
- Se um arquivo de extensão define a mesma sequência localizada, ele substitui a sequência.
## Obtendo textos localizados
### Lado do servidor
Obter o texto localizado no lado do servidor é bastante padrão.
#### Uso mais simples de uma classe
```csharp
public class MyService
{
private readonly IStringLocalizer<TestResource> _localizer;
public MyService(IStringLocalizer<TestResource> localizer)
{
_localizer = localizer;
}
public void Foo()
{
var str = _localizer["HelloWorld"];
}
}
```
#### Uso mais simples em uma vista / página do Razor
```csharp
@inject IHtmlLocalizer<TestResource> Localizer
<h1>@Localizer["HelloWorld"]</h1>
```
Consulte a [documentação de localização da Microsoft](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization) para obter detalhes sobre o uso da localização no lado do servidor.
### Lado do Cliente
A ABP fornece serviços JavaScript para usar os mesmos textos localizados no lado do cliente.
Obtenha um recurso de localização:
```js
var testResource = abp.localization.getResource('Test');
```
Localize uma sequência:
```js
var str = testResource('HelloWorld');
```

27
docs/pt-BR/Nightly-Builds.md

@ -0,0 +1,27 @@
# Compilações Noturnas
Todos os pacotes de estrutura e módulo são implantados no MyGet todas as noites durante a semana. Portanto, você pode usar ou testar o código mais recente sem aguardar o próximo lançamento.
## Configurar o Visual Studio
> Requer Visual Studio 2017 ou superior
1. Vá para `Tools > Options > NuGet Package Manager > Package Source`.
2. Clique no `+` ícone verde .
3. Defina `ABP Nightly`como *Nome* e `https://www.myget.org/F/abp-nightly/api/v3/index.json`como a *Fonte,* como mostrado abaixo: ![noite-compilação-adicionar-pepita-fonte](images/night-build-add-nuget-source.png)
4. Clique no `Update` botão
5. Clique no `OK` botão para salvar as alterações.
## Instalar pacote
Agora, você pode instalar pacotes noturnos / de visualização no seu projeto a partir do Nuget Browser ou do Package Manager Console.
![night-build-add-nuget-package](images/night-build-add-nuget-package.png)
1. No Nuget Browser, selecione "Incluir pré-lançamentos".
2. Altere a fonte do pacote para "Todos".
3. Pesquise um pacote. Você verá as pré *-liberações* do pacote formatadas como `(VERSION)-preview(DATE)`(como *v0.16.0-preview20190401* neste exemplo).
4. Você pode clicar no `Install`botão para adicionar um pacote ao seu projeto.

3
docs/pt-BR/Object-To-Object-Mapping.md

@ -0,0 +1,3 @@
## Object To Object Mapping
Façam

3
docs/pt-BR/SMS-Sending.md

@ -0,0 +1,3 @@
# Emailing
Façam!

3
docs/pt-BR/Settings.md

@ -0,0 +1,3 @@
# Settings
Façam!

3
docs/pt-BR/Specifications.md

@ -0,0 +1,3 @@
# Specifications
Façam!

275
docs/pt-BR/Startup-Templates/Application.md

@ -0,0 +1,275 @@
# Modelo de inicialização do aplicativo
## Introdução
Este modelo fornece uma estrutura de aplicativo em camadas com base nas práticas DDD ([Domain Driven Design](../Domain-Driven-Design.md)). Este documento explica a estrutura da solução e os projetos em detalhes. Se você deseja iniciar rapidamente, siga os guias abaixo:
- Consulte [Introdução ao modelo do ASP.NET Core MVC](../Getting-Started-AspNetCore-MVC-Template.md) para criar uma nova solução e executá-la para este modelo (usa o MVC como a estrutura da interface do usuário e o Entity Framework Core como o provedor de banco de dados).
- Consulte o [Tutorial de desenvolvimento de aplicativos do ASP.NET Core MVC](../Tutorials/AspNetCore-Mvc/Part-I.md) para aprender como desenvolver aplicativos usando este modelo (usa o MVC como a estrutura da interface do usuário e o Entity Framework Core como o provedor de banco de dados).
- Consulte o [Tutorial de desenvolvimento de aplicativos Angular](../Tutorials/Angular/Part-I.md) para aprender como desenvolver aplicativos usando este modelo (usa Angular como a estrutura da interface do usuário e MongoDB como o provedor de banco de dados).
## Como começar?
Você pode usar a [ABP CLI](../CLI.md) para criar um novo projeto usando este modelo de inicialização. Como alternativa, você pode criar e fazer o download diretamente na página [Introdução](https://abp.io/get-started) . A abordagem CLI é usada aqui.
Primeiro, instale a ABP CLI se você não tiver instalado antes:
```bash
dotnet tool install -g Volo.Abp.Cli
```
Em seguida, use o `abp new`comando em uma pasta vazia para criar uma nova solução:
```bash
abp new Acme.BookStore -t app
```
- `Acme.BookStore`é o nome da solução, como *YourCompany.YourProduct* . Você pode usar nomes de nível único, dois ou três níveis.
- Este exemplo especificou o nome do modelo ( `-t`ou `--template`opção). No entanto, `app`já é o modelo padrão se você não o especificar.
### Especifique a estrutura da interface do usuário
Este modelo fornece várias estruturas de interface do usuário:
- `mvc`: Interface do usuário do ASP.NET Core MVC com Razor Pages (padrão)
- `angular`: UI angular
Use `-u`ou `--ui`opção para especificar a estrutura da interface do usuário:
```bash
abp new Acme.BookStore -u angular
```
### Especifique o provedor de banco de dados
Este modelo suporta os seguintes provedores de banco de dados:
- `ef`: Entity Framework Core (padrão)
- `mongodb`: MongoDB
Use a opção `-d`(ou `--database-provider`) para especificar o provedor de banco de dados:
```bash
abp new Acme.BookStore -d mongodb
```
## Estrutura da solução
Com base nas opções especificadas, você obterá uma estrutura de solução ligeiramente diferente.
### Estrutura padrão
Se você não especificar nenhuma opção adicional, terá uma solução como a mostrada abaixo:
![livraria-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-v3.png)
Os projetos são organizados em `src`e `test`pastas. `src`A pasta contém o aplicativo real que está em camadas com base nos princípios [DDD](https://docs.abp.io/en/abp/latest/Domain-Driven-Design) , como mencionado anteriormente.
O diagrama abaixo mostra as camadas e dependências do projeto do aplicativo:
![dependências de projeto em camadas](../images/layered-project-dependencies.png)
Cada seção abaixo explicará o projeto relacionado e suas dependências.
#### Projeto .Domain.Shared
Este projeto contém constantes, enumerações e outros objetos. Na verdade, eles fazem parte da camada de domínio, mas precisam ser usados por todas as camadas / projetos da solução.
Um `BookType`enum e uma `BookConsts`classe (que podem ter alguns campos constantes para a `Book`entidade, como `MaxNameLength`) são bons candidatos para este projeto.
- Este projeto não depende de outros projetos na solução. Todos os outros projetos dependem disso direta ou indiretamente.
#### .Domain Project
Essa é a camada de domínio da solução. Ele contém principalmente [entidades, raízes agregadas](../Entities.md) , [serviços de domínio](../Domain-Services.md) , [tipos de valor](../Value-Types.md) , [interfaces de repositório](../Repositories) e outros objetos de domínio.
Uma `Book`entidade, um `BookManager`serviço de domínio e uma `IBookRepository`interface são bons candidatos para este projeto.
- Depende do `.Domain.Shared`porque usa constantes, enumerações e outros objetos definidos nesse projeto.
#### .Application.Contracts Project
Este projeto contém principalmente **interfaces de** [serviço de aplicativo](../Application-Services.md) e DTO ( [Data Transfer Objects](../Data-Transfer-Objects.md) ) da camada de aplicativo. Existe para separar a interface e a implementação da camada de aplicação. Dessa forma, o projeto de interface pode ser compartilhado com os clientes como um pacote de contrato.
Uma `IBookAppService`interface e uma `BookCreationDto`classe são boas candidatas para este projeto.
- Depende do `.Domain.Shared`porque ele pode usar constantes, enumerações e outros objetos compartilhados deste projeto nas interfaces de serviço de aplicativo e DTOs.
#### Projeto de Aplicação
Este projeto contém as **implementações** de [serviço de aplicativo](../Application-Services.md) das interfaces definidas no projeto.`.Application.Contracts`
Uma `BookAppService`turma é uma boa candidata para este projeto.
- Depende do `.Application.Contracts`projeto para poder implementar as interfaces e usar os DTOs.
- Depende do `.Domain`projeto para poder usar objetos de domínio (entidades, interfaces de repositório ... etc.) para executar a lógica do aplicativo.
#### Projeto .EntityFrameworkCore
Este é o projeto de integração para o EF Core. Ele define `DbContext`e implementa as interfaces de repositório definidas no `.Domain`projeto.
- Depende do `.Domain`projeto para poder fazer referência a entidades e interfaces de repositório.
> Este projeto está disponível apenas se você estiver usando o EF Core como provedor de banco de dados. Se você selecionar outro provedor de banco de dados, seu nome será diferente.
#### Projeto .EntityFrameworkCore.DbMigrations
Contém migrações de banco de dados EF Core para a solução. Ele foi separado `DbContext`para dedicado a gerenciar migrações.
ABP é uma estrutura modular e com um design ideal, cada módulo tem sua própria `DbContext`classe. É aqui que a migração `DbContext`entra em ação e unifica todas as `DbContext`configurações em um único modelo para manter um único esquema de banco de dados. Para cenários mais avançados, você pode ter vários bancos de dados (cada um contém uma única ou algumas tabelas de módulos) e várias migrações `DbContext`(cada uma mantém um esquema de banco de dados diferente).
Observe que a migração `DbContext`é usada apenas para migrações de banco de dados e *não em tempo de execução* .
- Depende do `.EntityFrameworkCore`projeto, pois reutiliza a configuração definida para `DbContext`o aplicativo.
> Este projeto está disponível apenas se você estiver usando o EF Core como provedor de banco de dados.
#### Projeto .DbMigrator
Este é um aplicativo de console que simplifica a execução de migrações de banco de dados em ambientes de desenvolvimento e produção. Quando você executa este aplicativo, ele;
- Cria o banco de dados, se necessário.
- Aplica as migrações de banco de dados pendentes.
- Semeia os dados iniciais, se necessário.
> Este projeto possui seu próprio `appsettings.json`arquivo. Portanto, se você deseja alterar a cadeia de conexão do banco de dados, lembre-se de alterar também esse arquivo.
Especialmente, semear dados iniciais é importante neste momento. A ABP possui uma infraestrutura modular de semente de dados. Consulte [a documentação](../Data-Seeding.md) para obter mais informações sobre a propagação de dados.
Embora a criação de banco de dados e a aplicação de migrações pareça necessária apenas para bancos de dados relacionais, esse projeto ocorre mesmo que você escolha um provedor de banco de dados NoSQL (como o MongoDB). Nesse caso, ele ainda semeia os dados iniciais necessários para a aplicação.
- Depende do `.EntityFrameworkCore.DbMigrations`projeto (para EF Core), pois ele precisa acessar as migrações.
- Depende do `.Application.Contracts`projeto para poder acessar as definições de permissão, porque o semeador de dados inicial concede todas as permissões para a função de administrador por padrão.
#### Projeto .HttpApi
Este projeto é usado para definir seus controladores de API.
Na maioria das vezes, você não precisa definir manualmente os controladores de API, pois o recurso de [controladores de API automática](../AspNetCore/Auto-API-Controllers.md) da ABP os cria automaticamente, com base na sua camada de aplicação. No entanto, no caso de você precisar escrever controladores de API, este é o melhor lugar para fazê-lo.
- Depende do `.Application.Contracts`projeto para poder injetar as interfaces de serviço do aplicativo.
#### Projeto .HttpApi.Client
Este é um projeto que define os proxies do cliente C # para usar as APIs HTTP da solução. Você pode compartilhar essa biblioteca com clientes de terceiros, para que eles consumam facilmente suas APIs HTTP em seus aplicativos Dotnet (para outros tipos de aplicativos, eles ainda podem usar suas APIs, manualmente ou usando uma ferramenta em sua própria plataforma)
Na maioria das vezes, você não precisa criar proxies de clientes C # manualmente, graças ao recurso [Dynamic C # API Clients](../AspNetCore/Dynamic-CSharp-API-Clients.md) da ABP .
`.HttpApi.Client.ConsoleTestApp` project é um aplicativo de console criado para demonstrar o uso dos proxies do cliente.
- Depende do `.Application.Contracts`projeto para poder compartilhar as mesmas interfaces de serviço de aplicativo e DTOs com o serviço remoto.
> Você pode excluir este projeto e dependências se não precisar criar proxies de cliente C # para suas APIs.
#### Projeto .Web
Este projeto contém a interface do usuário (UI) do aplicativo se você estiver usando a interface do usuário do ASP.NET Core MVC. Ele contém páginas Razor, arquivos JavaScript, arquivos CSS, imagens e assim por diante ...
Este projeto contém o `appsettings.json`arquivo principal que contém a cadeia de conexão e outras configurações do aplicativo.
- Depende da `.HttpApi`camada de interface do usuário que precisa usar APIs e interfaces de serviço de aplicativo da solução.
> Se você verificar o código fonte do `.Web.csproj`arquivo, verá as referências aos `.Application`e aos `.EntityFrameworkCore.DbMigrations`projetos.
>
> Na verdade, essas referências não são necessárias durante a codificação da camada da interface do usuário, porque a camada da interface do usuário normalmente não depende da implementação do EF Core ou da camada do Aplicativo. Esses modelos de inicialização estão prontos para a implantação em camadas, em que a camada da API está hospedada em um servidor separado da camada da interface do usuário.
>
> No entanto, se você não escolher a opção `--tiered`, essas referências estarão no projeto .Web para poder hospedar as camadas da Web, API e aplicativos em um único ponto de extremidade do aplicativo.
>
> Isso permite que você use entidades e repositórios de domínio em sua camada de apresentação. No entanto, isso é considerado uma má prática de acordo com o DDD.
#### Projetos de teste
A solução possui vários projetos de teste, um para cada camada:
- `.Domain.Tests` é usado para testar a camada de domínio.
- `.Application.Tests` é usado para testar a camada de aplicativo.
- `.EntityFrameworkCore.Tests` é usado para testar a configuração do EF Core e os repositórios personalizados.
- `.Web.Tests` é usado para testar a interface do usuário (se você estiver usando a interface do ASP.NET Core MVC).
- `.TestBase` é um projeto básico (compartilhado) para todos os testes.
Além disso, `.HttpApi.Client.ConsoleTestApp`é um aplicativo de console (não um projeto de teste automatizado) que demonstra o uso de APIs HTTP de um aplicativo .NET.
Projetos de teste são preparados para testes de integração;
- É totalmente integrado à estrutura ABP e a todos os serviços em sua aplicação.
- Ele usa o banco de dados SQLite na memória para o EF Core. Para o MongoDB, ele usa a biblioteca [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) .
- A autorização está desabilitada, portanto, qualquer serviço de aplicativo pode ser facilmente usado em testes.
Você ainda pode criar testes de unidade para suas classes, que serão mais difíceis de escrever (porque você precisará preparar objetos simulados / falsos), mas mais rápidos de executar (porque apenas testa uma única classe e ignora todo o processo de inicialização).
#### Como correr?
Defina `.Web`como o projeto de inicialização e execute o aplicativo. O nome de usuário padrão é `admin`e a senha é `1q2w3E*`.
Consulte [Introdução ao modelo ASP.NET Core MVC](../Getting-Started-AspNetCore-MVC-Template.md) para obter mais informações.
### Estrutura em camadas
Se você selecionou a interface do usuário do ASP.NET Core e especificou a `--tiered`opção, a solução criada será uma solução em camadas. O objetivo da estrutura em camadas é poder **implantar aplicativos da Web e API HTTP em diferentes servidores** :
![livraria-visual-studio-solution-v3](../images/tiered-solution-servers.png)
- O navegador executa sua interface do usuário executando HTML, CSS e JavaScript.
- Os servidores da Web hospedam arquivos de interface do usuário estáticos (CSS, JavaScript, imagem ... etc.) e componentes dinâmicos (por exemplo, páginas Razor). Ele executa solicitações HTTP para o servidor da API para executar a lógica de negócios do aplicativo.
- O API Server hospeda as APIs HTTP que, em seguida, usam as camadas de aplicativo e domínio do aplicativo para executar a lógica de negócios.
- Finalmente, o servidor de banco de dados hospeda seu banco de dados.
Portanto, a solução resultante permite uma implantação em quatro camadas, comparando com a implantação em três camadas da estrutura padrão explicada anteriormente.
> A menos que você realmente precise de uma implantação em quatro camadas, é recomendável seguir a estrutura padrão que é mais simples de desenvolver, implantar e manter.
A estrutura da solução é mostrada abaixo:
![livraria-visual-studio-solution-v3](../images/bookstore-visual-studio-solution-tiered.png)
Diferente da estrutura padrão, dois novos projetos entram em jogo: `.IdentityServer`& `.HttpApi.Host`.
#### Projeto .IdentityServer
Este projeto é usado como um servidor de autenticação para outros projetos. `.Web`O projeto usa a autenticação do OpenId Connect para obter tokens de identidade e acesso para o usuário atual do IdentityServer. Em seguida, usa o token de acesso para chamar o servidor da API HTTP. O servidor HTTP API usa autenticação de token de portador para obter declarações do token de acesso para autorizar o usuário atual.
![aplicativos de solução em camadas](../images/tiered-solution-applications.png)
O ABP usa a estrutura [IdentityServer4 de](https://identityserver.io/) código aberto para a autenticação entre aplicativos. Consulte a [documentação do IdentityServer4](http://docs.identityserver.io/) para obter detalhes sobre o protocolo IdentityServer4 e OpenID Connect.
Ele possui seu próprio `appsettings.json`que contém conexão com o banco de dados e outras configurações.
#### Projeto .HttpApi.Host
Este projeto é um aplicativo que hospeda a API da solução. Ele possui seu próprio `appsettings.json`que contém conexão com o banco de dados e outras configurações.
#### Projeto .Web
Assim como a estrutura padrão, este projeto contém a interface do usuário (UI) do aplicativo. Ele contém páginas de barbear, arquivos JavaScript, arquivos de estilo, imagens e assim por diante ...
Este projeto contém um `appsettings.json`arquivo, mas desta vez não possui uma cadeia de conexão porque nunca se conecta ao banco de dados. Em vez disso, ele contém principalmente o terminal do servidor de API remoto e o servidor de autenticação.
#### Pré requisitos
- [Redis](https://redis.io/) : os aplicativos usam Redis como cache distribuído. Então, você precisa ter o Redis instalado e funcionando.
#### Como correr?
Você deve executar o aplicativo com a ordem especificada:
- Primeiro, execute o `.IdentityServer`aplicativo, pois outros aplicativos dependem dele.
- Em seguida, execute o `.HttpApi.Host`que é usado pelo `.Web`aplicativo.
- Por fim, você pode executar o `.Web`projeto e efetuar login no aplicativo (usando `admin`como nome de usuário e `1q2w3E*`senha).
### UI angular
Se você escolher Angular como a estrutura da interface do usuário (usando a `-u angular`opção), a solução será separada em duas pastas:
- `angular` A pasta contém a solução Angular UI, do lado do cliente.
- `aspnet-core` A pasta contém a solução ASP.NET Core, do lado do servidor.
O lado do servidor é muito semelhante à solução descrita acima. `.HttpApi.Host`projeto serve a API, para que o aplicativo Angular possa consumi-lo.
Os arquivos na `angular/src/environments`pasta têm a configuração essencial do aplicativo.
## Qual é o próximo?
- Consulte [Introdução ao modelo ASP.NET Core MVC](../Getting-Started-AspNetCore-MVC-Template.md) para criar uma nova solução e executá-la para este modelo.
- Consulte o [Tutorial](../Tutorials/AspNetCore-Mvc/Part-I.md) do [ASP.NET Core MVC](../Tutorials/AspNetCore-Mvc/Part-I.md) para aprender como desenvolver aplicativos usando este modelo.

7
docs/pt-BR/Startup-Templates/Index.md

@ -0,0 +1,7 @@
# Modelos de inicialização
Embora você possa começar com um projeto vazio e adicionar os pacotes necessários manualmente, os modelos de inicialização facilitam e são confortáveis para iniciar uma nova solução com a estrutura ABP. Clique no nome da lista abaixo para ver a documentação do modelo de inicialização relacionado:
- [**app**](Application.md) : modelo de aplicativo.
- [**módulo**](Module.md) : Módulo / modelo de serviço.

161
docs/pt-BR/Startup-Templates/Module.md

@ -0,0 +1,161 @@
# Modelo de inicialização do módulo MVC
Este modelo pode ser usado para criar um **módulo de aplicativo** **reutilizável com** base nas [melhores práticas e convenções de desenvolvimento do módulo](../Best-Practices/Index.md). Também é adequado para criar **microsserviços** (com ou sem interface do usuário).
## Como começar?
Você pode usar a [ABP CLI](../CLI.md) para criar um novo projeto usando este modelo de inicialização. Como alternativa, você pode criar e fazer o download diretamente na página [Introdução](https://abp.io/get-started) . A abordagem CLI é usada aqui.
Primeiro, instale a ABP CLI se você não tiver instalado antes:
```bash
dotnet tool install -g Volo.Abp.Cli
```
Em seguida, use o `abp new`comando em uma pasta vazia para criar uma nova solução:
```bash
abp new Acme.IssueManagement -t module
```
- `Acme.IssueManagement`é o nome da solução, como *YourCompany.YourProduct* . Você pode usar nomes de nível único, dois ou três níveis.
### Sem interface de usuário
O modelo vem com uma interface do usuário do MVC por padrão. Você pode usar a `--no-ui`opção para não incluir a camada da interface do usuário.
```bash
abp new Acme.IssueManagement -t mvc-module --no-ui
```
## Estrutura da solução
Com base nas opções especificadas, você obterá uma estrutura de solução ligeiramente diferente. Se você não especificar nenhuma opção, terá uma solução como a mostrada abaixo:
![issuemanagement-module-solution](../images/issuemanagement-module-solution.png)
Projetos são organizados como `src`, `test`e `host`pastas:
- `src`A pasta contém o módulo real, que é estratificado com base nos princípios [DDD](../Domain-Driven-Design.md) .
- `test` pasta contém testes de unidade e integração.
- `host`A pasta contém aplicativos com configurações diferentes para demonstrar como hospedar o módulo em um aplicativo. Isso não faz parte do módulo, mas é útil no desenvolvimento.
O diagrama abaixo mostra as camadas e dependências do projeto do módulo:
![módulo de dependências do projeto em camadas](../images/layered-project-dependencies-module.png)
Cada seção abaixo explicará o projeto relacionado e suas dependências.
### Projeto .Domain.Shared
Este projeto contém constantes, enumerações e outros objetos. Na verdade, eles fazem parte da camada de domínio, mas precisam ser usados por todas as camadas / projetos da solução.
Um `IssueType`enum e uma `IssueConsts`classe (que podem ter alguns campos constantes para a `Issue`entidade, como `MaxTitleLength`) são bons candidatos para este projeto.
- Este projeto não depende de outros projetos na solução. Todos os outros projetos dependem disso direta ou indiretamente.
### .Domain Project
Essa é a camada de domínio da solução. Ele contém principalmente [entidades, raízes agregadas](../Entities.md) , [serviços de domínio](../Domain-Services.md) , [tipos de valor](../Value-Types.md) , [interfaces de repositório](../Repositories.md) e outros objetos de domínio.
Uma `Issue`entidade, um `IssueManager`serviço de domínio e uma `IIssueRepository`interface são bons candidatos para este projeto.
- Depende do `.Domain.Shared`porque usa constantes, enumerações e outros objetos definidos nesse projeto.
### .Application.Contracts Project
Este projeto contém principalmente **interfaces de** [serviço de aplicativo](../Application-Services.md) e DTO ( [Data Transfer Objects](../Data-Transfer-Objects.md) ) da camada de aplicativo. Existe para separar a interface e a implementação da camada de aplicação. Dessa forma, o projeto de interface pode ser compartilhado com os clientes como um pacote de contrato.
Uma `IIssueAppService`interface e uma `IssueCreationDto`classe são boas candidatas para este projeto.
- Depende do `.Domain.Shared`porque ele pode usar constantes, enumerações e outros objetos compartilhados deste projeto nas interfaces de serviço de aplicativo e DTOs.
### Projeto de Aplicação
Este projeto contém as **implementações** de [serviço de aplicativo](../Application-Services.md) das interfaces definidas no projeto.`.Application.Contracts`
Uma `IssueAppService`turma é uma boa candidata para este projeto.
- Depende do `.Application.Contracts`projeto para poder implementar as interfaces e usar os DTOs.
- Depende do `.Domain`projeto para poder usar objetos de domínio (entidades, interfaces de repositório ... etc.) para executar a lógica do aplicativo.
### Projeto .EntityFrameworkCore
Este é o projeto de integração do EF Core. Ele define `DbContext`e implementa as interfaces de repositório definidas no `.Domain`projeto.
- Depende do `.Domain`projeto para poder fazer referência a entidades e interfaces de repositório.
> Você pode excluir este projeto se não desejar dar suporte ao EF Core para o seu módulo.
### Projeto .MongoDB
Este é o projeto de integração do MongoDB.
- Depende do `.Domain`projeto para poder fazer referência a entidades e interfaces de repositório.
> Você pode excluir este projeto se não quiser dar suporte ao MongoDB para o seu módulo.
### Projetos de teste
A solução possui vários projetos de teste, um para cada camada:
- `.Domain.Tests` é usado para testar a camada de domínio.
- `.Application.Tests` é usado para testar a camada de aplicativo.
- `.EntityFrameworkCore.Tests` é usado para testar a configuração do EF Core e os repositórios personalizados.
- `.MongoDB.Tests` é usado para testar a configuração do MongoDB e os repositórios personalizados.
- `.TestBase` é um projeto básico (compartilhado) para todos os testes.
Além disso, `.HttpApi.Client.ConsoleTestApp`é um aplicativo de console (não um projeto de teste automatizado) que demonstra o uso de APIs HTTP de um aplicativo Dotnet.
Projetos de teste são preparados para testes de integração;
- É totalmente integrado à estrutura ABP e a todos os serviços em sua aplicação.
- Ele usa o banco de dados SQLite na memória para o EF Core. Para o MongoDB, ele usa a biblioteca [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) .
- A autorização está desabilitada, portanto, qualquer serviço de aplicativo pode ser facilmente usado em testes.
Você ainda pode criar testes de unidade para suas classes, que serão mais difíceis de escrever (porque você precisará preparar objetos simulados / falsos), mas mais rápidos de executar (porque apenas testa uma única classe e ignora todo o processo de inicialização).
> Os testes de domínio e aplicativos estão usando o EF Core. Se você remover a integração do EF Core ou desejar usar o MongoDB para testar essas camadas, altere manualmente as referências do projeto e as dependências do módulo.
### Projetos Anfitriões
A solução possui alguns aplicativos host para executar seu módulo. Aplicativos host são usados para executar seu módulo em um aplicativo totalmente configurado. É útil no desenvolvimento. Os aplicativos host incluem alguns outros módulos além do módulo que está sendo desenvolvido:
Os aplicativos host oferecem suporte a dois tipos de cenários.
#### Cenário de aplicativo único (unificado)
Se o seu módulo tiver uma interface do usuário, o `.Web.Unified`aplicativo será usado para hospedar a interface do usuário e a API em um único ponto. Ele possui seu próprio `appsettings.json`arquivo (que inclui a cadeia de conexão do banco de dados) e as migrações do banco de dados EF Core.
Para o `.Web.Unified`aplicativo, há um único banco de dados chamado `YourProjectName_Unified`(como *IssueManagement_Unified* para esta amostra).
> Se você selecionou a `--no-ui`opção, este projeto não estará na sua solução.
##### Como correr?
Defina-o como o projeto de inicialização, execute o `Update-Database`comando para o EF Core no Package Manager Console e execute seu aplicativo. O nome de usuário padrão é `admin`e a senha é `1q2w3E*`.
#### Implantação separada e cenário de bancos de dados
Nesse cenário, há três aplicativos;
- `.IdentityServer`application é um servidor de autenticação usado por outros aplicativos. Ele possui seu próprio `appsettings.json`que contém conexão com o banco de dados e outras configurações.
- `.HttpApi.Host`hospeda a API HTTP do módulo. Ele possui seu próprio `appsettings.json`que contém conexões com o banco de dados e outras configurações.
- `.Web.Host`hospedar a interface do usuário do módulo. Este projeto contém um `appsettings.json`arquivo, mas não possui uma cadeia de conexão porque nunca se conecta ao banco de dados. Em vez disso, ele contém principalmente o terminal do servidor de API remoto e o servidor de autenticação.
O diagrama abaixo mostra a relação dos aplicativos:
![aplicativos de solução em camadas](../images/tiered-solution-applications.png)
`.Web.Host`O projeto usa a autenticação OpenId Connect para obter tokens de identidade e acesso para o usuário atual do `.IdentityServer`. Em seguida, usa o token de acesso para chamar o `.HttpApi.Host`. O servidor HTTP API usa autenticação de token de portador para obter declarações do token de acesso para autorizar o usuário atual.
##### Como correr?
Você deve executar o aplicativo com a ordem especificada:
- Primeiro, execute o `.IdentityServer`aplicativo, pois outros aplicativos dependem dele.
- Em seguida, execute o `.HttpApi.Host`que é usado pelo `.Web.Host`aplicativo.
- Por fim, você pode executar o `.Web.Host`projeto e efetuar login no aplicativo usando `admin`como nome de usuário e `1q2w3E*`senha.

3
docs/pt-BR/Testing.md

@ -0,0 +1,3 @@
# Testing
Façam!

661
docs/pt-BR/Tutorials/Angular/Part-I.md

@ -0,0 +1,661 @@
## Tutorial Angular - Parte I
### Sobre este tutorial
Nesta série de tutoriais, você criará um aplicativo usado para gerenciar uma lista de livros e seus autores. **Angular** será usado como estrutura da interface do usuário e **MongoDB** será usado como provedor de banco de dados.
Esta é a primeira parte da série de tutoriais angulares. Veja todas as peças:
- **Parte I: Crie o projeto e uma página de lista de livros (este tutorial)**
- [Parte II: Criar, atualizar e excluir livros](Part-II)
- [Parte III: Testes de Integração](Part-III)
Você pode acessar o **código fonte** do aplicativo no [repositório GitHub](https://github.com/abpframework/abp/tree/dev/samples/BookStore-Angular-MongoDb) .
### Criando o projeto
Crie um novo projeto nomeado `Acme.BookStore`selecionando Angular como a estrutura da interface do usuário e MongoDB como o provedor de banco de dados, crie o banco de dados e execute o aplicativo seguindo o [documento Introdução](../../Getting-Started-Angular-Template.md) .
### Estrutura da solução (back-end)
É assim que a estrutura da solução em camadas cuida da criação:
![solução de back-end da livraria](images/bookstore-backend-solution-v2.png)
> Você pode ver o [documento do modelo de aplicativo](../../Startup-Templates/Application.md) 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.Domain`contém suas [entidades](../../Entities.md) , [serviços de domínio](../../Domain-Services.md) 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](../../Entities.md) na **camada de domínio** ( `Acme.BookStore.Domain`projeto) da solução. A entidade principal do aplicativo é a `Book`. Crie uma classe, chamada `Book`, no `Acme.BookStore.Domain`projeto, como mostrado abaixo:
```csharp
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: `AggregateRoot`e `Entity`. **A raiz agregada** é um dos conceitos de **DDD (Domain Driven Design)** . Consulte o [documento da entidade](../../Entities.md) para obter detalhes e melhores práticas.
- `Book`entidade herda `AuditedAggregateRoot`que adiciona algumas propriedades de auditoria ( `CreationTime`, `CreatorId`, `LastModificationTime`... etc.) no topo da `AggregateRoot`classe.
- `Guid`é o **tipo** de **chave primária** da `Book`entidade.
#### BookType Enum
Defina a `BookType`enumeração no `Acme.BookStore.Domain.Shared`projeto:
```csharp
namespace Acme.BookStore
{
public enum BookType
{
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry
}
}
```
#### Adicionar entidade de livro ao seu DbContext
Adicione uma `IMongoCollection`propriedade ao `BookStoreMongoDbContext`interior do `Acme.BookStore.MongoDB`projeto:
```csharp
public class BookStoreMongoDbContext : AbpMongoDbContext
{
public IMongoCollection<Book> Books => Collection<Book>();
...
}
```
#### Adicionar dados de semente (amostra)
Esta seção é opcional, mas seria bom ter um dado inicial no banco de dados na primeira execução. O ABP fornece um [sistema de semente de dados](../../Data-Seeding.md) . Crie uma classe derivada de `IDataSeedContributor`no `.Domain`projeto:
```csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
namespace Acme.BookStore
{
public class BookStoreDataSeederContributor
: IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookStoreDataSeederContributor(IRepository<Book, Guid> bookRepository)
{
_bookRepository = bookRepository;
}
public async Task SeedAsync(DataSeedContext context)
{
if (await _bookRepository.GetCountAsync() > 0)
{
return;
}
await _bookRepository.InsertAsync(
new Book
{
Name = "1984",
Type = BookType.Dystopia,
PublishDate = new DateTime(1949, 6, 8),
Price = 19.84f
}
);
await _bookRepository.InsertAsync(
new Book
{
Name = "The Hitchhiker's Guide to the Galaxy",
Type = BookType.ScienceFiction,
PublishDate = new DateTime(1995, 9, 27),
Price = 42.0f
}
);
}
}
}
```
`BookStoreDataSeederContributor`simplesmente insere dois livros no banco de dados se não houver nenhum livro adicionado antes. O ABP descobre e executa automaticamente essa classe quando você propaga o banco de dados executando o `Acme.BookStore.DbMigrator`projeto.
### Crie o serviço de aplicativo
O próximo passo é criar um [serviço de aplicativo](../../Application-Services.md) 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 `BookDto`no `Acme.BookStore.Application.Contracts`projeto:
```csharp
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](../../Data-Transfer-Objects.md) 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 `Book`classe definida acima.
Será necessário converter `Book`entidades em `BookDto`objetos enquanto retorna os livros para a camada de apresentação. A biblioteca do [AutoMapper](https://automapper.org/) 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 `BookStoreApplicationAutoMapperProfile`classe no `Acme.BookStore.Application`projeto:
```csharp
using AutoMapper;
namespace Acme.BookStore
{
public class BookStoreApplicationAutoMapperProfile : Profile
{
public BookStoreApplicationAutoMapperProfile()
{
CreateMap<Book, BookDto>();
}
}
}
```
#### CreateUpdateBookDto
Crie uma classe DTO denominada `CreateUpdateBookDto`no `Acme.BookStore.Application.Contracts`projeto:
```csharp
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](../../Validation.md) pela estrutura ABP.
Em seguida, adicione um mapeamento `BookStoreApplicationAutoMapperProfile`do `CreateUpdateBookDto`objeto à `Book`entidade:
```csharp
CreateMap<CreateUpdateBookDto, Book>();
```
#### IBookAppService
Defina uma interface nomeada `IBookAppService`no `Acme.BookStore.Application.Contracts`projeto:
```csharp
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.
- `ICrudAppService`define comuns **CRUD** métodos: `GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync`e `DeleteAsync`. Não é necessário estendê-lo. Em vez disso, você pode herdar da `IApplicationService`interface vazia e definir seus próprios métodos manualmente.
- Existem algumas variações de `ICrudAppService`onde você pode usar DTOs separados para cada método.
#### BookAppService
Implemente `IBookAppService`como nomeado `BookAppService`no `Acme.BookStore.Application`projeto:
```csharp
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.
- `BookAppService`injeta `IRepository<Book, Guid>`qual é o repositório padrão da `Book`entidade. O ABP cria automaticamente repositórios padrão para cada raiz (ou entidade) agregada. Veja o [documento do repositório](../../Repositories) .
- `BookAppService`usa `IObjectMapper`para converter `Book`objetos em `BookDto`objetos e `CreateUpdateBookDto`objetos em `Book`objetos. O modelo de inicialização usa a biblioteca [AutoMapper](http://automapper.org/) 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**](../../AspNetCore/Auto-API-Controllers.md) 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](https://swagger.io/tools/swagger-ui/) usando a biblioteca [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) . Execute o `Acme.BookStore.HttpApi.Host`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 `Book`serviço e seus pontos de extremidade no estilo REST:
![livraria-arrogância](images/bookstore-swagger-api.png)
O Swagger tem uma ótima interface para testar APIs. Você pode tentar executar a `[GET] /api/app/book`API para obter uma lista de livros.
### Crie a página de livros
Neste tutorial;
- [A CLI angular](https://angular.io/cli) será usada para criar módulos, componentes e serviços
- [NGXS](https://ngxs.gitbook.io/ngxs/) será usado como a biblioteca de gerenciamento de estado
- [O Bootstrap](https://ng-bootstrap.github.io/#/home) será usado como a biblioteca de componentes da interface do usuário.
- [O Visual Studio Code](https://code.visualstudio.com/) será usado como editor de código (você pode usar seu editor favorito).
#### Instalar pacotes NPM
Abra uma janela do terminal, vá para a `angular`pasta e execute o `yarn` comando para instalar os pacotes NPM:
```
yarn
```
#### BooksModule
Execute a seguinte linha de comando para criar um novo módulo, denominado `BooksModule`:
```bash
yarn ng generate module books --route books --module app.module
```
![Creating-Books-Module.terminal](images/bookstore-creating-books-module-terminal.png)
Execute `yarn start`, aguarde Angular para executar o aplicativo e abra `http://localhost:4200/books`em um navegador:
![página inicial dos livros](images/bookstore-initial-books-page.png)
#### Encaminhamento
Abra `app-routing.module.ts`e substitua `books`conforme mostrado abaixo:
```js
import { ApplicationLayoutComponent } from '@abp/ng.theme.basic';-
//...
{
path: 'books',
component: ApplicationLayoutComponent,
loadChildren: () => import('./books/books.module').then(m => m.BooksModule),
data: {
routes: {
name: 'Books',
} as ABP.Route,
},
},
```
`ApplicationLayoutComponent`configuração define o layout do aplicativo para a nova página. Se você deseja ver sua rota na barra de navegação (menu principal), também deve adicionar o `data`objeto com `name`propriedade à sua rota.
![página inicial dos livros](images/bookstore-initial-books-page-with-layout.png)
#### Componente da lista de livros
Primeiro, substitua pela `books.component.html`seguinte linha para colocar a saída do roteador:
```html
<router-outlet></router-outlet>
```
Em seguida, execute o comando abaixo no terminal na pasta raiz para gerar um novo componente, chamado book-list:
```bash
yarn ng generate component books/book-list
```
![terminal-criando-lista-de-livros](images/bookstore-creating-book-list-terminal.png)
Importe `SharedModule`para `BooksModule`para reutilizar alguns componentes e serviços definidos em:
```js
import { SharedModule } from '../shared/shared.module';
@NgModule({
//...
imports: [
//...
SharedModule,
],
})
export class BooksModule {}
```
Em seguida, atualize o `routes`no `books-routing.module.ts`para adicionar o novo componente book-list:
```js
import { BookListComponent } from './book-list/book-list.component';
const routes: Routes = [
{
path: '',
component: BooksComponent,
children: [{ path: '', component: BookListComponent }],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class BooksRoutingModule {}
```
![página inicial da lista de livros](images/bookstore-initial-book-list-page.png)
#### Criar BooksState
Execute o seguinte comando no terminal para criar um novo estado, denominado `BooksState`:
```shell
yarn ng generate ngxs-schematic:state books
```
Este comando cria vários novos arquivos e edições `app.modules.ts`para importar o `NgxsModule`com o novo estado:
```js
// app.module.ts
import { BooksState } from './store/states/books.state';
@NgModule({
imports: [
//...
NgxsModule.forRoot([BooksState]),
],
//...
})
export class AppModule {}
```
#### Obter dados de livros do back-end
Primeiro, crie tipos de dados para mapear os dados que retornam do back-end (você pode verificar a interface do swagger ou a API do back-end para conhecer o formato dos dados).
Modifique o `books.ts`como mostrado abaixo:
```js
export namespace Books {
export interface State {
books: Response;
}
export interface Response {
items: Book[];
totalCount: number;
}
export interface Book {
name: string;
type: BookType;
publishDate: string;
price: number;
lastModificationTime: string;
lastModifierId: string;
creationTime: string;
creatorId: string;
id: string;
}
export enum BookType {
Undefined,
Adventure,
Biography,
Dystopia,
Fantastic,
Horror,
Science,
ScienceFiction,
Poetry,
}
}
```
Adicionada `Book`interface que representa um objeto de livro e `BookType`enum representa uma categoria de livro.
#### BooksService
Agora, crie um novo serviço, nomeado `BooksService`para executar chamadas HTTP para o servidor:
```bash
yarn ng generate service books/shared/books
```
![serviço-terminal-saída](images/bookstore-service-terminal-output.png)
Modifique `books.service.ts`como mostrado abaixo:
```js
import { Injectable } from '@angular/core';
import { RestService } from '@abp/ng.core';
import { Books } from '../../store/models';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class BooksService {
constructor(private restService: RestService) {}
get(): Observable<Books.Response> {
return this.restService.request<void, Books.Response>({
method: 'GET',
url: '/api/app/book'
});
}
}
```
Adicionado o `get`método para obter a lista de livros executando uma solicitação HTTP no terminal relacionado.
Substitua o `books.actions.ts`conteúdo conforme mostrado abaixo:
```js
export class GetBooks {
static readonly type = '[Books] Get';
}
```
#### Implementar o BooksState
Abra o `books.state.ts`e altere o arquivo, como mostrado abaixo:
```js
import { State, Action, StateContext, Selector } from '@ngxs/store';
import { GetBooks } from '../actions/books.actions';
import { Books } from '../models/books';
import { BooksService } from '../../books/shared/books.service';
import { tap } from 'rxjs/operators';
@State<Books.State>({
name: 'BooksState',
defaults: { books: {} } as Books.State,
})
export class BooksState {
@Selector()
static getBooks(state: Books.State) {
return state.books.items || [];
}
constructor(private booksService: BooksService) {}
@Action(GetBooks)
get(ctx: StateContext<Books.State>) {
return this.booksService.get().pipe(
tap(booksResponse => {
ctx.patchState({
books: booksResponse,
});
}),
);
}
}
```
Adicionada a `GetBooks`ação que usa o `BookService`definido acima para obter os livros e corrigir o estado.
> O NGXS exige retornar o observável sem assiná-lo, conforme feito nesta amostra (na função get).
#### BookListComponent
Modifique o `book-list.component.ts`como mostrado abaixo:
```js
import { Component, OnInit } from '@angular/core';
import { Store, Select } from '@ngxs/store';
import { BooksState } from '../../store/states';
import { Observable } from 'rxjs';
import { Books } from '../../store/models';
import { GetBooks } from '../../store/actions';
@Component({
selector: 'app-book-list',
templateUrl: './book-list.component.html',
styleUrls: ['./book-list.component.scss'],
})
export class BookListComponent implements OnInit {
@Select(BooksState.getBooks)
books$: Observable<Books.Book[]>;
booksType = Books.BookType;
loading = false;
constructor(private store: Store) {}
ngOnInit() {
this.loading = true;
this.store.dispatch(new GetBooks()).subscribe(() => {
this.loading = false;
});
}
}
```
> Consulte as [ações de despacho](https://ngxs.gitbook.io/ngxs/concepts/store#dispatching-actions) e [selecione](https://ngxs.gitbook.io/ngxs/concepts/select) na documentação do NGXS para obter mais informações sobre esses recursos do NGXS.
Substitua o `book-list.component.html`conteúdo conforme mostrado abaixo:
```html
<div id="wrapper" class="card">
<div class="card-header">
<div class="row">
<div class="col col-md-6">
<h5 class="card-title">
Books
</h5>
</div>
</div>
</div>
<div class="card-body">
<p-table [value]="books$ | async" [loading]="loading" [paginator]="true" [rows]="10">
<ng-template pTemplate="header">
<tr>
<th>Book name</th>
<th>Book type</th>
<th>Publish date</th>
<th>Price</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-data>
<tr>
<td>{{ data.name }}</td>
<td>{{ booksType[data.type] }}</td>
<td>{{ data.publishDate | date }}</td>
<td>{{ data.price }}</td>
</tr>
</ng-template>
</p-table>
</div>
</div>
```
> Usamos a [tabela PrimeNG](https://www.primefaces.org/primeng/#/table) neste componente.
A página de livros resultante é mostrada abaixo:
![livraria-lista-de-livros](images/bookstore-book-list.png)
E esta é a estrutura de pastas e arquivos no final deste tutorial:
![img](images/bookstore-angular-file-tree.png)
> Este tutorial segue o [Guia de estilo angular](https://angular.io/guide/styleguide#file-tree) .
### Próxima parte
Veja a [próxima parte](Part-II.md) deste tutorial.

582
docs/pt-BR/Tutorials/Angular/Part-II.md

@ -0,0 +1,582 @@
## Tutorial Angular - Parte II
### Sobre este tutorial
Esta é a segunda parte da série de tutoriais angulares. Veja todas as peças:
- [Parte I: Crie o projeto e uma página da lista de livros](Part-I.md)
- **Parte II: Criar, atualizar e excluir livros (este tutorial)**
- [Parte III: Testes de Integração](Part-III.md)
Você pode acessar o **código fonte** do aplicativo no [repositório GitHub](https://github.com/abpframework/abp/tree/dev/samples/BookStore-Angular-MongoDb) .
### Criando um novo livro
Nesta seção, você aprenderá como criar um novo formulário de diálogo modal para criar um novo livro.
#### Definição do tipo
Criar uma interface, com o nome `CreateUpdateBookInput`no `books.ts`como mostrado abaixo:
```js
export namespace Books {
//...
export interface CreateUpdateBookInput {
name: string;
type: BookType;
publishDate: string;
price: number;
}
}
```
`CreateUpdateBookInput`interface corresponde ao `CreateUpdateBookDto`no back-end.
#### Método de Serviço
Abra o `books.service.ts`e adicione um novo método, nomeado `create`para executar uma solicitação HTTP POST no servidor:
```js
create(createBookInput: Books.CreateUpdateBookInput): Observable<Books.Book> {
return this.restService.request<Books.CreateUpdateBookInput, Books.Book>({
method: 'POST',
url: '/api/app/book',
body: createBookInput
});
}
```
- `restService.request`A função obtém parâmetros genéricos para os tipos enviados e recebidos do servidor. Este exemplo envia um `CreateUpdateBookInput`objeto e recebe um `Book`objeto (você pode definir o tipo `void`de solicitação ou retorno, se não for usado).
#### Definições de estado
Adicione a `CreateUpdateBook`ação ao `books.actions.ts`conforme mostrado abaixo:
```js
import { Books } from '../models';
export class CreateUpdateBook {
static readonly type = '[Books] Create Update Book';
constructor(public payload: Books.CreateUpdateBookInput) {}
}
```
Abra `books.state.ts`e defina o `save`método que ouvirá uma `CreateUpdateBook`ação para criar um livro:
```js
import { ... , CreateUpdateBook } from '../actions/books.actions';
import { ... , switchMap } from 'rxjs/operators';
//...
@Action(CreateUpdateBook)
save(ctx: StateContext<Books.State>, action: CreateUpdateBook) {
return this.booksService
.create(action.payload)
.pipe(switchMap(() => ctx.dispatch(new GetBooks())));
}
```
Quando a `SaveBook`ação é despachada, o método save é executado. Ele chama o `create`método do `BooksService`definido anteriormente. Após a chamada de serviço, `BooksState`despacha a `GetBooks`ação para obter livros novamente do servidor para atualizar a página.
#### Adicionar um modal ao BookListComponent
Abra o `book-list.component.html`e adicione o `abp-modal`para mostrar / ocultar o modal para criar um novo livro.
```html
<abp-modal [(visible)]="isModalOpen">
<ng-template #abpHeader>
<h3>New Book</h3>
</ng-template>
<ng-template #abpBody> </ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-secondary" #abpClose>
Cancel
</button>
</ng-template>
</abp-modal>
```
`abp-modal`é um componente pré-construído para mostrar os modais. Embora você possa usar outra abordagem para mostrar um modal, `abp-modal`fornece benefícios adicionais.
Adicione um botão rotulado `New book`para mostrar o modal:
```html
<div class="row">
<div class="col col-md-6">
<h5 class="card-title">
Books
</h5>
</div>
<div class="text-right col col-md-6">
<button id="create-role" class="btn btn-primary" type="button" (click)="createBook()">
<i class="fa fa-plus mr-1"></i> <span>New book</span>
</button>
</div>
</div>
```
Abra a variável `book-list.component.ts`e adicione `isModalOpen`e `createBook`método para mostrar / ocultar o modal.
```js
isModalOpen = false;
//...
createBook() {
this.isModalOpen = true;
}
```
![modal vazio](images/bookstore-empty-new-book-modal.png)
#### Criar um formulário reativo
> [Os formulários reativos](https://angular.io/guide/reactive-forms) fornecem uma abordagem orientada a modelo para lidar com entradas de formulário cujos valores mudam ao longo do tempo.
Adicione uma `form`variável e injete um `FormBuilder`serviço `book-list.component.ts`como mostrado abaixo (lembre-se de adicionar a instrução de importação).
```js
import { FormGroup, FormBuilder } from '@angular/forms';
form: FormGroup;
constructor(
//...
private fb: FormBuilder
) {}
```
> O serviço [FormBuilder](https://angular.io/api/forms/FormBuilder) fornece métodos convenientes para gerar controles. Reduz a quantidade de clichê necessária para criar formulários complexos.
Adicione o `buildForm`método para criar um formulário de livro.
```js
buildForm() {
this.form = this.fb.group({
name: ['', Validators.required],
type: [null, Validators.required],
publishDate: [null, Validators.required],
price: [null, Validators.required],
});
}
```
- O `group`método de `FormBuilder`( `fb`) cria a `FormGroup`.
- Adicionado `Validators.required`método estático que valida o elemento de formulário relacionado.
Modifique o `createBook`método como mostrado abaixo:
```js
createBook() {
this.buildForm();
this.isModalOpen = true;
}
```
#### Crie os elementos DOM do formulário
Abra `book-list.component.html`e adicione o formulário no modelo de corpo do modal.
```html
<ng-template #abpBody>
<form [formGroup]="form">
<div class="form-group">
<label for="book-name">Name</label><span> * </span>
<input type="text" id="book-name" class="form-control" formControlName="name" autofocus />
</div>
<div class="form-group">
<label for="book-price">Price</label><span> * </span>
<input type="number" id="book-price" class="form-control" formControlName="price" />
</div>
<div class="form-group">
<label for="book-type">Type</label><span> * </span>
<select class="form-control" id="book-type" formControlName="type">
<option [ngValue]="null">Select a book type</option>
<option [ngValue]="booksType[type]" *ngFor="let type of bookTypeArr"> {{ type }}</option>
</select>
</div>
<div class="form-group">
<label>Publish date</label><span> * </span>
<input
#datepicker="ngbDatepicker"
class="form-control"
name="datepicker"
formControlName="publishDate"
ngbDatepicker
(click)="datepicker.toggle()"
/>
</div>
</form>
</ng-template>
```
- Este modelo cria um formulário com os campos Nome, Preço, Tipo e Data de publicação.
> Usamos o [datepicker do NgBootstrap](https://ng-bootstrap.github.io/#/components/datepicker/overview) neste componente.
Abra o `book-list.component.ts`e crie uma matriz chamada `bookTypeArr`:
```js
//...
form: FormGroup;
bookTypeArr = Object.keys(Books.BookType).filter(
bookType => typeof this.booksType[bookType] === 'number'
);
```
O `bookTypeArr`contém os campos da `BookType`enumeração. A matriz resultante é mostrada abaixo:
```js
['Adventure', 'Biography', 'Dystopia', 'Fantastic' ...]
```
Essa matriz foi usada no modelo de formulário anterior (no `ngFor`loop).
#### Requisitos do Datepicker
Você precisa importar `NgbDatepickerModule`para o `books.module.ts`:
```js
import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
imports: [
// ...
NgbDatepickerModule,
],
})
export class BooksModule {}
```
Abra o `book-list.component.ts`e adicione `providers`como mostrado abaixo:
```js
import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap';
@Component({
// ...
providers: [{ provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }],
})
export class BookListComponent implements OnInit {
// ...
```
> O `NgbDateAdapter`valor do Datepicker converte em `Date`tipo. Consulte os [adaptadores datepicker](https://ng-bootstrap.github.io/#/components/datepicker/overview) para obter mais detalhes.
![forma de livro novo](images/bookstore-new-book-form.png)
#### Salvando o livro
Abra o `book-list.component.html`e adicione um `abp-button`para salvar o formulário.
```html
<ng-template #abpFooter>
<button type="button" class="btn btn-secondary" #abpClose>
Cancel
</button>
<button class="btn btn-primary" (click)="save()">
<i class="fa fa-check mr-1"></i>
Save
</button>
</ng-template>
```
Isso adiciona um botão Salvar à área inferior do modal:
![livraria-novo-livro-formulário-v2](images/bookstore-new-book-form-v2.png)
Em seguida, defina um `save`método no `BookListComponent`:
```js
save() {
if (this.form.invalid) {
return;
}
this.store.dispatch(new CreateUpdateBook(this.form.value)).subscribe(() => {
this.isModalOpen = false;
this.form.reset();
});
}
```
### Atualizando um livro existente
#### BooksService
Abra o `books.service.ts`e adicione os métodos `getById`e `update`.
```js
getById(id: string): Observable<Books.Book> {
return this.restService.request<void, Books.Book>({
method: 'GET',
url: `/api/app/book/${id}`
});
}
update(updateBookInput: Books.CreateUpdateBookInput, id: string): Observable<Books.Book> {
return this.restService.request<Books.CreateUpdateBookInput, Books.Book>({
method: 'PUT',
url: `/api/app/book/${id}`,
body: updateBookInput
});
}
```
#### Ação CreateUpdateBook
Abra o parâmetro `books.actins.ts`e adicione `id`à `CreateUpdateBook`ação:
```js
export class CreateUpdateBook {
static readonly type = '[Books] Create Update Book';
constructor(public payload: Books.CreateUpdateBookInput, public id?: string) {}
}
```
Abra `books.state.ts`e modifique o `save`método conforme mostrado abaixo:
```js
@Action(CreateUpdateBook)
save(ctx: StateContext<Books.State>, action: CreateUpdateBook) {
let request;
if (action.id) {
request = this.booksService.update(action.payload, action.id);
} else {
request = this.booksService.create(action.payload);
}
return request.pipe(switchMap(() => ctx.dispatch(new GetBooks())));
}
```
#### BookListComponent
Injectar `BooksService`dependência, adicionando-o ao `book-list.component.ts`construtor e adicione uma variável chamada `selectedBook`.
```js
import { BooksService } from '../shared/books.service';
//...
selectedBook = {} as Books.Book;
constructor(
//...
private booksService: BooksService
)
```
`booksService`é usado para obter o livro de edição para preparar o formulário. Modifique o `buildForm`método para reutilizar o mesmo formulário ao editar um livro.
```js
buildForm() {
this.form = this.fb.group({
name: [this.selectedBook.name || '', Validators.required],
type: this.selectedBook.type || null,
publishDate: this.selectedBook.publishDate ? new Date(this.selectedBook.publishDate) : null,
price: this.selectedBook.price || null,
});
}
```
Adicione o `editBook`método como mostrado abaixo:
```js
editBook(id: string) {
this.booksService.getById(id).subscribe(book => {
this.selectedBook = book;
this.buildForm();
this.isModalOpen = true;
});
}
```
Adicionado `editBook`método para obter o livro de edição, criar o formulário e mostrar o modal.
Agora, adicione a `selectedBook`definição ao `createBook`método para reutilizar o mesmo formulário ao criar um novo livro:
```js
createBook() {
this.selectedBook = {} as Books.Book;
//...
}
```
Modifique o `save`método para passar o ID do livro selecionado, como mostrado abaixo:
```js
save() {
if (this.form.invalid) {
return;
}
this.store.dispatch(new CreateUpdateBook(this.form.value, this.selectedBook.id))
.subscribe(() => {
this.isModalOpen = false;
this.form.reset();
});
}
```
#### Adicione o menu suspenso "Ações" à tabela
Abra o `book-list.component.html` e adicione modifique o `p-table` como mostrado abaixo:
```html
<p-table [value]="books$ | async" [loading]="loading" [paginator]="true" [rows]="10">
<ng-template pTemplate="header">
<tr>
<th>Actions</th>
<th>Book name</th>
<th>Book type</th>
<th>Publish date</th>
<th>Price</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-data>
<tr>
<td>
<div ngbDropdown class="d-inline-block">
<button
class="btn btn-primary btn-sm dropdown-toggle"
data-toggle="dropdown"
aria-haspopup="true"
ngbDropdownToggle
>
<i class="fa fa-cog mr-1"></i>Actions
</button>
<div ngbDropdownMenu>
<button ngbDropdownItem (click)="editBook(data.id)">Edit</button>
</div>
</div>
</td>
<td>{{ data.name }}</td>
<td>{{ booksType[data.type] }}</td>
<td>{{ data.publishDate | date }}</td>
<td>{{ data.price }}</td>
</tr>
</ng-template>
</p-table>
```
- Adicionado um `th`para a coluna "Ações".
- Adicionado `button`com `ngbDropdownToggle`para abrir ações quando clicamos no botão.
> Nós costumávamos usar o [NgbDropdown](https://ng-bootstrap.github.io/#/components/dropdown/examples) no menu suspenso de ações.
A interface do usuário final é semelhante a:
![botões de ações](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/Angular/images/bookstore-actions-buttons.png)
Atualize o cabeçalho modal para alterar o título com base na operação atual:
```html
<ng-template #abpHeader>
<h3>{{ selectedBook.id ? 'Edit' : 'New Book' }}</h3>
</ng-template>
```
![botões de ações](images/bookstore-edit-modal.png)
### Exclusão de um livro existente
#### BooksService
Abra `books.service.ts`e inclua um `delete`método para excluir um livro com o `id`, executando uma solicitação HTTP no nó de extremidade relacionado:
```js
delete(id: string): Observable<void> {
return this.restService.request<void, void>({
method: 'DELETE',
url: `/api/app/book/${id}`
});
}
```
#### Ação DeleteBook
Adicione uma ação chamada `DeleteBook`para `books.actions.ts`:
```js
export class DeleteBook {
static readonly type = '[Books] Delete';
constructor(public id: string) {}
}
```
Abra o `books.state.ts`e adicione o `delete`método que ouvirá a `DeleteBook`ação para excluir um livro:
```js
import { ... , DeleteBook } from '../actions/books.actions';
//...
@Action(DeleteBook)
delete(ctx: StateContext<Books.State>, action: DeleteBook) {
return this.booksService.delete(action.id).pipe(switchMap(() => ctx.dispatch(new GetBooks())));
}
```
- Adicionado `DeleteBook`à lista de importação.
- Usa `bookService`para excluir o livro.
\#### Adicionar um botão Excluir
Abra `book-list.component.html`e modifique `ngbDropdownMenu`para adicionar o botão excluir, como mostrado abaixo:
```html
<div ngbDropdownMenu>
...
<button ngbDropdownItem (click)="delete(data.id, data.name)">
Delete
</button>
</div>
```
A interface do usuário suspensa de ações finais é semelhante a abaixo:
![livraria-final-ações-suspensa](images/bookstore-final-actions-dropdown.png)
\#### Caixa de diálogo Excluir confirmação
Abra `book-list.component.ts`e injete o `ConfirmationService`.
```js
import { ConfirmationService } from '@abp/ng.theme.shared';
//...
constructor(
//...
private confirmationService: ConfirmationService
)
```
> `ConfirmationService` é um serviço simples fornecido pela estrutura ABP que usa internamente o PrimeNG.
Adicione um método de exclusão ao `BookListComponent`:
```js
import { ... , DeleteBook } from '../../store/actions';
import { ... , Toaster } from '@abp/ng.theme.shared';
//...
delete(id: string, name: string) {
this.confirmationService
.error(`${name} will be deleted. Do you confirm that?`, 'Are you sure?')
.subscribe(status => {
if (status === Toaster.Status.confirm) {
this.store.dispatch(new DeleteBook(id));
}
});
}
```
O `delete`método mostra um pop-up de confirmação e assina a resposta do usuário. `DeleteBook`ação despachada somente se o usuário clicar no `Yes`botão O pop-up de confirmação é exibido abaixo:
![livraria-confirmação-pop-up](images/bookstore-confirmation-popup.png)
### Próxima parte
Veja a [próxima parte](Part-III.md) deste tutorial.

181
docs/pt-BR/Tutorials/Angular/Part-III.md

@ -0,0 +1,181 @@
## Tutorial do ASP.NET Core MVC - Parte III
### Sobre este tutorial
Esta é a terceira parte da série de tutoriais Angular. Veja todas as peças:
- [Parte I: Crie o projeto e uma página da lista de livros](Part-I.md)
- [Parte II: Criar, atualizar e excluir livros](Part-II.md)
- **Parte III: Testes de Integração (este tutorial)**
Esta parte abrange os testes do **lado** do **servidor** . Você pode acessar o **código fonte** do aplicativo no [repositório GitHub](https://github.com/abpframework/abp/tree/dev/samples/BookStore-Angular-MongoDb) .
### Testar projetos na solução
Existem vários projetos de teste na solução:
![livraria-teste-projetos](images/bookstore-test-projects-v3.png)
Cada projeto é usado para testar o projeto de aplicativo relacionado. Os projetos de teste usam as seguintes bibliotecas para teste:
- [xunit](https://xunit.github.io/) como a principal estrutura de teste.
- [Shouldly](http://shouldly.readthedocs.io/en/latest/) como uma biblioteca de asserções.
- [NSubstitute](http://nsubstitute.github.io/) como uma biblioteca de zombaria.
### Adicionando dados de teste
O modelo de inicialização contém a `BookStoreTestDataSeedContributor`classe no `Acme.BookStore.TestBase`projeto que cria alguns dados para executar os testes.
Mude a `BookStoreTestDataSeedContributor`classe como mostrado abaixo:
```csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
namespace Acme.BookStore
{
public class BookStoreTestDataSeedContributor
: IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Book, Guid> _bookRepository;
private readonly IGuidGenerator _guidGenerator;
public BookStoreTestDataSeedContributor(
IRepository<Book, Guid> bookRepository,
IGuidGenerator guidGenerator)
{
_bookRepository = bookRepository;
_guidGenerator = guidGenerator;
}
public async Task SeedAsync(DataSeedContext context)
{
await _bookRepository.InsertAsync(
new Book
{
Id = _guidGenerator.Create(),
Name = "Test book 1",
Type = BookType.Fantastic,
PublishDate = new DateTime(2015, 05, 24),
Price = 21
}
);
await _bookRepository.InsertAsync(
new Book
{
Id = _guidGenerator.Create(),
Name = "Test book 2",
Type = BookType.Science,
PublishDate = new DateTime(2014, 02, 11),
Price = 15
}
);
}
}
}
```
- Injetado `IRepository<Book, Guid>`e usado no `SeedAsync`para criar duas entidades de livro como dados de teste.
- `IGuidGenerator`Serviço usado para criar GUIDs. Embora `Guid.NewGuid()`funcionasse perfeitamente para testes, `IGuidGenerator`possui recursos adicionais especialmente importantes ao usar bancos de dados reais (consulte o documento de geração do [Guid](../../Guid-Generation.md) para obter mais informações).
### Testando o BookAppService
Crie uma classe de teste denominada `BookAppService_Tests`no `Acme.BookStore.Application.Tests`projeto:
```csharp
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Xunit;
namespace Acme.BookStore
{
public class BookAppService_Tests : BookStoreApplicationTestBase
{
private readonly IBookAppService _bookAppService;
public BookAppService_Tests()
{
_bookAppService = GetRequiredService<IBookAppService>();
}
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "Test book 1");
}
}
}
```
- `Should_Get_List_Of_Books`O teste simplesmente usa o `BookAppService.GetListAsync`método para obter e verificar a lista de usuários.
Adicione um novo teste que crie um novo livro válido:
```csharp
[Fact]
public async Task Should_Create_A_Valid_Book()
{
//Act
var result = await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "New test book 42",
Price = 10,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
//Assert
result.Id.ShouldNotBe(Guid.Empty);
result.Name.ShouldBe("New test book 42");
}
```
Adicione um novo teste que tente criar um livro inválido e falhe:
```csharp
[Fact]
public async Task Should_Not_Create_A_Book_Without_Name()
{
var exception = await Assert.ThrowsAsync<AbpValidationException>(async () =>
{
await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "",
Price = 10,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
});
exception.ValidationErrors
.ShouldContain(err => err.MemberNames.Any(mem => mem == "Name"));
}
```
- Como o `Name`está vazio, o ABP lança um `AbpValidationException`.
Abra a **janela Test Explorer** (use o menu Test -> Windows -> Test Explorer, se não estiver visível) e **execute Todos os** testes:
![testes de serviço de livraria](images/bookstore-test-explorer.png)
Parabéns, ícones verdes mostram que os testes foram aprovados com sucesso!

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-actions-buttons.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-angular-file-tree.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-backend-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-book-list.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-confirmation-popup.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-creating-book-list-terminal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-creating-books-module-terminal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-edit-modal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-empty-new-book-modal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-final-actions-dropdown.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-initial-book-list-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page-with-layout.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-service-terminal-output.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-swagger-api.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-test-explorer.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
docs/pt-BR/Tutorials/Angular/images/bookstore-test-projects-v3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

462
docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-I.md

@ -0,0 +1,462 @@
## 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:
- **Parte I: Crie o projeto e uma página de lista de livros (este tutorial)**
- [Parte II: Criar, atualizar e excluir livros](Part-II.md)
- [Parte III: Testes de Integração](Part-III.md)
Você pode acessar o **código fonte** do aplicativo [no repositório GitHub](https://github.com/abpframework/abp/tree/master/samples/BookStore) .
> Você também pode assistir a [este curso em vídeo](https://amazingsolutions.teachable.com/p/lets-build-the-bookstore-application) 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](Getting-Started-AspNetCore-MVC-Template.md).
### Estrutura da solução
É assim que a estrutura da solução em camadas cuida da criação:
![livraria-visual-studio-solução](images/bookstore-visual-studio-solution-v3.png)
> Você pode ver o [documento do modelo de aplicativo](https://docs.abp.io/en/abp/latest/Startup-Templates/Application) 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.Domain`contém suas [entidades](https://docs.abp.io/en/abp/latest/Entities.md) , [serviços de domínio](https://docs.abp.io/en/abp/latest/Domain-Services) 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](https://docs.abp.io/en/abp/latest/Entities) na **camada de domínio** ( `Acme.BookStore.Domain`projeto) da solução. A entidade principal do aplicativo é a `Book`. Crie uma classe, chamada `Book`, no `Acme.BookStore.Domain`projeto, como mostrado abaixo:
```csharp
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: `AggregateRoot`e `Entity`. **A raiz agregada** é um dos conceitos de **DDD (Domain Driven Design)** . Consulte o [documento da entidade](https://docs.abp.io/en/abp/latest/Entities) para obter detalhes e melhores práticas.
- `Book`entidade herda `AuditedAggregateRoot`que adiciona algumas propriedades de auditoria ( `CreationTime`, `CreatorId`, `LastModificationTime`... etc.) no topo da `AggregateRoot`classe.
- `Guid`é o **tipo** de **chave primária** da `Book`entidade.
#### BookType Enum
Defina a `BookType`enumeração no `Acme.BookStore.Domain.Shared`projeto:
```csharp
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 `DbSet`propriedade à `BookStoreDbContext`classe no `Acme.BookStore.EntityFrameworkCore`projeto, conforme mostrado abaixo:
```csharp
public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
{
public DbSet<Book> Books { get; set; }
...
}
```
#### Configure sua entidade do livro
Abra o `BookStoreDbContextModelCreatingExtensions.cs`arquivo no `Acme.BookStore.EntityFrameworkCore`projeto e adicione o seguinte código ao final do `ConfigureBookStore`método para configurar a entidade Livro:
```csharp
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](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) 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.DbMigrations`como o **projeto padrão** e execute o seguinte comando:
![livraria-pmc-add-book-migration](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png)
Isso criará uma nova classe de migração dentro da `Migrations`pasta. Em seguida, execute o `Update-Database`comando para atualizar o esquema do banco de dados:
```
PM> Update-Database
```
#### Adicionar dados de amostra
`Update-Database`O comando criou a `AppBooks`tabela 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](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-books-table.png)
### Crie o serviço de aplicativo
O próximo passo é criar um [serviço de aplicativo](https://docs.abp.io/en/abp/latest/Application-Services) 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 `BookDto`no `Acme.BookStore.Application.Contracts`projeto:
```csharp
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](https://docs.abp.io/en/abp/latest/Data-Transfer-Objects) 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 `Book`classe definida acima.
Será necessário converter `Book`entidades em `BookDto`objetos enquanto retorna os livros para a camada de apresentação. [A](https://automapper.org/) biblioteca do [AutoMapper](https://automapper.org/) 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 `BookStoreApplicationAutoMapperProfile`classe no `Acme.BookStore.Application`projeto:
```csharp
using AutoMapper;
namespace Acme.BookStore
{
public class BookStoreApplicationAutoMapperProfile : Profile
{
public BookStoreApplicationAutoMapperProfile()
{
CreateMap<Book, BookDto>();
}
}
}
```
#### CreateUpdateBookDto
Crie uma classe DTO denominada `CreateUpdateBookDto`no `Acme.BookStore.Application.Contracts`projeto:
```csharp
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](https://docs.abp.io/en/abp/latest/Validation) pela estrutura ABP.
Em seguida, adicione um mapeamento `BookStoreApplicationAutoMapperProfile`do `CreateUpdateBookDto`objeto à `Book`entidade:
```csharp
CreateMap<CreateUpdateBookDto, Book>();
```
#### IBookAppService
Defina uma interface nomeada `IBookAppService`no `Acme.BookStore.Application.Contracts`projeto:
```csharp
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.
- `ICrudAppService`define comuns **CRUD** métodos: `GetAsync`, `GetListAsync`, `CreateAsync`, `UpdateAsync`e `DeleteAsync`. Não é necessário estendê-lo. Em vez disso, você pode herdar da `IApplicationService`interface vazia e definir seus próprios métodos manualmente.
- Existem algumas variações de `ICrudAppService`onde você pode usar DTOs separados para cada método.
#### BookAppService
Implemente `IBookAppService`como nomeado `BookAppService`no `Acme.BookStore.Application`projeto:
```csharp
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.
- `BookAppService`injeta `IRepository<Book, Guid>`qual é o repositório padrão da `Book`entidade. O ABP cria automaticamente repositórios padrão para cada raiz (ou entidade) agregada. Veja o [documento](https://docs.abp.io/en/abp/latest/Repositories) do [repositório](https://docs.abp.io/en/abp/latest/Repositories) .
- `BookAppService`usa `IObjectMapper`para converter `Book`objetos em `BookDto`objetos e `CreateUpdateBookDto`objetos em `Book`objetos. O modelo de inicialização usa a biblioteca [AutoMapper](http://automapper.org/) 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**](https://docs.abp.io/en/abp/latest/AspNetCore/Auto-API-Controllers) 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](https://swagger.io/tools/swagger-ui/) do [swagger](https://swagger.io/tools/swagger-ui/) usando a biblioteca [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/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 `Book`serviço e seus pontos de extremidade no estilo REST:
![livraria-arrogância](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-swagger.png)
O Swagger tem uma ótima interface para testar APIs. Você pode tentar executar a `[GET] /api/app/book`API 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 `$.ajax`ou 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:
```js
acme.bookStore.book.getList({}).done(function (result) { console.log(result); });
```
- `acme.bookStore`é o espaço para nome do `BookAppService`convertido em [camelCase](https://en.wikipedia.org/wiki/Camel_case) .
- `book`é o nome convencional para o `BookAppService`(postfix do AppService removido e convertido em camelCase).
- `getList`é o nome convencional para o `GetListAsync`método definido na `AsyncCrudAppService`classe base (postfix assíncrono removido e convertido em camelCase).
- `{}`O argumento é usado para enviar um objeto vazio ao `GetListAsync`método que normalmente espera um objeto do tipo `PagedAndSortedResultRequestDto`usado 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).
- `getList`A 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](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist.png)
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](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist-network.png)
Vamos **criar um novo livro** usando a `create`função:
```js
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 `Books`tabela no banco de dados para ver a nova linha do livro. Você pode tentar `get`, `update`e `delete`funciona 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,](https://docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/razor-pages-start) recomendada pela Microsoft.
Crie uma nova `Books`pasta na `Pages`pasta do `Acme.BookStore.Web`projeto e adicione uma nova página Razor denominada `Index.cshtml`:
![livraria-add-index-page](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png)
Abra `Index.cshtml`e altere o conteúdo, como mostrado abaixo:
```html
@page
@using Acme.BookStore.Web.Pages.Books
@inherits Acme.BookStore.Web.Pages.BookStorePage
@model IndexModel
<h2>Books</h2>
```
- Esse código altera a herança padrão do Razor View Page Model para que ele **herda** da `BookStorePage`classe (em vez de `PageModel`). A `BookStorePage`classe que acompanha o modelo de inicialização e fornece algumas propriedades / métodos compartilhados usados por todas as páginas.
- Verifique se o `IndexModel`( *Index.cshtml.cs)* possui o `Acme.BookStore.Pages.Books`espaço para nome ou atualize-o no `Index.cshtml`.
#### Adicionar página de livros ao menu principal
Abra a `BookStoreMenuContributor`classe na `Menus`pasta e adicione o seguinte código ao final do `ConfigureMainMenuAsync`método:
```csharp
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/BookStore`pasta do `Acme.BookStore.Domain.Shared`projeto:
![arquivos de localização de livraria](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png)
Abra o `en.json`arquivo e adicione textos de localização `Menu:BookStore`e `Menu:Books`chaves ao final do arquivo:
```json
{
"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](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization) e o estende de várias maneiras. Consulte o [documento de localização](https://docs.abp.io/en/abp/latest/Localization) 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](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-menu-items.png)
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](https://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.cshtml`seguinte:
```html
@page
@inherits Acme.BookStore.Web.Pages.BookStorePage
@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](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro) é usado para adicionar **scripts** externos à página. Possui muitos recursos adicionais em comparação com a `script`tag padrão . Ele lida com **minificação** e **controle** de **versão,** por exemplo. Consulte o [documento de compactação e redução](https://docs.abp.io/en/abp/latest/AspNetCore/Bundling-Minification) para obter detalhes.
- `abp-card`e `abp-table`são **auxiliares de tags** para o [componente de cartão](http://getbootstrap.com/docs/4.1/components/card/) do Twitter Bootstrap . Existem muitos auxiliares de tag no ABP para usar facilmente a maioria dos componentes de [autoinicialização](https://getbootstrap.com/) . 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](https://docs.abp.io/en/abp/latest/AspNetCore/Tag-Helpers) da [tag](https://docs.abp.io/en/abp/latest/AspNetCore/Tag-Helpers) .
- 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.js`arquivo JavaScript na `Pages/Books/`pasta:
![arquivo-index-js-bookstore](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png)
`index.js` o conteúdo é mostrado abaixo:
```js
$(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](https://datatables.net/manual/) para obter mais opções de configuração.
A interface do usuário final é mostrada abaixo:
![livraria-lista-de-livros](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-book-list-2.png)
### Próxima parte
Veja a [próxima parte](https://docs.abp.io/en/abp/latest/Tutorials/AspNetCore-Mvc/Part-II) deste tutorial.

466
docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-II.md

@ -0,0 +1,466 @@
## Tutorial do ASP.NET Core MVC - Parte II
### Sobre este tutorial
Esta é a segunda parte da série de tutoriais do ASP.NET Core MVC. Veja todas as peças:
- [Parte I: Crie o projeto e uma página da lista de livros](https://docs.abp.io/en/abp/latest/Tutorials/AspNetCore-Mvc/Part-I)
- **Parte II: Criar, atualizar e excluir livros (este tutorial)**
- [Parte III: Testes de Integração](https://docs.abp.io/en/abp/latest/Tutorials/AspNetCore-Mvc/Part-III)
Você pode acessar o **código fonte** do aplicativo [no repositório GitHub](https://github.com/volosoft/abp/tree/master/samples/BookStore) .
> Você também pode assistir a [este curso em vídeo](https://amazingsolutions.teachable.com/p/lets-build-the-bookstore-application) preparado por um membro da comunidade ABP, com base neste tutorial.
### Criando um novo livro
Nesta seção, você aprenderá como criar um novo formulário de diálogo modal para criar um novo livro. A caixa de diálogo do resultado será assim:
![livraria-criar-diálogo](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog-2.png)
#### Crie o formulário modal
Crie uma nova página de navalha, nomeada `CreateModal.cshtml`sob a `Pages/Books`pasta do `Acme.BookStore.Web`projeto:
![livraria-adicionar-criar-diálogo](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png)
##### CreateModal.cshtml.cs
Abra o `CreateModal.cshtml.cs`arquivo ( `CreateModalModel`classe) e substitua pelo seguinte código:
```csharp
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Acme.BookStore.Web.Pages.Books
{
public class CreateModalModel : BookStorePageModel
{
[BindProperty]
public CreateUpdateBookDto Book { get; set; }
private readonly IBookAppService _bookAppService;
public CreateModalModel(IBookAppService bookAppService)
{
_bookAppService = bookAppService;
}
public async Task<IActionResult> OnPostAsync()
{
await _bookAppService.CreateAsync(Book);
return NoContent();
}
}
}
```
- Esta classe é derivada do em `BookStorePageModel`vez do padrão `PageModel`. `BookStorePageModel`herda o `PageModel`e adiciona algumas propriedades / métodos comuns que podem ser usados pelas classes de modelo de página.
- `[BindProperty]`O atributo na `Book`propriedade vincula os dados de solicitação posterior a essa propriedade.
- Essa classe simplesmente injeta o `IBookAppService`em seu construtor e chama o `CreateAsync`método no `OnPostAsync`manipulador.
##### CreateModal.cshtml
Abra o `CreateModal.cshtml`arquivo e cole o código abaixo:
```html
@page
@inherits Acme.BookStore.Web.Pages.BookStorePage
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model Acme.BookStore.Web.Pages.Books.CreateModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="Book" data-ajaxForm="true" asp-page="/Books/CreateModal">
<abp-modal>
<abp-modal-header title="@L["NewBook"].Value"></abp-modal-header>
<abp-modal-body>
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>
```
- Este modal usa o
```
abp-dynamic-form
```
auxiliar de marca para criar automaticamente o formulário a partir da
```
CreateBookViewModel
```
classe.
- `abp-model`O atributo indica o objeto do modelo, a `Book`propriedade neste caso.
- `data-ajaxForm` O atributo faz com que o formulário seja enviado via AJAX, em vez de uma postagem de página clássica.
- `abp-form-content`O auxiliar de marca é um espaço reservado para renderizar os controles do formulário (isso é opcional e necessário apenas se você tiver adicionado outro conteúdo à `abp-dynamic-form`marca, como nesta página).
#### Adicione o botão "Novo livro"
Abra `Pages/Books/Index.cshtml`e altere a `abp-card-header`tag, como mostrado abaixo:
```html
<abp-card-header>
<abp-row>
<abp-column size-md="_6">
<h2>@L["Books"]</h2>
</abp-column>
<abp-column size-md="_6" class="text-right">
<abp-button id="NewBookButton"
text="@L["NewBook"].Value"
icon="plus"
button-type="Primary" />
</abp-column>
</abp-row>
</abp-card-header>
```
Acabei de adicionar um botão **Novo livro** no canto **superior direito** da tabela:
![livraria-novo-livro-botão](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-new-book-button.png)
Abra o `pages/books/index.js`e adicione o seguinte código logo após a configuração da tabela de dados:
```js
var createModal = new abp.ModalManager(abp.appPath + 'Books/CreateModal');
createModal.onResult(function () {
dataTable.ajax.reload();
});
$('#NewBookButton').click(function (e) {
e.preventDefault();
createModal.open();
});
```
- `abp.ModalManager`é uma classe auxiliar para abrir e gerenciar modais no lado do cliente. Ele usa internamente o modal padrão do Twitter Bootstrap, mas abstrai muitos detalhes, fornecendo uma API simples.
Agora, você pode **executar o aplicativo** e adicionar novos livros usando o novo formulário modal.
### Atualizando um livro existente
Crie uma nova página de navalha, nomeada `EditModal.cshtml`sob a `Pages/Books`pasta do `Acme.BookStore.Web`projeto:
![livraria-adicionar-editar-diálogo](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-add-edit-dialog.png)
#### EditModal.cshtml.cs
Abra o `EditModal.cshtml.cs`arquivo ( `EditModalModel`classe) e substitua pelo seguinte código:
```csharp
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Acme.BookStore.Web.Pages.Books
{
public class EditModalModel : BookStorePageModel
{
[HiddenInput]
[BindProperty(SupportsGet = true)]
public Guid Id { get; set; }
[BindProperty]
public CreateUpdateBookDto Book { get; set; }
private readonly IBookAppService _bookAppService;
public EditModalModel(IBookAppService bookAppService)
{
_bookAppService = bookAppService;
}
public async Task OnGetAsync()
{
var bookDto = await _bookAppService.GetAsync(Id);
Book = ObjectMapper.Map<BookDto, CreateUpdateBookDto>(bookDto);
}
public async Task<IActionResult> OnPostAsync()
{
await _bookAppService.UpdateAsync(Id, Book);
return NoContent();
}
}
}
```
- `[HiddenInput]`e `[BindProperty]`são atributos padrão do ASP.NET Core MVC. Utilizado `SupportsGet`para obter o valor do ID a partir do parâmetro da string de consulta da solicitação.
- Mapeado `BookDto`(recebido de `BookAppService.GetAsync`) para `CreateUpdateBookDto`no `GetAsync`método
- O `OnPostAsync`simplesmente usa `BookAppService.UpdateAsync`para atualizar a entidade.
#### Mapeamento de BookDto para CreateUpdateBookDto
A fim de executar `BookDto`a `CreateUpdateBookDto`opor mapeamento, abrir o `BookStoreWebAutoMapperProfile.cs`no `Acme.BookStore.Web`projecto e alterá-lo como se mostra abaixo:
```csharp
using AutoMapper;
namespace Acme.BookStore.Web
{
public class BookStoreWebAutoMapperProfile : Profile
{
public BookStoreWebAutoMapperProfile()
{
CreateMap<BookDto, CreateUpdateBookDto>();
}
}
}
```
- Apenas adicionado `CreateMap<BookDto, CreateUpdateBookDto>();`como a definição de mapeamento.
#### EditModal.cshtml
Substitua o `EditModal.cshtml`conteúdo pelo seguinte:
```html
@page
@inherits Acme.BookStore.Web.Pages.BookStorePage
@using Acme.BookStore.Web.Pages.Books
@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
@model EditModalModel
@{
Layout = null;
}
<abp-dynamic-form abp-model="Book" data-ajaxForm="true" asp-page="/Books/EditModal">
<abp-modal>
<abp-modal-header title="@L["Update"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Id" />
<abp-form-content />
</abp-modal-body>
<abp-modal-footer buttons="@(AbpModalButtons.Cancel|AbpModalButtons.Save)"></abp-modal-footer>
</abp-modal>
</abp-dynamic-form>
```
Esta página é muito semelhante à `CreateModal.cshtml`exceção;
- Ele inclui um `abp-input`para a `Id`propriedade armazenar o ID do livro de edição (que é uma entrada oculta).
- Ele usa `Books/EditModal`como URL de postagem e texto de *atualização* como cabeçalho modal.
#### Adicione o menu suspenso "Ações" à tabela
Adicionaremos um botão suspenso ("Ações") para cada linha da tabela. A interface do usuário final é assim:
![livraria-livros-mesa-ações](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-books-table-actions.png)
Abra a `Pages/Books/Index.cshtml`página e altere a seção da tabela como mostrado abaixo:
```html
<abp-table striped-rows="true" id="BooksTable">
<thead>
<tr>
<th>@L["Actions"]</th>
<th>@L["Name"]</th>
<th>@L["Type"]</th>
<th>@L["PublishDate"]</th>
<th>@L["Price"]</th>
<th>@L["CreationTime"]</th>
</tr>
</thead>
</abp-table>
```
- Acabei de adicionar uma nova `th`tag para as "Ações".
Abra `pages/books/index.js`e substitua o conteúdo como abaixo:
```js
$(function () {
var l = abp.localization.getResource('BookStore');
var createModal = new abp.ModalManager(abp.appPath + 'Books/CreateModal');
var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal');
var dataTable = $('#BooksTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
order: [[1, "asc"]],
ajax: abp.libs.datatables.createAjax(acme.bookStore.book.getList),
columnDefs: [
{
rowAction: {
items:
[
{
text: l('Edit'),
action: function (data) {
editModal.open({ id: data.record.id });
}
}
]
}
},
{ data: "name" },
{ data: "type" },
{ data: "publishDate" },
{ data: "price" },
{ data: "creationTime" }
]
}));
createModal.onResult(function () {
dataTable.ajax.reload();
});
editModal.onResult(function () {
dataTable.ajax.reload();
});
$('#NewBookButton').click(function (e) {
e.preventDefault();
createModal.open();
});
});
```
- Utilizado `abp.localization.getResource('BookStore')`para poder usar os mesmos textos de localização definidos no lado do servidor.
- Adicionado um novo `ModalManager`nome `createModal`para abrir a caixa de diálogo criar modal.
- Adicionado um novo `ModalManager`nome `editModal`para abrir a caixa de diálogo modal de edição.
- Adicionada uma nova coluna no início da `columnDefs`seção. Esta coluna é usada para o botão suspenso "Ações".
- A ação "Novo livro" simplesmente chama `createModal.open`para abrir a caixa de diálogo Criar.
- A ação "Editar" simplesmente chama `editModal.open`para abrir a caixa de diálogo de edição. `Você pode executar o aplicativo e editar qualquer livro selecionando a ação de edição.
### Exclusão de um livro existente
Abra o `pages/books/index.js`e adicione um novo item ao `rowAction` `items`:
```js
{
text: l('Delete'),
confirmMessage: function (data) {
return l('BookDeletionConfirmationMessage', data.record.name);
},
action: function (data) {
acme.bookStore.book
.delete(data.record.id)
.then(function() {
abp.notify.info(l('SuccessfullyDeleted'));
dataTable.ajax.reload();
});
}
}
```
- `confirmMessage`A opção é usada para fazer uma pergunta de confirmação antes de executar o `action`.
- Utilizou a `acme.bookStore.book.delete`função de proxy javascript para executar uma solicitação AJAX para excluir um livro.
- `abp.notify.info` é usado para mostrar uma notificação toastr logo após a exclusão.
O `index.js`conteúdo final é mostrado abaixo:
```js
$(function () {
var l = abp.localization.getResource('BookStore');
var createModal = new abp.ModalManager(abp.appPath + 'Books/CreateModal');
var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal');
var dataTable = $('#BooksTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: false,
autoWidth: false,
scrollCollapse: true,
order: [[1, "asc"]],
ajax: abp.libs.datatables.createAjax(acme.bookStore.book.getList),
columnDefs: [
{
rowAction: {
items:
[
{
text: l('Edit'),
action: function (data) {
editModal.open({ id: data.record.id });
}
},
{
text: l('Delete'),
confirmMessage: function (data) {
return l('BookDeletionConfirmationMessage', data.record.name);
},
action: function (data) {
acme.bookStore.book
.delete(data.record.id)
.then(function() {
abp.notify.info(l('SuccessfullyDeleted'));
dataTable.ajax.reload();
});
}
}
]
}
},
{ data: "name" },
{ data: "type" },
{ data: "publishDate" },
{ data: "price" },
{ data: "creationTime" }
]
}));
createModal.onResult(function () {
dataTable.ajax.reload();
});
editModal.onResult(function () {
dataTable.ajax.reload();
});
$('#NewBookButton').click(function (e) {
e.preventDefault();
createModal.open();
});
});
```
Abra o `en.json`no `Acme.BookStore.Domain.Shared`projeto e adicione a seguinte linha:
```json
"BookDeletionConfirmationMessage": "Are you sure to delete the book {0}?"
```
Execute o aplicativo e tente excluir um livro.
### Próxima parte
Veja a [próxima parte](https://docs.abp.io/en/abp/latest/Tutorials/AspNetCore-Mvc/Part-III) deste tutorial.

182
docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-III.md

@ -0,0 +1,182 @@
## Tutorial do ASP.NET Core MVC - Parte III
### Sobre este tutorial
Esta é a terceira parte da série de tutoriais do ASP.NET Core MVC. Veja todas as peças:
- [Parte I: Crie o projeto e uma página da lista de livros](https://docs.abp.io/en/abp/latest/Tutorials/AspNetCore-Mvc/Part-I)
- [Parte II: Criar, atualizar e excluir livros](https://docs.abp.io/en/abp/latest/Tutorials/AspNetCore-Mvc/Part-II)
- **Parte III: Testes de Integração (este tutorial)**
Você pode acessar o **código fonte** do aplicativo [no repositório GitHub](https://github.com/volosoft/abp/tree/master/samples/BookStore) .
> Você também pode assistir a [este curso em vídeo](https://amazingsolutions.teachable.com/p/lets-build-the-bookstore-application) preparado por um membro da comunidade ABP, com base neste tutorial.
### Testar projetos na solução
Existem vários projetos de teste na solução:
![livraria-teste-projetos-v2](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png)
Cada projeto é usado para testar o projeto de aplicativo relacionado. Os projetos de teste usam as seguintes bibliotecas para teste:
- [xunit](https://xunit.github.io/) como a principal estrutura de teste.
- [Altamente](http://shouldly.readthedocs.io/en/latest/) como uma biblioteca de asserções.
- [NSubstitute](http://nsubstitute.github.io/) como uma biblioteca de zombaria.
### Adicionando dados de teste
O modelo de inicialização contém a `BookStoreTestDataSeedContributor`classe no `Acme.BookStore.TestBase`projeto que cria alguns dados para executar os testes.
Mude a `BookStoreTestDataSeedContributor`classe como mostrado abaixo:
```csharp
using System;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
namespace Acme.BookStore
{
public class BookStoreTestDataSeedContributor
: IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Book, Guid> _bookRepository;
private readonly IGuidGenerator _guidGenerator;
public BookStoreTestDataSeedContributor(
IRepository<Book, Guid> bookRepository,
IGuidGenerator guidGenerator)
{
_bookRepository = bookRepository;
_guidGenerator = guidGenerator;
}
public async Task SeedAsync(DataSeedContext context)
{
await _bookRepository.InsertAsync(
new Book
{
Id = _guidGenerator.Create(),
Name = "Test book 1",
Type = BookType.Fantastic,
PublishDate = new DateTime(2015, 05, 24),
Price = 21
}
);
await _bookRepository.InsertAsync(
new Book
{
Id = _guidGenerator.Create(),
Name = "Test book 2",
Type = BookType.Science,
PublishDate = new DateTime(2014, 02, 11),
Price = 15
}
);
}
}
}
```
- Injetado `IRepository<Book, Guid>`e usado no `SeedAsync`para criar duas entidades de livro como dados de teste.
- `IGuidGenerator`Serviço usado para criar GUIDs. Embora `Guid.NewGuid()`funcionasse perfeitamente para testes, `IGuidGenerator`possui recursos adicionais especialmente importantes ao usar bancos de dados reais (consulte o [documento de geração](https://docs.abp.io/en/abp/latest/Guid-Generation) do [Guid](https://docs.abp.io/en/abp/latest/Guid-Generation) para obter mais informações).
### Testando o BookAppService
Crie uma classe de teste denominada `BookAppService_Tests`no `Acme.BookStore.Application.Tests`projeto:
```csharp
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Xunit;
namespace Acme.BookStore
{
public class BookAppService_Tests : BookStoreApplicationTestBase
{
private readonly IBookAppService _bookAppService;
public BookAppService_Tests()
{
_bookAppService = GetRequiredService<IBookAppService>();
}
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "Test book 1");
}
}
}
```
- `Should_Get_List_Of_Books`O teste simplesmente usa o `BookAppService.GetListAsync`método para obter e verificar a lista de usuários.
Adicione um novo teste que crie um novo livro válido:
```csharp
[Fact]
public async Task Should_Create_A_Valid_Book()
{
//Act
var result = await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "New test book 42",
Price = 10,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
//Assert
result.Id.ShouldNotBe(Guid.Empty);
result.Name.ShouldBe("New test book 42");
}
```
Adicione um novo teste que tente criar um livro inválido e falhe:
```csharp
[Fact]
public async Task Should_Not_Create_A_Book_Without_Name()
{
var exception = await Assert.ThrowsAsync<AbpValidationException>(async () =>
{
await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "",
Price = 10,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
});
exception.ValidationErrors
.ShouldContain(err => err.MemberNames.Any(mem => mem == "Name"));
}
```
- Como o `Name`está vazio, o ABP lança um `AbpValidationException`.
Abra a **janela Test Explorer** (use o menu Test -> Windows -> Test Explorer, se não estiver visível) e **execute Todos os** testes:
![testes de serviço de livraria](https://raw.githubusercontent.com/abpframework/abp/master/docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png)
Parabéns, ícones verdes mostram que os testes foram aprovados com sucesso!

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-edit-dialog.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table-actions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-template.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-homepage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-menu-items.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-new-book-button.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-swagger.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist-network.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-user-management.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

3
docs/pt-BR/Unit-Of-Work.md

@ -0,0 +1,3 @@
## Unit of Work
Façam

3
docs/pt-BR/Validation.md

@ -0,0 +1,3 @@
## Validation
Façam

3
docs/pt-BR/Value-Objects.md

@ -0,0 +1,3 @@
## Value Objects
Façam

328
docs/pt-BR/docs-nav.json

@ -0,0 +1,328 @@
{
"items": [
{
"text": "Começando",
"items": [
{
"text": "De Modelo de Inicialização",
"items": [
{
"text": "Aplicativo com MVC (Razor Pages) UI",
"path": "Getting-Started-AspNetCore-MVC-Template.md"
},
{
"text": "Aplicativo com Angular UI",
"path": "Getting-Started-Angular-Template.md"
}
]
},
{
"text": "De Projetos Vazios",
"items": [
{
"text": "Com Aplicativo ASP.NET Core Web",
"path": "Getting-Started-AspNetCore-Application.md"
},
{
"text": "Com Aplicativo Console",
"path": "Getting-Started-Console-Application.md"
}
]
}
]
},
{
"text": "Tutoriais",
"items": [
{
"text": "Desenvolvimento de Aplicações",
"items": [
{
"text": "Com ASP.NET Core MVC UI",
"path": "Tutorials/AspNetCore-Mvc/Part-I.md"
},
{
"text": "Com Angular UI",
"path": "Tutorials/Angular/Part-I.md"
}
]
}
]
},
{
"text": "CLI",
"path": "CLI.md"
},
{
"text": "Fundamentos",
"items": [
{
"text": "Injeção de Dependência",
"path": "Dependency-Injection.md",
"items": [
{
"text": "Integração com Autofac",
"path": "Autofac-Integration.md"
}
]
},
{
"text": "Sistema de Arquivos Virtual",
"path": "Virtual-File-System.md"
},
{
"text": "Localização",
"path": "Localization.md"
},
{
"text": "Manipulação de Exceção",
"path": "Exception-Handling.md"
},
{
"text": "Validação"
},
{
"text": "Autorização"
},
{
"text": "Armazenamento em Cache"
},
{
"text": "Auditoria"
},
{
"text": "Gerenciamento de Configurações"
}
]
},
{
"text": "Eventos",
"items": [
{
"text": "Barramento de Eventos (local)"
},
{
"text": "Barramento de Eventos Distribuídos",
"items": [
{
"text": "Integração RabbitMQ"
}
]
}
]
},
{
"text": "Serviços",
"items": [
{
"text": "Serialização de Objetos"
},
{
"text": "Serialização JSON"
},
{
"text": "Emailing"
},
{
"text": "GUIDs"
},
{
"text": "Threading"
},
{
"text": "Timing"
}
]
},
{
"text": "Múltiplos Inquilinos",
"path": "Multi-Tenancy.md"
},
{
"text": "Desenvolvimento de Módulos",
"items": [
{
"text": "Fundamentos",
"path": "Module-Development-Basics.md"
},
{
"text": "Módulos de plug-in"
},
{
"text": "Melhores práticas",
"path": "Best-Practices/Index.md"
}
]
},
{
"text": "Design Orientado a Domínio",
"path": "Domain-Driven-Design.md",
"items": [
{
"text": "Camada de Domínio",
"items": [
{
"text": "Entidades & Raízes Agregadas",
"path": "Entities.md"
},
{
"text": "Value Objects"
},
{
"text": "Repositórios",
"path": "Repositories.md"
},
{
"text": "Serviços de Domínio"
},
{
"text": "Especificações"
}
]
},
{
"text": "Camada de Aplicação",
"items": [
{
"text": "Serviços de Aplicação",
"path": "Application-Services.md"
},
{
"text": "Objetos de Transferência de Dados"
},
{
"text": "Unidade de Trabalho"
}
]
}
]
},
{
"text": "ASP.NET Core",
"items": [
{
"text": "API",
"items": [
{
"text": "Controladores de API Automática",
"path": "AspNetCore/Auto-API-Controllers.md"
},
{
"text": "Clientes da API C # Dinâmica",
"path": "AspNetCore/Dynamic-CSharp-API-Clients.md"
}
]
},
{
"text": "Interface de Usuário",
"items": [
{
"text": "Gerenciamento de Pacotes do Lado do Cliente",
"path": "AspNetCore/Client-Side-Package-Management.md"
},
{
"text": "Compactação & Minificação",
"path": "AspNetCore/Bundling-Minification.md"
},
{
"text": "Tag Helpers",
"path": "AspNetCore/Tag-Helpers/Index.md"
},
{
"text": "Widgets",
"path": "AspNetCore/Widgets.md"
},
{
"text": "Theming",
"path": "AspNetCore/Theming.md"
}
]
}
]
},
{
"text": "Acesso de Dados",
"items": [
{
"text": "Integração do Entity Framework Core",
"path": "Entity-Framework-Core.md",
"items": [
{
"text": "Integração do PostgreSQL",
"path": "Best-Practices/PostgreSQL-Integration.md"
}
]
},
{
"text": "Integração do MongoDB",
"path": "MongoDB.md"
},
{
"text": "Integração do Dapper",
"path": "Dapper.md"
}
]
},
{
"text": "Background",
"items": [
{
"text": "Trabalhos em Segundo Plano",
"path": "Background-Jobs.md",
"items": [
{
"text": "Integração do Hangfire",
"path": "Background-Jobs-Hangfire.md"
},
{
"text": "Integração do RabbitMQ",
"path": "Background-Jobs-RabbitMq.md"
}
]
}
]
},
{
"text": "Modelos de Inicialização",
"path": "Startup-Templates/Index.md",
"items": [
{
"text": "Aplicativo",
"path": "Startup-Templates/Application.md"
},
{
"text": "Módulo",
"path": "Startup-Templates/Module.md"
}
]
},
{
"text": "Exemplos",
"items": [
{
"text": "Demonstração de Microsserviços",
"path": "Samples/Microservice-Demo.md"
}
]
},
{
"text": "Módulos de Aplicação",
"path": "Modules/Index.md"
},
{
"text": "Arquitetura de Microsserviços",
"path": "Microservice-Architecture.md"
},
{
"text": "Testando"
},
{
"text": "Compilações Noturnas",
"path": "Nightly-Builds.md"
},
{
"text": "Guia de Contribuição",
"path": "Contribution/Index.md"
}
]
}

BIN
docs/pt-BR/images/MonthlyProfitWidgetFiles.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
docs/pt-BR/images/bookstore-apis.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/pt-BR/images/bookstore-create-template.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
docs/pt-BR/images/bookstore-homepage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/pt-BR/images/bookstore-swagger-ui-host.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
docs/pt-BR/images/bookstore-user-management-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/pt-BR/images/bookstore-visual-studio-solution-for-spa.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
docs/pt-BR/images/bookstore-visual-studio-solution-tiered.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save