diff --git a/README.md b/README.md
index 95ff04736d..fc98373efd 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[](https://www.nuget.org/packages/Volo.Abp.Core)
[](https://docs.abp.io/en/abp/latest/Nightly-Builds)
-This project is the next generation of the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) web application framework. See [the announcement](https://abp.io/blog/abp/Abp-vNext-Announcement).
+This project is the next generation of the [ASP.NET Boilerplate](https://aspnetboilerplate.com/) web application framework. See [the announcement](https://blog.abp.io/abp/Abp-vNext-Announcement).
See the official [web site (abp.io)](https://abp.io/) for more information.
@@ -21,7 +21,7 @@ See the documentation.
#### Pre Requirements
-- Visual Studio 2019 16.1.0+
+- Visual Studio 2019 16.3.0+
#### Framework
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..a85f7d5bcc
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/pt-BR.json
@@ -0,0 +1,13 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ "Account": "Conta",
+ "Welcome": "Bem-vindo",
+ "UseOneOfTheFollowingLinksToContinue": "Use um dos seguintes links para continuar",
+ "FrameworkHomePage": "Página inicial do Framework",
+ "FrameworkDocumentation": " Documentação do Framework",
+ "OfficialBlog": "Blog oficial",
+ "CommercialHomePage": "Página inicial comercial",
+ "CommercialSupportWebSite": "Site de suporte comercial"
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..1dc69524e1
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/pt-BR.json
@@ -0,0 +1,60 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ "Permission:NpmPackages": "Pacotes NPM",
+ "Permission:NugetPackages": "Pacotes Nuget",
+ "Permission:Maintenance": "Manutenção",
+ "Permission:Maintain": "Manter",
+ "Permission:ClearCaches": "Limpar caches",
+ "Permission:Modules": "Módulos",
+ "Permission:Packages": "Pacotes",
+ "Permission:Edit": "Editar",
+ "Permission:Delete": "Excluir",
+ "Permission:Create": "Criar",
+ "Menu:Packages": "Pacotes",
+ "NpmPackageDeletionWarningMessage": "Este pacote NPM será excluído. Você confirma isso?",
+ "NugetPackageDeletionWarningMessage": "Este pacote Nuget será excluído. Você confirma isso?",
+ "ModuleDeletionWarningMessage": "Este módulo será excluído. Você confirma isso?",
+ "Name": "Nome",
+ "DisplayName": "Mostrar nome",
+ "ShortDescription": "Breve descrição",
+ "NameFilter": "Nome",
+ "CreationTime": "Hora da criação",
+ "IsPro": "É profissional",
+ "EfCoreConfigureMethodName": "Configurar nome do método",
+ "IsProFilter": "É profissional",
+ "ApplicationType": "Tipo de aplicativo",
+ "Target": "Objetivo",
+ "TargetFilter": "Objetivo",
+ "ModuleClass": "Classe do módulo",
+ "NugetPackageTarget.DomainShared": "Domínio compartilhado",
+ "NugetPackageTarget.Domain": "Domínio",
+ "NugetPackageTarget.Application": "Aplicativo",
+ "NugetPackageTarget.ApplicationContracts": "Contratos de aplicativos",
+ "NugetPackageTarget.HttpApi": "Http Api",
+ "NugetPackageTarget.HttpApiClient": "Cliente HTTP da API",
+ "NugetPackageTarget.Web": "Web",
+ "NugetPackageTarget.EntityFrameworkCore": "EntityFramework Core",
+ "NugetPackageTarget.MongoDB": "MongoDB",
+ "Edit": "Editar",
+ "Delete": "Excluir",
+ "Refresh": "Atualizar",
+ "NpmPackages": "Pacotes NPM",
+ "NugetPackages": "Pacotes Nuget",
+ "NpmPackageCount": "Contagem de pacotes NPM",
+ "NugetPackageCount": "Contagem de pacotes Nuget",
+ "Module": "Módulos",
+ "ModuleInfo": "Informações do módulo",
+ "CreateANpmPackage": "Criar um pacote NPM",
+ "CreateAModule": "Criar um módulo",
+ "CreateANugetPackage": "Criar um pacote Nuget",
+ "AddNew": "Adicionar novo",
+ "PackageAlreadyExist{0}": "\"{0}\" o pacote já foi adicionado.",
+ "ClearCache": "Limpar cache",
+ "SuccessfullyCleared": "Limpo com sucesso",
+ "Menu:NpmPackages": "Pacotes NPM",
+ "Menu:Modules": "Módulos",
+ "Menu:Maintenance": "Manutenção",
+ "Menu:NugetPackages": "Pacotes Nuget"
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..a95bb9a874
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json
@@ -0,0 +1,31 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ "Volo.AbpIo.Domain:010004": "Número máximo de membros atingido!",
+ "Volo.AbpIo.Domain:010005": "Número máximo de proprietários atingido!",
+ "Volo.AbpIo.Domain:010006": "Este usuário já é proprietário desta organização!",
+ "Volo.AbpIo.Domain:010007": "Este usuário já é desenvolvedor desta organização!",
+ "Volo.AbpIo.Domain:010008": "A contagem permitida de desenvolvedores não pode ser inferior à contagem atual de desenvolvedores!",
+ "Volo.AbpIo.Domain:010009": "A contagem permitida de desenvolvedores não pode ser inferior a 0!",
+ "Volo.AbpIo.Domain:010010": "A contagem máxima de endereços mac foi excedida!",
+ "Volo.AbpIo.Domain:010011": "A licença pessoal não pode ter mais de um desenvolvedor!",
+ "Volo.AbpIo.Domain:010012": "A licença não pode ser estendida um mês após a expiração da licença!",
+ "Volo.AbpIo.Domain:020001": "Não foi possível excluir este pacote NPM porque \"{NugetPackages}\" Os pacotes Nuget dependem deste pacote.",
+ "Volo.AbpIo.Domain:020002": "Não foi possível excluir este pacote NPM porque \"{Modules}\" Módulos estão usando este pacote.",
+ "Volo.AbpIo.Domain:020003": "Não foi possível excluir este pacote NPM porque \"{Modules}\" Módulos estão usando este pacote e \"{NugetPackages}\" Os pacotes Nuget dependem deste pacote.",
+ "Volo.AbpIo.Domain:020004": "Não foi possível excluir este pacote Nuget porque \"{Modules}\" Módulos estão usando este pacote.",
+ "WantToLearn?": "Quer aprender?",
+ "ReadyToGetStarted?": "Pronto para começar?",
+ "JoinOurCommunity": "Participe da nossa comunidade",
+ "GetStartedUpper": "INICIAR",
+ "ForkMeOnGitHub": "Bifurque-me no GitHub",
+ "Features": "Recursos",
+ "GetStarted": "Introdução",
+ "Documents": "Documentos",
+ "Community": "Comunidade",
+ "ContributionGuide": "Guia de contribuição",
+ "Blog": "Blog",
+ "Commercial": "Comercial",
+ "SeeDocuments": "Ver documentos"
+ }
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Blog/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Blog/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..2012b4c128
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Blog/Localization/Resources/pt-BR.json
@@ -0,0 +1,5 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
index 3785288f0b..d4eca0b7e6 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
+++ b/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}"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..e9133491f4
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json
@@ -0,0 +1,30 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ "OrganizationManagement": "Gerenciamento da organização",
+ "OrganizationList": "Lista de organização",
+ "Volo.AbpIo.Commercial:010003": "Você não é proprietário desta organização!",
+ "OrganizationNotFoundMessage": "Nenhuma organização encontrada!",
+ "DeveloperCount": "Número de desenvolvedores",
+ "Owners": "Proprietários",
+ "AddMember": "Adicionar membro",
+ "AddOwner": "Adicionar proprietário",
+ "AddDeveloper": "Adicionar desenvolvedor",
+ "UserName": "Nome de usuário",
+ "Name": "Nome",
+ "EmailAddress": "Endereço de email",
+ "Developers": "Desenvolvedores",
+ "LicenseType": "Tipo de licença",
+ "Manage": "Gerenciar",
+ "StartDate": "Data de início",
+ "EndDate": "Data final",
+ "Modules": "Módulos",
+ "LicenseExtendMessage": "A data de término da sua licença foi estendida para {0}",
+ "LicenseUpgradeMessage": "Sua licença foi atualizada para {0}",
+ "LicenseAddDeveloperMessage": "{0} desenvolvedores adicionados à sua licença",
+ "Volo.AbpIo.Commercial:010004": "Não foi possível encontrar o usuário especificado! O usuário já deve ter se registrado.",
+ "MyOrganizations": "Minhas organizações",
+ "ApiKey": "Chave da API",
+ "UserNameNotFound": "Não há usuário com nome de usuário {0}"
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
index fd25239044..77dab7302e 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
+++ b/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"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..2012b4c128
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/pt-BR.json
@@ -0,0 +1,5 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..2012b4c128
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/pt-BR.json
@@ -0,0 +1,5 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json
new file mode 100644
index 0000000000..382beec925
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json
@@ -0,0 +1,160 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ "GetStarted": "Introdução",
+ "Create": "Criar",
+ "NewProject": "Novo projeto",
+ "DirectDownload": "Download direto",
+ "ProjectName": "Nome do projeto",
+ "ProjectType": "Tipo de projeto",
+ "DatabaseProvider": "Provedor de banco de dados",
+ "NTier": "N-Tier",
+ "IncludeUserInterface": "Incluir interface do usuário",
+ "CreateNow": "Criar agora",
+ "TheStartupProject": "O projeto de inicialização",
+ "Tutorial": "Tutorial",
+ "UsingCLI": "Usando CLI",
+ "SeeDetails": "Ver detalhes",
+ "AbpShortDescription": "ABP é uma arquitetura completa e uma forte infraestrutura para criar aplicativos da web modernos! Segue as melhores práticas e convenções para fornecer uma sólida experiência de desenvolvimento.",
+ "SourceCodeUpper": "CÓDIGO FONTE",
+ "LatestReleaseLogs": "Últimos registros de lançamento",
+ "Infrastructure": "Infra-estrutura",
+ "Architecture": "Arquitetura",
+ "Modular": "Modular",
+ "DontRepeatYourself": "Não se repita",
+ "DeveloperFocused": "Desenvolvedor focado",
+ "FullStackApplicationInfrastructure": "Infraestrutura de aplicativos full stack.",
+ "DomainDrivenDesign": "Design Orientado a Domínio",
+ "DomainDrivenDesignExplanation": "Projetado e desenvolvido com base nos padrões e princípios DDD. Fornece um modelo em camadas para seu aplicativo.",
+ "Authorization": "Autorização",
+ "AuthorizationExplanation": "Autorização avançada com usuário, função e sistema de permissão refinado. Criada na biblioteca Microsoft Identity.",
+ "MultiTenancy": "Múltiplos inquilinos",
+ "MultiTenancyExplanation": "Aplicativos SaaS facilitados! Multilocação integrada do banco de dados à interface do usuário.",
+ "CrossCuttingConcerns": "Preocupações transversais",
+ "CrossCuttingConcernsExplanation": "Infraestrutura completa para autorização, validação, tratamento de exceções, armazenamento em cache, log de auditoria, gerenciamento de transações e assim por diante.",
+ "BuiltInBundlingMinification": "Pacote & Minificação Integrados",
+ "BuiltInBundlingMinificationExplanation": "Pare de usar ferramentas externas para empacotamento e minificação. O ABP oferece uma maneira mais simples, dinâmica, poderosa, modular e integrada!",
+ "VirtualFileSystem": "Sistema de arquivos virtual",
+ "VirtualFileSystemExplanation": "Incorpore visualizações, scripts, estilos, imagens ... aos pacotes/bibliotecas e reutilize-os em diferentes aplicativos.",
+ "Theming": "Theming",
+ "ThemingExplanation": "Use e personalize o tema da interface do usuário padrão baseado em bootstrap-based ou crie o seu próprio.",
+ "BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers & Dynamic Forms",
+ "BootstrapTagHelpersDynamicFormsExplanation": "Sistema de tarefas em segundo plano integrado que pode ser integrado ao Hangfire, RabbitMQ ou a qualquer ferramenta que você desejar.", //TODO explanation doesn't match.
+ "HTTPAPIsDynamicProxies": "APIs HTTP e proxies dinâmicos",
+ "HTTPAPIsDynamicProxiesExplanation": "Exponha automaticamente os serviços de aplicativo como APIs HTTP do estilo REST e consuma com proxies JavaScript & C # dinâmicos.",
+ "CompleteArchitectureInfo": "Arquitetura moderna para criar soluções de software sustentáveis.",
+ "DomainDrivenDesignBasedLayeringModelExplanation": "Ajuda você a implementar uma arquitetura em camadas baseada em DDD e a construir uma base de código sustentável.",
+ "DomainDrivenDesignBasedLayeringModelExplanationCont": "Fornece modelos de inicialização, abstrações, classes base, serviços, documentação e guias para ajudá-lo a desenvolver seu aplicativo com base nos padrões e princípios DDD.",
+ "MicroserviceCompatibleModelExplanation": "O framework principal e os módulos de pré-construção foram projetados para a arquitetura de microsserviço.",
+ "MicroserviceCompatibleModelExplanationCont": "Fornece infraestrutura, integrações, amostras e documentação para implementar soluções de microsserviço mais facilmente, enquanto isso não traga complexidade adicional se você quiser um aplicativo monolítico.",
+ "ModularInfo": "O ABP fornece um sistema completo de modularidade para permitir o desenvolvimento de módulos de aplicativos reutilizáveis.",
+ "PreBuiltModulesThemes": "Módulos pré-construídos & Temas",
+ "PreBuiltModulesThemesExplanation": "Módulos e temas de código aberto e comerciais estão prontos para uso em seu aplicativo de negócios.",
+ "NuGetNPMPackages": "Pacotes NuGet & NPM",
+ "NuGetNPMPackagesExplanation": "Distribuído como pacotes NuGet & NPM. Fácil de instalar e atualizar.",
+ "ExtensibleReplaceable": "Extensível/Substituível",
+ "ExtensibleReplaceableExplanation": "Todos os serviços e módulos são projetados para extensibilidade. Você pode substituir serviços, páginas, estilos, componentes...",
+ "CrossCuttingConcernsExplanation2": "Mantenha seu código mais limpo e concentre-se em seu próprio código comercial.",
+ "CrossCuttingConcernsExplanation3": "Não perca tempo para implementar requisitos de aplicativos comuns repetidamente.",
+ "AuthenticationAuthorization": "Autenticação & Autorização",
+ "ExceptionHandling": "Manipulação de exceção",
+ "Validation": "Validação",
+ "DatabaseConnection": "Conexão com o Banco de Dados",
+ "TransactionManagement": "Gerenciamento de transações",
+ "AuditLogging": "Log de auditoria",
+ "Caching": "Armazenamento em cache",
+ "Multitenancy": "Múltiplos inquilinos",
+ "DataFiltering": "Filtragem de dados",
+ "ConventionOverConfiguration": "Convenção sobre configuração",
+ "ConventionOverConfigurationExplanation": "O ABP implementa convenções comuns de aplicativos por padrão com uma configuração mínima ou zero.",
+ "ConventionOverConfigurationExplanationList1": "Registra automaticamente serviços conhecidos na injeção de dependência.",
+ "ConventionOverConfigurationExplanationList2": "Expõe os serviços de aplicativos como APIs HTTP, nomeando convenções.",
+ "ConventionOverConfigurationExplanationList3": "Cria proxies de clientes HTTP dinâmicos para C # e JavaScript.",
+ "ConventionOverConfigurationExplanationList4": "Fornece repositórios padrão para suas entidades.",
+ "ConventionOverConfigurationExplanationList5": "Gerencia a unidade de trabalho por solicitação da Web ou método de serviço de aplicativo.",
+ "ConventionOverConfigurationExplanationList6": "Publica, cria, atualiza e exclui eventos para suas entidades.",
+ "BaseClasses": "Classes base",
+ "BaseClassesExplanation": "Classes base pré-criadas para padrões de aplicativos comuns.",
+ "DeveloperFocusedExplanation": "O ABP é para desenvolvedores.",
+ "DeveloperFocusedExplanationCont": "Tem como objetivo simplificar o desenvolvimento diário de seu software, sem restringir o trabalho de baixo nível quando necessário.",
+ "SeeAllFeatures": "Veja todos os recursos",
+ "CLI_CommandLineInterface": "CLI (Command Line Interface)",
+ "CLI_CommandLineInterfaceExplanation": "A CLI é automatizada para criar novos projetos e adicionar módulos ao seu aplicativo.",
+ "StartupTemplates": "Modelos de inicialização",
+ "StartupTemplatesExplanation": "Vários modelos de inicialização fornecem uma solução totalmente configurada para iniciar rapidamente seu desenvolvimento.",
+ "BasedOnFamiliarTools": "Baseado em ferramentas familiares",
+ "BasedOnFamiliarToolsExplanation": "Construído e integrado a ferramentas populares que você já conhece. Baixa curva de aprendizado, fácil adaptação, desenvolvimento confortável.",
+ "ORMIndependent": "ORM Independente",
+ "ORMIndependentExplanation": "O framework principal é independente do ORM/banco de dados e pode funcionar com qualquer fonte de dados. Os provedores Entity Framework Core e MongoDB já estão disponíveis.",
+ "Features": "Recursos",
+ "ABPCLI": "ABP CLI",
+ "Modularity": "Modularidade",
+ "BootstrapTagHelpers": "Bootstrap Tag Helpers",
+ "DynamicForms": "Formulários dinâmicos",
+ "BundlingMinification": "Empacotamento e Minificação",
+ "BackgroundJobs": "Trabalhos em segundo plano",
+ "DDDInfrastructure": "Infraestrutura DDD",
+ "DomainDrivenDesignInfrastructure": "Infraestrutura de Design Orientada a Domínio",
+ "AutoRESTAPIs": "APIs REST automáticas",
+ "DynamicClientProxies": "Proxies de cliente dinâmicos",
+ "DistributedEventBus": "Barramento de Eventos Distribuídos",
+ "DistributedEventBusWithRabbitMQIntegration": "Barramento de Eventos Distribuídos com Integração RabbitMQ",
+ "TestInfrastructure": "Infraestrutura de Teste",
+ "AuditLogging": "Log de auditoria",
+ "AuditLoggingEntityHistories": "Log de auditoria e históricos de entidades",
+ "ObjectToObjectMapping": "Objeto para Mapeamento de Objetos",
+ "EmailSMSAbstractions": "Abstrações de E-mail e SMS",
+ "EmailSMSAbstractionsWithTemplatingSupport": "Abstrações de e-mail e SMS com suporte a modelos",
+ "Localization": "Localização",
+ "SettingManagement": "Gerenciamento de configurações",
+ "ExtensionMethods": "Métodos de extensão",
+ "ExtensionMethodsHelpers": "Métodos de extensão & Helpers",
+ "AspectOrientedProgramming": "Programação Orientada a Aspectos",
+ "DependencyInjection": "Injeção de dependência",
+ "DependencyInjectionByConventions": "Injeção de dependência por convenções",
+ "ABPCLIExplanation": "O ABP CLI (Command Line Interface) é uma ferramenta de linha de comando para executar algumas operações comuns em soluções baseadas em ABP.",
+ "ModularityExplanation": "O ABP fornece uma infraestrutura completa para criar seus próprios módulos de aplicativos, que podem ter entidades, serviços, integração de banco de dados, APIs, componentes de interface do usuário e assim por diante ...", //TODO: strong "your own application modules",-
+ "MultiTenancyExplanation": "ABP framework não apenas suporta o desenvolvimento de aplicativos com vários inquilinos, mas também faz com que seu código desconheça a multilocação.",
+ "MultiTenancyExplanation2": "Pode determinar automaticamente o inquilino atual, isolar os dados de inquilinos diferentes um do outro.",
+ "MultiTenancyExplanation3": "Suporta abordagens de banco de dados único, banco de dados por inquilino e híbrido.",
+ "MultiTenancyExplanation4": "Você se concentra no seu código comercial e deixa o framework lidar com a multilocação em seu nome.",
+ "BootstrapTagHelpersExplanation": "Em vez de escrever manualmente os detalhes repetidos dos componentes do bootstrap, use os tag helpers da ABP para simplificá-lo e tirar proveito do intellisense. Você pode definitivamente usar o Bootstrap sempre que precisar.",
+ "DynamicFormsExplanation": "Formulário dinâmico e entrada de tag helpers pode criar o formulário completo a partir de uma classe C# como modelo.",
+ "AuthenticationAuthorizationExplanation": "Opções avançadas de autenticação e autorização integradas ao ASP.NET Core Identity & IdentityServer4. Fornece um sistema de permissões extensível e detalhado.",
+ "CrossCuttingConcernsExplanation": "Não se repita para implementar todas essas coisas comuns repetidamente. Concentre-se no seu código comercial e permita que a ABP os automatize por convenções.",
+ "DatabaseConnectionTransactionManagement": "Gerenciamento de conexão e transação de banco de dados",
+ "CorrelationIdTracking": "Rastreamento de ID de correlação",
+ "BundlingMinificationExplanation": "A ABP oferece um sistema de empacotamento e minificação simples, dinâmico, poderoso, modular e embutido.",
+ "VirtualFileSystemnExplanation": "O Sistema de Arquivos Virtual possibilita gerenciar arquivos que não existem fisicamente no sistema de arquivos (disco). É usado principalmente para incorporar arquivos (js, css, image, cshtml ...) em assemblies e usar como arquivos físicos em tempo de execução.",
+ "ThemingExplanation": "O sistema Theming permite o desenvolvimento independente do tema do aplicativo e dos módulos, definindo um conjunto de bibliotecas e layouts básicos comuns, com base na estrutura mais recente do Bootstrap.",
+ "DomainDrivenDesignInfrastructureExplanation": "Uma infraestrutura completa para criar aplicativos em camadas com base nos padrões e princípios de Design Orientado a Domínio;",
+ "Specification": "Especificação",
+ "Repository": "Repositório",
+ "DomainService": "Serviço de Domínio",
+ "ValueObject": "Value Object",
+ "ApplicationService": "Serviço de Aplicativo",
+ "DataTransferObject": "Objeto de transferência de dados",
+ "AggregateRootEntity": "Raiz agregada, entidade",
+ "AutoRESTAPIsExplanation": "O ABP pode configurar automaticamente seus serviços de aplicativo como controladores de API por convenção.",
+ "DynamicClientProxiesExplanation": "Consumir facilmente suas APIs de JavaScript e C # clientes.",
+ "DistributedEventBusWithRabbitMQIntegrationExplanation": "Publique e consuma facilmente eventos distribuídos usando o Barramento de Eventos Distribuídos interno com a integração RabbitMQ disponível.",
+ "TestInfrastructureExplanation": "A estrutura foi desenvolvida para testes de unidade e integração. Fornece classes básicas para facilitar. Os modelos de inicialização são pré-configurados para teste.",
+ "AuditLoggingEntityHistoriesExplanation": "Registro de auditoria interno para aplicativos críticos para os negócios. Solicitação, serviço, log de auditoria no nível do método e histórico de entidades com detalhes no nível da propriedade.",
+ "EmailSMSAbstractionsWithTemplatingSupportExplanation": "As abstrações IEmailSender e ISmsSender dissociam sua lógica de aplicativo da infraestrutura. O sistema avançado de modelo de email permite criar e localizar modelos de email e usá-lo facilmente sempre que necessário.",
+ "LocalizationExplanation": "O sistema de localização permite criar recursos em arquivos JSON simples e usá-los para localizar sua interface do usuário. Ele suporta cenários avançados como herança, extensões e integração de JavaScript, enquanto é totalmente compatível com o sistema de localização do AspNet Core.",
+ "SettingManagementExplanation": "Defina as configurações do seu aplicativo e obtenha valores no tempo de execução com base na configuração atual, inquilino e usuário.",
+ "ExtensionMethodsHelpersExplanation": "Não se repita, mesmo em partes triviais do código. Extensões e helpers para tipos padrão tornam seu código muito mais limpo e fácil de escrever.",
+ "AspectOrientedProgrammingExplanation": "Fornece uma infraestrutura confortável para criar proxies dinâmicos e implementar a Programação Orientada a Aspectos. Intercepte qualquer classe e execute seu código antes e depois de cada execução de método.",
+ "DependencyInjectionByConventionsExplanation": "Não há necessidade de registrar suas classes na injeção de dependência manualmente. Registra automaticamente tipos de serviço comuns por convenção. Para outros tipos de serviços, você pode usar interfaces e atributos para facilitar e colocar no local.",
+ "DataFilteringExplanation": "Defina e use filtros de dados que serão aplicados automaticamente quando você consultar entidades do banco de dados. Os filtros Soft Delete e MultiTenant são fornecidos imediatamente quando você implementa interfaces simples.",
+ "PublishEvents": "Publicar eventos",
+ "HandleEvents": "Manipular Eventos",
+ "AndMore": "e mais...",
+ "Code": "Código",
+ "Result": "Resultado",
+ "SeeTheDocumentForMoreInformation": "Consulte o {0} documento para obter mais informações",
+ "IndexPageHeroSection": "código abertoAplicativo da Web Framework para o ASP.NET Core",
+ "UiFramework": "UI Framework",
+ "EmailAddress": "Endereço de email"
+ }
+}
\ No newline at end of file
diff --git a/common.props b/common.props
index e97735b0ac..1b69d58ed0 100644
--- a/common.props
+++ b/common.props
@@ -1,7 +1,7 @@
latest
- 0.19.0
+ 0.22.0$(NoWarn);CS1591https://abp.io/assets/abp_nupkg.pnghttps://abp.io
diff --git a/common.test.props b/common.test.props
new file mode 100644
index 0000000000..e90103e606
--- /dev/null
+++ b/common.test.props
@@ -0,0 +1,10 @@
+
+
+ latest
+ $(NoWarn);CS1591
+ true
+ false
+ false
+ false
+
+
\ No newline at end of file
diff --git a/docs/cs/Best-Practices/PostgreSQL-Integration.md b/docs/cs/Best-Practices/PostgreSQL-Integration.md
new file mode 100644
index 0000000000..6bf8224f1e
--- /dev/null
+++ b/docs/cs/Best-Practices/PostgreSQL-Integration.md
@@ -0,0 +1,35 @@
+## Entity Framework Core PostgreSQL integrace
+
+> Podívejte se na [Entity Framework Core integrační dokument](../Entity-Framework-Core.md) pro základy integrace EF Core.
+
+### Aktualizace projektu EntityFrameworkCore
+
+- V projektu `Acme.BookStore.EntityFrameworkCore` nahraďte balík `Volo.Abp.EntityFrameworkCore.SqlServer` za `Volo.Abp.EntityFrameworkCore.PostgreSql`
+- Aktualizace pro použití PostgreSQL v `BookStoreEntityFrameworkCoreModule`
+ - Nahraďte `AbpEntityFrameworkCoreSqlServerModule` za `AbpEntityFrameworkCorePostgreSqlModule`
+ - Nahraďte `options.UseSqlServer()` za `options.UsePostgreSql()`
+- V jiných projektech aktualizujte PostgreSQL connection string v nezbytných `appsettings.json` souborech
+
+#### Odstranění stávajících migrací
+
+Smažte všechny stavající migrační soubory (včetně `DbContextModelSnapshot`)
+
+
+
+#### Znovu vygenerujte počáteční migraci & aktualizujte databázi
+
+Nastavte správný spouštěcí projekt (obvykle web projekt),
+Otevřete **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console), zvolte `Acme.BookStore.EntityFrameworkCore.DbMigrations` jako **Default project** a proveďte následující příkaz:
+
+Proveďte příkaz `Add-Migration`:
+````
+PM> Add-Migration Initial
+````
+
+Poté proveďte příkaz `Update-Database` k aktualizaci schématu databáze:
+
+````
+PM> Update-Database
+````
+
+
diff --git a/docs/cs/Best-Practices/images/postgresql-delete-initial-migrations.png b/docs/cs/Best-Practices/images/postgresql-delete-initial-migrations.png
new file mode 100644
index 0000000000..39d9e6dedf
Binary files /dev/null and b/docs/cs/Best-Practices/images/postgresql-delete-initial-migrations.png differ
diff --git a/docs/cs/Best-Practices/images/postgresql-update-database.png b/docs/cs/Best-Practices/images/postgresql-update-database.png
new file mode 100644
index 0000000000..02b61ef6a3
Binary files /dev/null and b/docs/cs/Best-Practices/images/postgresql-update-database.png differ
diff --git a/docs/cs/Dapper.md b/docs/cs/Dapper.md
new file mode 100644
index 0000000000..94e40347f0
--- /dev/null
+++ b/docs/cs/Dapper.md
@@ -0,0 +1,61 @@
+# Dapper integrace
+
+Jelikož myšlenka Dapper je taková, že sql příkaz má přednost, tak hlavně poskytuje metody rozšíření pro `IDbConnection` rozhraní.
+
+Abp nezapouzdřuje přílíš mnoho funkcí pro Dapper. Abp Dapper poskytuje základní třídu `DapperRepository` založenou na Abp EntityFrameworkCore, který poskytuje vlastnosti `IDbConnection` a `IDbTransaction` vyžadované v Dapper.
+
+Tyto dvě vlastnosti fungují dobře s [jednotkou práce](Unit-Of-Work.md).
+
+## Instalace
+
+Nainstalujte a nakonfigurujte EF Core podle [EF Core integrační dokumentace](Entity-Framework-Core.md).
+
+`Volo.Abp.Dapper` je hlavní NuGet balík pro Dapper integraci. Nainstalujte jej proto do vašeho projektu (pro strukturovanou aplikaci do datové/infrastrukturní vrstvy):
+
+```shell
+Install-Package Volo.Abp.Dapper
+```
+
+Poté přidejte závislost na `AbpDapperModule` modulu (atribut `DependsOn`) do Vašeho [modulu](Module-Development-Basics.md):
+
+````C#
+using Volo.Abp.Dapper;
+using Volo.Abp.Modularity;
+
+namespace MyCompany.MyProject
+{
+ [DependsOn(typeof(AbpDapperModule))]
+ public class MyModule : AbpModule
+ {
+ //...
+ }
+}
+````
+
+## Implementace Dapper repozitáře
+
+Následující kód implementuje repozitář `Person`, který vyžaduje `DbContext` z EF Core (MyAppDbContext). Můžete vložit `PersonDapperRepository` k volání jeho metod.
+
+`DbConnection` a `DbTransaction` jsou ze základní třídy `DapperRepository`.
+
+```C#
+public class PersonDapperRepository : DapperRepository, ITransientDependency
+{
+ public PersonDapperRepository(IDbContextProvider dbContextProvider)
+ : base(dbContextProvider)
+ {
+ }
+
+ public virtual async Task> GetAllPersonNames()
+ {
+ return (await DbConnection.QueryAsync("select Name from People", transaction: DbTransaction))
+ .ToList();
+ }
+
+ public virtual async Task UpdatePersonNames(string name)
+ {
+ return await DbConnection.ExecuteAsync("update People set Name = @NewName", new { NewName = name },
+ DbTransaction);
+ }
+}
+```
diff --git a/docs/cs/Getting-Started-Angular-Template.md b/docs/cs/Getting-Started-Angular-Template.md
new file mode 100644
index 0000000000..6accc637e8
--- /dev/null
+++ b/docs/cs/Getting-Started-Angular-Template.md
@@ -0,0 +1,126 @@
+## Začínáme s Angular aplikační šablonou
+
+Tento tutoriál vysvětluje, jak vytvořit novou Angular aplikaci pomocí spouštěcí šablony, jak ji nakonfigurovat a spustit.
+
+### Tvorba nového projektu
+
+Tento tutorial používá k vytvoření nového projektu **ABP CLI**. Podívejte se na stránku [začínáme](https://abp.io/get-started) pro více možností.
+
+Pokud jste tak dosud neučinili, nainstalujte ABP CLI pomocí okna příkazového řádku:
+
+````bash
+dotnet tool install -g Volo.Abp.Cli
+````
+
+Použíjte příkaz `abp new` v prázdné složce k vytvoření Vašeho projektu:
+
+````bash
+abp new Acme.BookStore -u angular
+````
+
+> Můžete použít různé úrovně jmenných prostorů; např. BookStore, Acme.BookStore nebo Acme.Retail.BookStore.
+
+`-u angular` volba specifikuje Angular jako UI framework. Výchozí poskytovatel databáze je EF Core. Podívejte se na [CLI dokumentaci](CLI.md) pro všechny dostupné možnosti.
+
+#### Předběžné požadavky
+
+Vytvořené řešení vyžaduje;
+
+* [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/)
+* [.NET Core 2.2+](https://www.microsoft.com/net/download/dotnet-core/)
+* [Node v10.16+](https://nodejs.org)
+* [Yarn v1.17+](https://yarnpkg.com/)
+
+### Struktura řešení
+
+Otevřete řešení ve **Visual Studio**:
+
+
+
+Řešení má vrstvenou strukturu (založenou na [domain driven designu](Domain-Driven-Design.md)) a obsahuje projekty testů jednotek a integrace správně nakonfigurované pro práci s **EF Core** & **SQLite in-memory** databází.
+
+> Podívejte se na [dokument šablony aplikace](Startup-Templates/Application.md) k detailnímu pochopení struktury řešení.
+
+### Databázový connection string
+
+Zkontrolujte **connection string** v souboru `appsettings.json` u projektu `.HttpApi.Host`:
+
+````json
+{
+ "ConnectionStrings": {
+ "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True"
+ }
+}
+````
+
+Řešení je nakonfigurováno pro použití **Entity Framework Core** s **MS SQL Server**. EF Core podporuje [různé](https://docs.microsoft.com/en-us/ef/core/providers/) poskytovatele databáze, takže pokud chcete můžete použít jiný DBMS. V případě potřeby změňte connection string.
+
+### Tvorba databáze & aplikace migrací databáze
+
+K vytvoření databáze máte dvě možnosti.
+
+#### Použití aplikace DbMigrator
+
+Řešení obsahuje konzolovou aplikaci (v tomto příkladu nazvanou `Acme.BookStore.DbMigrator`), která dokáže vytvořit databázi, aplikovat migrace a vložit počáteční data. Ta je užitečná jak pro vývojové tak pro produkční prostředí.
+
+> `.DbMigrator` má vlastní `appsettings.json`. Pokud jste změnili connection string výše, měli byste změnit i tento.
+
+Klikněte pravým na projekt `.DbMigrator` zvolte **Set as StartUp Project**:
+
+
+
+Zmáčkněte F5 (nebo Ctrl+F5) ke spuštění aplikace. Výstup by měl být podobný vyobrazení níže:
+
+
+
+#### Použití příkazu EF Core Update-Database
+
+Ef Core máš příkaz `Update-Database`, který v případě potřeby vytvoří databázi a aplikuje čekající migrace. Klikněte pravým na projekt `.Web` a zvolte **Set as StartUp Project**:
+
+
+
+Otevřete **Package Manager Console**, zvolte `.EntityFrameworkCore.DbMigrations` jako **Default Project** a proveďte příkaz `Update-Database`:
+
+
+
+Tímto vytvoříte novou databáze podle nakonfigurovaného connection string.
+
+> Je doporučeno užití nástroje `.DbMigrator`, protože zároveň vloží i počáteční data ke správnému běhu webové aplikace.
+
+### Spuštění aplikace
+
+#### Spuštění API Host (na straně serveru)
+
+Ujistěte se že je projekt `.HttpApi.Host` nastaven jako startovací a spusťte aplikaci což otevře Swagger UI:
+
+
+
+Tady můžete vidět API aplikace a zároveň je i otestovat. Získejte [více informací](https://swagger.io/tools/swagger-ui/) o Swagger UI.
+
+##### Autorizace pro Swagger UI
+
+Vetšina API aplikace vyžaduje autentizaci & autorizaci. Pokud chcete otestovat autorizované API, manuálně přejděte na stránku `/Account/Login`, vložte `admin` jako uživatelské jméno a `1q2w3E*` jako heslo k příhlášení do aplikace. Poté budete moci provádět autorizované požadavky API.
+
+#### Spuštění Angular aplikace (na straně klienta)
+
+Přejděte do složky `angular`, otevřete terminál příkazového řádku, proveďte příkaz `yarn` (doporučujeme používat správce balíků [yarn](https://yarnpkg.com), npm install bude v mnoha případech také fungovat):
+
+````bash
+yarn
+````
+
+Jakmile jsou načteny všechny node moduly, proveďte příkaz `yarn start` nebo `npm start`:
+
+````bash
+yarn start
+````
+
+Otevřete Váš oblíbený prohlížeč a přejděte na adresu `localhost:4200`. Počáteční uživatelské jméno je `admin` a heslo `1q2w3E*`.
+
+Startovací šablona obsahuje moduly **správa identit** a **správa tenantů**. Jakmile se přihlásíte, zprístupní se administrační menu kde můžete spravovat **tenanty**, **role**, **uživatele** a jejich **oprávnění**.
+
+> Doporučujeme [Visual Studio Code](https://code.visualstudio.com/) jako editor pro Angular projekt, ale klidně použijte Váš oblíbený editor.
+
+### Co dále?
+
+* [Tutoriál vývoje aplikace](Tutorials/Angular/Part-I.md)
diff --git a/docs/cs/docs-nav.json b/docs/cs/docs-nav.json
index 8560190492..91badc73e9 100644
--- a/docs/cs/docs-nav.json
+++ b/docs/cs/docs-nav.json
@@ -202,7 +202,7 @@
"items": [
{
"text": "API",
- "items": [
+ "items": [
{
"text": "Automatické API řadiče",
"path": "AspNetCore/Auto-API-Controllers.md"
@@ -245,11 +245,21 @@
"items": [
{
"text": "Entity Framework Core integrace",
- "path": "Entity-Framework-Core.md"
+ "path": "Entity-Framework-Core.md",
+ "items": [
+ {
+ "text": "PostgreSQL integrace",
+ "path": "Best-Practices/PostgreSQL-Integration.md"
+ }
+ ]
},
{
"text": "MongoDB integrace",
"path": "MongoDB.md"
+ },
+ {
+ "text": "Dapper integrace",
+ "path": "Dapper.md"
}
]
},
diff --git a/docs/docs-langs.json b/docs/docs-langs.json
index d4ee0190d2..a73882bd51 100644
--- a/docs/docs-langs.json
+++ b/docs/docs-langs.json
@@ -4,6 +4,11 @@
"DisplayName" : "English",
"Code" : "en",
"IsDefault": true
+ },
+ {
+ "DisplayName" : "Português",
+ "Code" : "pt-BR",
+ "IsDefault": false
},
{
"DisplayName" : "简体中文",
diff --git a/docs/en/Blog-Posts/2019-09-25 v0_21_Release/Post.md b/docs/en/Blog-Posts/2019-09-25 v0_21_Release/Post.md
new file mode 100644
index 0000000000..d44ab5d7df
--- /dev/null
+++ b/docs/en/Blog-Posts/2019-09-25 v0_21_Release/Post.md
@@ -0,0 +1,21 @@
+# ABP v0.21 Has Been Released based on the ASP.NET Core 3.0
+
+Just one hour after Microsoft released it, ABP v0.21 [has been released](https://twitter.com/abpframework/status/1176185493119258624) based on the ASP.NET Core 3.0.
+
+v0.21 has no new feature. It just upgrades to the stable ASP.NET Core 3.0. Check [v0.20 release notes](https://github.com/abpframework/abp/releases/tag/0.20.0) for new features, enhancements and bug fixes.
+
+## About v1.0
+
+ABP framework is getting closer to v1.0. We intent to release it in the middle of this October. In this time, we will test and document more.
+
+## .NET Conf 2019
+
+Microsoft has lunched ASP.NET Core 3.0 in the .NET Conf 2019, a 3-days virtual conference. ABP's lead developer [Halil ibrahim Kalkan](https://twitter.com/hibrahimkalkan) has also talked in the conference to introduce the ABP framework. It was great to be a part of this important event.
+
+## Techorama Netherlands 2019
+
+[Techorama NL](https://techorama.nl/) is one of the biggest conferences in Europe. This year, Volosoft is a sponsor of the conference and will have a booth to talk to software developers about the ABP framework and software development. Our booth wall will look like shown below:
+
+
+
+If you are in the conference, come to out booth to talk about the ABP framework. We will also have nice swags for you :)
\ No newline at end of file
diff --git a/docs/en/Blog-Posts/2019-09-25 v0_21_Release/volosoft-booth.png b/docs/en/Blog-Posts/2019-09-25 v0_21_Release/volosoft-booth.png
new file mode 100644
index 0000000000..3dca4409e4
Binary files /dev/null and b/docs/en/Blog-Posts/2019-09-25 v0_21_Release/volosoft-booth.png differ
diff --git a/docs/en/Getting-Started-Angular-Template.md b/docs/en/Getting-Started-Angular-Template.md
index 1bd605cd65..31186eaa35 100644
--- a/docs/en/Getting-Started-Angular-Template.md
+++ b/docs/en/Getting-Started-Angular-Template.md
@@ -85,13 +85,13 @@ Open the **Package Manager Console**, select `.EntityFrameworkCore.DbMigrations`
This will create a new database based on the configured connection string.
-> Using the `.Migrator` tool is the suggested way, because it also seeds the initial data to be able to properly run the web application.
+> Using the `.DbMigrator` tool is the suggested way, because it also seeds the initial data to be able to properly run the web application.
### Running the Application
#### Run the API Host (Server Side)
-Ensure that the `.HttpApi.Host` project is the startup project and un the application which will open a Swagger UI:
+Ensure that the `.HttpApi.Host` project is the startup project and run the application which will open a Swagger UI:

diff --git a/docs/en/Modules/Index.md b/docs/en/Modules/Index.md
index 2771c9a8a9..662ecf30a6 100644
--- a/docs/en/Modules/Index.md
+++ b/docs/en/Modules/Index.md
@@ -15,7 +15,7 @@ There are some **free and open source** application modules developed and mainta
* **Audit Logging**: Used to persist audit logs to a database.
* **Background Jobs**: Used to persist background jobs when using default background job manager.
* **Blogging**: Used to create fancy blogs. ABP's [own blog](https://abp.io/blog/abp/) already using this module.
-* [**Docs**](Docs.md): Used to create technical documentation pages. ABP's [own documentation](https://abp.io/documents/) already using this module.
+* [**Docs**](Docs.md): Used to create technical documentation pages. ABP's [own documentation](https://docs.abp.io) already using this module.
* **Identity**: Used to manage roles, users and their permissions.
* **Identity Server**: Integrates to IdentityServer4.
* **Permission Management**: Used to persist permissions.
@@ -23,4 +23,4 @@ There are some **free and open source** application modules developed and mainta
* **Tenant Management**: Used to manage tenants for a [multi-tenant](../Multi-Tenancy.md) application.
* **Users**: Used to abstract users, so other modules can depend on this instead of the Identity module.
-Documenting the modules is in the progress. See [this repository](https://github.com/abpframework/abp/tree/master/modules) for source code of all modules.
\ No newline at end of file
+Documenting the modules is in the progress. See [this repository](https://github.com/abpframework/abp/tree/master/modules) for source code of all modules.
diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md
index f5510a82db..0ad3c66b26 100644
--- a/docs/en/Multi-Tenancy.md
+++ b/docs/en/Multi-Tenancy.md
@@ -114,7 +114,7 @@ namespace MyCompany.MyProject
{
Configure(options =>
{
- options.TenantResolvers.Add(new MyCustomTenantResolver());
+ options.TenantResolvers.Add(new MyCustomTenantResolveContributor());
});
//...
@@ -123,14 +123,14 @@ namespace MyCompany.MyProject
}
````
-MyCustomTenantResolver must implement **ITenantResolver** as shown below:
+`MyCustomTenantResolveContributor` must implement **ITenantResolveContributor** as shown below:
````C#
using Volo.Abp.MultiTenancy;
namespace MyCompany.MyProject
{
- public class MyCustomTenantResolver : ITenantResolver
+ public class MyCustomTenantResolveContributor : ITenantResolveContributor
{
public void Resolve(ITenantResolveContext context)
{
diff --git a/docs/en/Startup-Templates/Module.md b/docs/en/Startup-Templates/Module.md
index fa425c67e2..2b95e49a56 100644
--- a/docs/en/Startup-Templates/Module.md
+++ b/docs/en/Startup-Templates/Module.md
@@ -25,7 +25,7 @@ abp new Acme.IssueManagement -t module
The template comes with an MVC UI by default. You can use `--no-ui` option to not include the UI layer.
````bash
-abp new Acme.IssueManagement -t mvc-module --no-ui
+abp new Acme.IssueManagement -t module --no-ui
````
## Solution Structure
diff --git a/docs/es/Index.md b/docs/es/Index.md
new file mode 100644
index 0000000000..772a0afc13
--- /dev/null
+++ b/docs/es/Index.md
@@ -0,0 +1,31 @@
+# Documentación de ABP
+
+ABP es un **marco de desarrollo de código abierto** enfocado en el desarrollo de aplicaciones web basadas en ASP.NET Core, pero tambien soporta el desarrollo de otro tipo de aplicaciones.
+
+Explora el menú de navegación de la izquierda para profundizar en la documentación.
+
+## Estado del proyecto
+
+ABP es la **próxima generación** del marco de desarrollo de código abierto [ASP.NET Boilerplate](https://aspnetboilerplate.com/). Actualmente se encuentra en una fase preliminar y no está listo para su uso en producción. La documentación todavía está en progreso y se encuentra lejos de estar completa.
+
+Para aplicaciones en fase de producción o que lo vayan a estar en el corto plazo, se sugiere usar el marco de desarrollo [ASP.NET Boilerplate](https://aspnetboilerplate.com/) el cual tiene un completo conjunto de funciones, es maduro, mantenido y actualizado activamente.
+
+## Primeros pasos
+
+La manera más facil para iniciar un proyecto con ABP es usar las plantillas de inicio:
+
+* [Plantilla ASP.NET Core MVC (Razor Pages) UI](Getting-Started-AspNetCore-MVC-Template.md)
+* [Plantilla Angular UI](Getting-Started-Angular-Template.md)
+
+Si quieres iniciar desde cero (con un proyecto vacío), entonces instala manualmente el marco de desarrollo ABP y usa los siguientes tutoriales:
+
+* [Aplicación de Consola](Getting-Started-Console-Application.md)
+* [Aplicación web con ASP.NET Core](Getting-Started-AspNetCore-Application.md)
+
+## Código fuente
+
+ABP está hospedado en GitHub. Mira el [código fuente](https://github.com/abpframework/abp).
+
+## ¿Quieres contribuir?
+
+ABP es un proyecto de código abierto impulsado por la comunidad. Mira la [guía de contribución](Contribution/Index.md) si quieres formar parte de este proyecto.
\ No newline at end of file
diff --git a/docs/pt-BR/Aspect-Oriented-Programming.md b/docs/pt-BR/Aspect-Oriented-Programming.md
new file mode 100644
index 0000000000..bfc7b0f705
--- /dev/null
+++ b/docs/pt-BR/Aspect-Oriented-Programming.md
@@ -0,0 +1,3 @@
+## Dynamic Proxying / Interceptors
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Audit-Logging.md b/docs/pt-BR/Audit-Logging.md
new file mode 100644
index 0000000000..a714eebf14
--- /dev/null
+++ b/docs/pt-BR/Audit-Logging.md
@@ -0,0 +1,3 @@
+# Audit Logging
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Authorization.md b/docs/pt-BR/Authorization.md
new file mode 100644
index 0000000000..941666a9bf
--- /dev/null
+++ b/docs/pt-BR/Authorization.md
@@ -0,0 +1,3 @@
+## Authorization
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/AutoMapper-Integration.md b/docs/pt-BR/AutoMapper-Integration.md
new file mode 100644
index 0000000000..24dd8ebfc4
--- /dev/null
+++ b/docs/pt-BR/AutoMapper-Integration.md
@@ -0,0 +1,3 @@
+## AutoMapper Integration
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Background-Jobs-Hangfire.md b/docs/pt-BR/Background-Jobs-Hangfire.md
new file mode 100644
index 0000000000..66e6944e88
--- /dev/null
+++ b/docs/pt-BR/Background-Jobs-Hangfire.md
@@ -0,0 +1,3 @@
+# Hangfire Background Job Manager
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Background-Jobs-RabbitMq.md b/docs/pt-BR/Background-Jobs-RabbitMq.md
new file mode 100644
index 0000000000..a984a2a3ab
--- /dev/null
+++ b/docs/pt-BR/Background-Jobs-RabbitMq.md
@@ -0,0 +1,3 @@
+# RabbitMQ Background Job Manager
+
+TODO
\ No newline at end of file
diff --git a/docs/pt-BR/CLI.md b/docs/pt-BR/CLI.md
new file mode 100644
index 0000000000..4d78237e1c
--- /dev/null
+++ b/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 [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 [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 [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.
+```
+
+
+
\ No newline at end of file
diff --git a/docs/pt-BR/Caching.md b/docs/pt-BR/Caching.md
new file mode 100644
index 0000000000..cc28531e90
--- /dev/null
+++ b/docs/pt-BR/Caching.md
@@ -0,0 +1,3 @@
+# Caching
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Contribution/Index.md b/docs/pt-BR/Contribution/Index.md
new file mode 100644
index 0000000000..e51ff4646c
--- /dev/null
+++ b/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) .
\ No newline at end of file
diff --git a/docs/pt-BR/CorrelationId.md b/docs/pt-BR/CorrelationId.md
new file mode 100644
index 0000000000..97b18c5099
--- /dev/null
+++ b/docs/pt-BR/CorrelationId.md
@@ -0,0 +1,3 @@
+# Correlation ID
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Data-Filtering.md b/docs/pt-BR/Data-Filtering.md
new file mode 100644
index 0000000000..58b1431f2c
--- /dev/null
+++ b/docs/pt-BR/Data-Filtering.md
@@ -0,0 +1,3 @@
+# Data Filtering
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Data-Seeding.md b/docs/pt-BR/Data-Seeding.md
new file mode 100644
index 0000000000..75eea2bcb9
--- /dev/null
+++ b/docs/pt-BR/Data-Seeding.md
@@ -0,0 +1,3 @@
+# Data Seeding
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Data-Transfer-Objects.md b/docs/pt-BR/Data-Transfer-Objects.md
new file mode 100644
index 0000000000..a29865a13c
--- /dev/null
+++ b/docs/pt-BR/Data-Transfer-Objects.md
@@ -0,0 +1,3 @@
+## Data Transfer Objects
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Distributed-Event-Bus.md b/docs/pt-BR/Distributed-Event-Bus.md
new file mode 100644
index 0000000000..da8e2ff516
--- /dev/null
+++ b/docs/pt-BR/Distributed-Event-Bus.md
@@ -0,0 +1,3 @@
+# Distributed Event Bus
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Domain-Services.md b/docs/pt-BR/Domain-Services.md
new file mode 100644
index 0000000000..c412c7b3b3
--- /dev/null
+++ b/docs/pt-BR/Domain-Services.md
@@ -0,0 +1,3 @@
+# ABP Documentation
+
+Façam!
\ No newline at end of file
diff --git a/docs/pt-BR/Dynamic-Proxying-Interceptors.md b/docs/pt-BR/Dynamic-Proxying-Interceptors.md
new file mode 100644
index 0000000000..bfc7b0f705
--- /dev/null
+++ b/docs/pt-BR/Dynamic-Proxying-Interceptors.md
@@ -0,0 +1,3 @@
+## Dynamic Proxying / Interceptors
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Emailing.md b/docs/pt-BR/Emailing.md
new file mode 100644
index 0000000000..a69b1cd7f3
--- /dev/null
+++ b/docs/pt-BR/Emailing.md
@@ -0,0 +1,3 @@
+# Emailing
+
+Façam!
\ No newline at end of file
diff --git a/docs/pt-BR/Event-Bus.md b/docs/pt-BR/Event-Bus.md
new file mode 100644
index 0000000000..d95792bbb7
--- /dev/null
+++ b/docs/pt-BR/Event-Bus.md
@@ -0,0 +1,3 @@
+# Event Bus
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Extension-Methods-And-Helpers.md b/docs/pt-BR/Extension-Methods-And-Helpers.md
new file mode 100644
index 0000000000..fb4d33c7e7
--- /dev/null
+++ b/docs/pt-BR/Extension-Methods-And-Helpers.md
@@ -0,0 +1,3 @@
+# Extension Methods & Helpers
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Getting-Started-Angular-Template.md b/docs/pt-BR/Getting-Started-Angular-Template.md
new file mode 100644
index 0000000000..f8f1eac944
--- /dev/null
+++ b/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** :
+
+
+
+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** **EF Core** & **SQLite in-memory**.
+
+> Consulte o [documento do modelo do aplicativo](Startup-Templates/Application.md) para entender a estrutura da solução em detalhes.
+
+### String de Conexão de Banco de Dados
+
+Verifique o **connection string** 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** :
+
+
+
+Pressione F5 (ou Ctrl + F5) para executar o aplicativo. Terá uma saída como mostrado abaixo:
+
+
+
+#### 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** :
+
+
+
+Abra o **Console do Gerenciador de Pacotes** , selecione o `.EntityFrameworkCore.DbMigrations`projeto como **Projeto Padrão** e execute o `Update-Database`comando:
+
+
+
+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:
+
+
+
+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)
\ No newline at end of file
diff --git a/docs/pt-BR/Getting-Started-AspNetCore-Application.md b/docs/pt-BR/Getting-Started-AspNetCore-Application.md
new file mode 100644
index 0000000000..4c5fb40ce1
--- /dev/null
+++ b/docs/pt-BR/Getting-Started-AspNetCore-Application.md
@@ -0,0 +1,183 @@
+# Introdução ao ABP com o AspNet Core MVC Web Application
+
+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 AspNet Core Web Application no Visual Studio:
+
+
+
+1. Selecionar modelo vazio
+
+
+
+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();
+
+ 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()` 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 framework 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();` linha na `Startup`classe, como mostrado abaixo:
+
+```csharp
+services.AddApplication(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()
+ .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) .
\ No newline at end of file
diff --git a/docs/pt-BR/Getting-Started-AspNetCore-MVC-Template.md b/docs/pt-BR/Getting-Started-AspNetCore-MVC-Template.md
new file mode 100644
index 0000000000..029b898b8d
--- /dev/null
+++ b/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** :
+
+
+
+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 **connection string** 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** :
+
+
+
+Pressione F5 (ou Ctrl + F5) para executar o aplicativo. Terá uma saída como mostrado abaixo:
+
+
+
+#### 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** :
+
+
+
+Abra o **Console do Gerenciador de Pacotes** , selecione o `.EntityFrameworkCore.DbMigrations`projeto como **Projeto Padrão** e execute o `Update-Database`comando:
+
+
+
+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:
+
+
+
+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:
+
+
+
+### Qual é o próximo?
+
+- [Tutorial de desenvolvimento de aplicativos](Tutorials/AspNetCore-Mvc/Part-I.md)
\ No newline at end of file
diff --git a/docs/pt-BR/Getting-Started-Console-Application.md b/docs/pt-BR/Getting-Started-Console-Application.md
new file mode 100644
index 0000000000..f5a0d5d5d0
--- /dev/null
+++ b/docs/pt-BR/Getting-Started-Console-Application.md
@@ -0,0 +1,181 @@
+# 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:
+
+
+
+## Instale o pacote Volo.Abp
+
+Volo.Abp.Core é o pacote principal de nuget 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 é um framework 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())
+ {
+ 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())
+ {
+ application.Initialize();
+
+ //Resolve a service and use it
+ var helloWorldService =
+ application.ServiceProvider.GetService();
+ 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 framework 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 do framework 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(options =>
+ {
+ options.UseAutofac(); //Autofac integration
+ }))
+ {
+ application.Initialize();
+
+ //Resolve a service and use it
+ var helloWorldService =
+ application.ServiceProvider.GetService();
+ 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) .
+
+
diff --git a/docs/pt-BR/Guid-Generation.md b/docs/pt-BR/Guid-Generation.md
new file mode 100644
index 0000000000..68c582348c
--- /dev/null
+++ b/docs/pt-BR/Guid-Generation.md
@@ -0,0 +1,3 @@
+## Guid Generation
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Index.md b/docs/pt-BR/Index.md
new file mode 100644
index 0000000000..535db6478a
--- /dev/null
+++ b/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.
\ No newline at end of file
diff --git a/docs/pt-BR/Integration-Tests.md b/docs/pt-BR/Integration-Tests.md
new file mode 100644
index 0000000000..712ceb5633
--- /dev/null
+++ b/docs/pt-BR/Integration-Tests.md
@@ -0,0 +1,3 @@
+# Integration Tests
+
+Façam!
\ No newline at end of file
diff --git a/docs/pt-BR/Local-Event-Bus.md b/docs/pt-BR/Local-Event-Bus.md
new file mode 100644
index 0000000000..ff4d87d210
--- /dev/null
+++ b/docs/pt-BR/Local-Event-Bus.md
@@ -0,0 +1,3 @@
+# Local Event Bus
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Localization.md b/docs/pt-BR/Localization.md
new file mode 100644
index 0000000000..f665b68073
--- /dev/null
+++ b/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(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ Configure(options =>
+ {
+ //Define a new localization resource (TestResource)
+ options.Resources
+ .Add("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:
+
+
+
+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(options =>
+{
+ options.Resources
+ .Add("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(options =>
+{
+ options.Resources
+ .Get()
+ .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 _localizer;
+
+ public MyService(IStringLocalizer localizer)
+ {
+ _localizer = localizer;
+ }
+
+ public void Foo()
+ {
+ var str = _localizer["HelloWorld"];
+ }
+}
+```
+
+#### Uso mais simples em uma vista / página do Razor
+
+```csharp
+@inject IHtmlLocalizer Localizer
+
+
@Localizer["HelloWorld"]
+```
+
+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');
+```
+
+
+
\ No newline at end of file
diff --git a/docs/pt-BR/Nightly-Builds.md b/docs/pt-BR/Nightly-Builds.md
new file mode 100644
index 0000000000..9d3e49ccf6
--- /dev/null
+++ b/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: 
+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.
+
+
+
+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.
+
+
+
\ No newline at end of file
diff --git a/docs/pt-BR/Object-To-Object-Mapping.md b/docs/pt-BR/Object-To-Object-Mapping.md
new file mode 100644
index 0000000000..7d5f74a3fe
--- /dev/null
+++ b/docs/pt-BR/Object-To-Object-Mapping.md
@@ -0,0 +1,3 @@
+## Object To Object Mapping
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/SMS-Sending.md b/docs/pt-BR/SMS-Sending.md
new file mode 100644
index 0000000000..a69b1cd7f3
--- /dev/null
+++ b/docs/pt-BR/SMS-Sending.md
@@ -0,0 +1,3 @@
+# Emailing
+
+Façam!
\ No newline at end of file
diff --git a/docs/pt-BR/Settings.md b/docs/pt-BR/Settings.md
new file mode 100644
index 0000000000..55d5536798
--- /dev/null
+++ b/docs/pt-BR/Settings.md
@@ -0,0 +1,3 @@
+# Settings
+
+Façam!
\ No newline at end of file
diff --git a/docs/pt-BR/Specifications.md b/docs/pt-BR/Specifications.md
new file mode 100644
index 0000000000..0214f704ce
--- /dev/null
+++ b/docs/pt-BR/Specifications.md
@@ -0,0 +1,3 @@
+# Specifications
+
+Façam!
\ No newline at end of file
diff --git a/docs/pt-BR/Startup-Templates/Application.md b/docs/pt-BR/Startup-Templates/Application.md
new file mode 100644
index 0000000000..1f8d871d28
--- /dev/null
+++ b/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:
+
+
+
+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:
+
+
+
+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** :
+
+
+
+- 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:
+
+
+
+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.
+
+
+
+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.
+
+
diff --git a/docs/pt-BR/Startup-Templates/Index.md b/docs/pt-BR/Startup-Templates/Index.md
new file mode 100644
index 0000000000..61f2d2d544
--- /dev/null
+++ b/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.
+
diff --git a/docs/pt-BR/Startup-Templates/Module.md b/docs/pt-BR/Startup-Templates/Module.md
new file mode 100644
index 0000000000..04984d181c
--- /dev/null
+++ b/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:
+
+
+
+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:
+
+
+
+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:
+
+
+
+`.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.
+
+
+
\ No newline at end of file
diff --git a/docs/pt-BR/Testing.md b/docs/pt-BR/Testing.md
new file mode 100644
index 0000000000..ec9f5626a9
--- /dev/null
+++ b/docs/pt-BR/Testing.md
@@ -0,0 +1,3 @@
+# Testing
+
+Façam!
\ No newline at end of file
diff --git a/docs/pt-BR/Tutorials/Angular/Part-I.md b/docs/pt-BR/Tutorials/Angular/Part-I.md
new file mode 100644
index 0000000000..566690a1d3
--- /dev/null
+++ b/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:
+
+
+
+> 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
+ {
+ 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 Books => Collection();
+ ...
+}
+```
+
+#### 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 _bookRepository;
+
+ public BookStoreDataSeederContributor(IRepository 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
+ {
+ 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`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();
+ }
+ }
+}
+```
+
+#### 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();
+```
+
+#### 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,
+ IBookAppService
+ {
+ public BookAppService(IRepository repository)
+ : base(repository)
+ {
+
+ }
+ }
+}
+```
+
+- `BookAppService`é derivado do `CrudAppService<...>`qual implementa todos os métodos CRUD definidos acima.
+- `BookAppService`injeta `IRepository`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:
+
+
+
+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
+```
+
+
+
+Execute `yarn start`, aguarde Angular para executar o aplicativo e abra `http://localhost:4200/books`em um navegador:
+
+
+
+#### 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.
+
+
+
+#### Componente da lista de livros
+
+Primeiro, substitua pela `books.component.html`seguinte linha para colocar a saída do roteador:
+
+```html
+
+```
+
+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
+```
+
+
+
+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 {}
+```
+
+
+
+#### 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
+```
+
+
+
+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 {
+ return this.restService.request({
+ 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({
+ 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) {
+ 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;
+
+ 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
+
+
+
+
+
+ Books
+
+
+
+
+
+
+
+
+
Book name
+
Book type
+
Publish date
+
Price
+
+
+
+
+
{{ data.name }}
+
{{ booksType[data.type] }}
+
{{ data.publishDate | date }}
+
{{ data.price }}
+
+
+
+
+
+```
+
+> Usamos a [tabela PrimeNG](https://www.primefaces.org/primeng/#/table) neste componente.
+
+A página de livros resultante é mostrada abaixo:
+
+
+
+E esta é a estrutura de pastas e arquivos no final deste tutorial:
+
+
+
+> 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.
+
+
+
\ No newline at end of file
diff --git a/docs/pt-BR/Tutorials/Angular/Part-II.md b/docs/pt-BR/Tutorials/Angular/Part-II.md
new file mode 100644
index 0000000000..6113c325a3
--- /dev/null
+++ b/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 {
+ return this.restService.request({
+ 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, 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
+
+
+
New Book
+
+
+
+
+
+
+
+
+```
+
+`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
+
+
+
+ Books
+
+
+
+
+
+
+```
+
+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;
+}
+```
+
+
+
+#### 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
+
+
+
+```
+
+- 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.
+
+
+
+#### Salvando o livro
+
+Abra o `book-list.component.html`e adicione um `abp-button`para salvar o formulário.
+
+```html
+
+
+
+
+```
+
+Isso adiciona um botão Salvar à área inferior do modal:
+
+
+
+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 {
+ return this.restService.request({
+ method: 'GET',
+ url: `/api/app/book/${id}`
+ });
+}
+
+update(updateBookInput: Books.CreateUpdateBookInput, id: string): Observable {
+ return this.restService.request({
+ 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, 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
+
+
+
+
Actions
+
Book name
+
Book type
+
Publish date
+
Price
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ data.name }}
+
{{ booksType[data.type] }}
+
{{ data.publishDate | date }}
+
{{ data.price }}
+
+
+
+```
+
+- 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:
+
+
+
+Atualize o cabeçalho modal para alterar o título com base na operação atual:
+
+```html
+
+
{{ selectedBook.id ? 'Edit' : 'New Book' }}
+
+```
+
+
+
+### 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 {
+ return this.restService.request({
+ 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, 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
+
+ ...
+
+
+```
+
+A interface do usuário suspensa de ações finais é semelhante a abaixo:
+
+
+
+\#### 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:
+
+
+
+### Próxima parte
+
+Veja a [próxima parte](Part-III.md) deste tutorial.
+
diff --git a/docs/pt-BR/Tutorials/Angular/Part-III.md b/docs/pt-BR/Tutorials/Angular/Part-III.md
new file mode 100644
index 0000000000..fc8d1b6c3b
--- /dev/null
+++ b/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:
+
+
+
+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 _bookRepository;
+ private readonly IGuidGenerator _guidGenerator;
+
+ public BookStoreTestDataSeedContributor(
+ IRepository 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`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();
+ }
+
+ [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(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:
+
+
+
+Parabéns, ícones verdes mostram que os testes foram aprovados com sucesso!
+
+
+
\ No newline at end of file
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-actions-buttons.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-actions-buttons.png
new file mode 100644
index 0000000000..aecf31c1ad
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-actions-buttons.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-angular-file-tree.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-angular-file-tree.png
new file mode 100644
index 0000000000..be05ad3e4a
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-angular-file-tree.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-backend-solution-v2.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-backend-solution-v2.png
new file mode 100644
index 0000000000..79bcecb561
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-backend-solution-v2.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-book-list.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-book-list.png
new file mode 100644
index 0000000000..3f9717df6e
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-book-list.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-confirmation-popup.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-confirmation-popup.png
new file mode 100644
index 0000000000..c3f46af821
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-confirmation-popup.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-creating-book-list-terminal.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-creating-book-list-terminal.png
new file mode 100644
index 0000000000..9f01e94121
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-creating-book-list-terminal.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-creating-books-module-terminal.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-creating-books-module-terminal.png
new file mode 100644
index 0000000000..c74b37b1b5
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-creating-books-module-terminal.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-edit-modal.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-edit-modal.png
new file mode 100644
index 0000000000..c911403792
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-edit-modal.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-empty-new-book-modal.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-empty-new-book-modal.png
new file mode 100644
index 0000000000..2a02802bb9
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-empty-new-book-modal.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-final-actions-dropdown.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-final-actions-dropdown.png
new file mode 100644
index 0000000000..6b0be415c4
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-final-actions-dropdown.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-book-list-page.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-book-list-page.png
new file mode 100644
index 0000000000..0b345ac61d
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-book-list-page.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page-with-layout.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page-with-layout.png
new file mode 100644
index 0000000000..484837f78a
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page-with-layout.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page.png
new file mode 100644
index 0000000000..4af86c50fa
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-initial-books-page.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form-v2.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form-v2.png
new file mode 100644
index 0000000000..72513de6e5
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form-v2.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form.png
new file mode 100644
index 0000000000..95de64f8d4
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-new-book-form.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-service-terminal-output.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-service-terminal-output.png
new file mode 100644
index 0000000000..69aaccba31
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-service-terminal-output.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-swagger-api.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-swagger-api.png
new file mode 100644
index 0000000000..437c772503
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-swagger-api.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-test-explorer.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-test-explorer.png
new file mode 100644
index 0000000000..06e9e7d331
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-test-explorer.png differ
diff --git a/docs/pt-BR/Tutorials/Angular/images/bookstore-test-projects-v3.png b/docs/pt-BR/Tutorials/Angular/images/bookstore-test-projects-v3.png
new file mode 100644
index 0000000000..32ea91b325
Binary files /dev/null and b/docs/pt-BR/Tutorials/Angular/images/bookstore-test-projects-v3.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-I.md b/docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-I.md
new file mode 100644
index 0000000000..798836ba52
--- /dev/null
+++ b/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:
+
+
+
+> 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
+ {
+ 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
+ {
+ public DbSet 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(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:
+
+
+
+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:
+
+
+
+### 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
+ {
+ 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`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();
+ }
+ }
+}
+```
+
+#### 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();
+```
+
+#### 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,
+ IBookAppService
+ {
+ public BookAppService(IRepository repository)
+ : base(repository)
+ {
+
+ }
+ }
+}
+```
+
+- `BookAppService`é derivado do `CrudAppService<...>`qual implementa todos os métodos CRUD definidos acima.
+- `BookAppService`injeta `IRepository`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:
+
+
+
+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:
+
+
+
+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:
+
+
+
+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`:
+
+
+
+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
+
+
Books
+```
+
+- 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:
+
+
+
+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:
+
+
+
+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
+{
+
+}
+
+
+
@L["Books"]
+
+
+
+
+
+
@L["Name"]
+
@L["Type"]
+
@L["PublishDate"]
+
@L["Price"]
+
@L["CreationTime"]
+
+
+
+
+
+```
+
+- `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:
+
+
+
+`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:
+
+
+
+### Próxima parte
+
+Veja a [próxima parte](https://docs.abp.io/en/abp/latest/Tutorials/AspNetCore-Mvc/Part-II) deste tutorial.
\ No newline at end of file
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-II.md b/docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-II.md
new file mode 100644
index 0000000000..7e6471d3ed
--- /dev/null
+++ b/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:
+
+
+
+#### 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:
+
+
+
+##### 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 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;
+}
+
+
+
+
+
+
+
+
+
+```
+
+
+
+- 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
+
+
+
+
@L["Books"]
+
+
+
+
+
+
+```
+
+
+
+Acabei de adicionar um botão **Novo livro** no canto **superior direito** da tabela:
+
+
+
+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:
+
+
+
+#### 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);
+ }
+
+ public async Task 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();
+ }
+ }
+}
+```
+
+
+
+- Apenas adicionado `CreateMap();`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;
+}
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+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:
+
+
+
+Abra a `Pages/Books/Index.cshtml`página e altere a seção da tabela como mostrado abaixo:
+
+```html
+
+
+
+
@L["Actions"]
+
@L["Name"]
+
@L["Type"]
+
@L["PublishDate"]
+
@L["Price"]
+
@L["CreationTime"]
+
+
+
+```
+
+
+
+- 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.
\ No newline at end of file
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-III.md b/docs/pt-BR/Tutorials/AspNetCore-Mvc/Part-III.md
new file mode 100644
index 0000000000..ff1ad29a25
--- /dev/null
+++ b/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:
+
+
+
+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 _bookRepository;
+ private readonly IGuidGenerator _guidGenerator;
+
+ public BookStoreTestDataSeedContributor(
+ IRepository 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`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();
+ }
+
+ [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(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:
+
+
+
+Parabéns, ícones verdes mostram que os testes foram aprovados com sucesso!
\ No newline at end of file
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png
new file mode 100644
index 0000000000..fcadfd7a82
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-create-dialog-v2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-edit-dialog.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-edit-dialog.png
new file mode 100644
index 0000000000..b28d8736dd
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-edit-dialog.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png
new file mode 100644
index 0000000000..2606bbab32
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-add-index-page-v2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png
new file mode 100644
index 0000000000..942d2832a6
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-appservice-tests.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list-2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list-2.png
new file mode 100644
index 0000000000..a7d49a661b
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list-2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list.png
new file mode 100644
index 0000000000..f531e6f457
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-book-list.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table-actions.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table-actions.png
new file mode 100644
index 0000000000..bc1d4e3f6f
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table-actions.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table.png
new file mode 100644
index 0000000000..3cc8d7ca18
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-books-table.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog-2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog-2.png
new file mode 100644
index 0000000000..3d5f1e8582
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog-2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog.png
new file mode 100644
index 0000000000..4691d3c8fa
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-dialog.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-template.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-template.png
new file mode 100644
index 0000000000..7cc96c8c94
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-create-template.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-homepage.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-homepage.png
new file mode 100644
index 0000000000..5e5b512220
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-homepage.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png
new file mode 100644
index 0000000000..1ba9a48600
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-index-js-file-v2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png
new file mode 100644
index 0000000000..79314dd2dc
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-localization-files-v2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-menu-items.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-menu-items.png
new file mode 100644
index 0000000000..255defb707
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-menu-items.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-new-book-button.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-new-book-button.png
new file mode 100644
index 0000000000..dfd4b5d8aa
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-new-book-button.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png
new file mode 100644
index 0000000000..edf2826361
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration.png
new file mode 100644
index 0000000000..5d29f4d32b
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-swagger.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-swagger.png
new file mode 100644
index 0000000000..437c772503
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-swagger.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist-network.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist-network.png
new file mode 100644
index 0000000000..2f2c42fd9e
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist-network.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist.png
new file mode 100644
index 0000000000..47af48b1ea
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-js-proxy-getlist.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png
new file mode 100644
index 0000000000..8701164d75
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-test-projects-v2.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-user-management.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-user-management.png
new file mode 100644
index 0000000000..bc3c176557
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-user-management.png differ
diff --git a/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png
new file mode 100644
index 0000000000..307e3516a5
Binary files /dev/null and b/docs/pt-BR/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v3.png differ
diff --git a/docs/pt-BR/Unit-Of-Work.md b/docs/pt-BR/Unit-Of-Work.md
new file mode 100644
index 0000000000..af662f86de
--- /dev/null
+++ b/docs/pt-BR/Unit-Of-Work.md
@@ -0,0 +1,3 @@
+## Unit of Work
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Validation.md b/docs/pt-BR/Validation.md
new file mode 100644
index 0000000000..5818566cdd
--- /dev/null
+++ b/docs/pt-BR/Validation.md
@@ -0,0 +1,3 @@
+## Validation
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/Value-Objects.md b/docs/pt-BR/Value-Objects.md
new file mode 100644
index 0000000000..647e6d2f0a
--- /dev/null
+++ b/docs/pt-BR/Value-Objects.md
@@ -0,0 +1,3 @@
+## Value Objects
+
+Façam
\ No newline at end of file
diff --git a/docs/pt-BR/docs-nav.json b/docs/pt-BR/docs-nav.json
new file mode 100644
index 0000000000..11b9b84fd1
--- /dev/null
+++ b/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"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/docs/pt-BR/images/MonthlyProfitWidgetFiles.png b/docs/pt-BR/images/MonthlyProfitWidgetFiles.png
new file mode 100644
index 0000000000..e1e9d316f5
Binary files /dev/null and b/docs/pt-BR/images/MonthlyProfitWidgetFiles.png differ
diff --git a/docs/pt-BR/images/bookstore-apis.png b/docs/pt-BR/images/bookstore-apis.png
new file mode 100644
index 0000000000..aedd79c7f1
Binary files /dev/null and b/docs/pt-BR/images/bookstore-apis.png differ
diff --git a/docs/pt-BR/images/bookstore-create-template.png b/docs/pt-BR/images/bookstore-create-template.png
new file mode 100644
index 0000000000..7cc96c8c94
Binary files /dev/null and b/docs/pt-BR/images/bookstore-create-template.png differ
diff --git a/docs/pt-BR/images/bookstore-homepage.png b/docs/pt-BR/images/bookstore-homepage.png
new file mode 100644
index 0000000000..5e5b512220
Binary files /dev/null and b/docs/pt-BR/images/bookstore-homepage.png differ
diff --git a/docs/pt-BR/images/bookstore-swagger-ui-host.png b/docs/pt-BR/images/bookstore-swagger-ui-host.png
new file mode 100644
index 0000000000..74ff73f7e3
Binary files /dev/null and b/docs/pt-BR/images/bookstore-swagger-ui-host.png differ
diff --git a/docs/pt-BR/images/bookstore-user-management-v2.png b/docs/pt-BR/images/bookstore-user-management-v2.png
new file mode 100644
index 0000000000..dd95740754
Binary files /dev/null and b/docs/pt-BR/images/bookstore-user-management-v2.png differ
diff --git a/docs/pt-BR/images/bookstore-visual-studio-solution-for-spa.png b/docs/pt-BR/images/bookstore-visual-studio-solution-for-spa.png
new file mode 100644
index 0000000000..5a5a283c7d
Binary files /dev/null and b/docs/pt-BR/images/bookstore-visual-studio-solution-for-spa.png differ
diff --git a/docs/pt-BR/images/bookstore-visual-studio-solution-tiered.png b/docs/pt-BR/images/bookstore-visual-studio-solution-tiered.png
new file mode 100644
index 0000000000..19662bf731
Binary files /dev/null and b/docs/pt-BR/images/bookstore-visual-studio-solution-tiered.png differ
diff --git a/docs/pt-BR/images/bookstore-visual-studio-solution-v3.png b/docs/pt-BR/images/bookstore-visual-studio-solution-v3.png
new file mode 100644
index 0000000000..307e3516a5
Binary files /dev/null and b/docs/pt-BR/images/bookstore-visual-studio-solution-v3.png differ
diff --git a/docs/pt-BR/images/build-action-embedded-resource-sample.png b/docs/pt-BR/images/build-action-embedded-resource-sample.png
new file mode 100644
index 0000000000..d001c5d19f
Binary files /dev/null and b/docs/pt-BR/images/build-action-embedded-resource-sample.png differ
diff --git a/docs/pt-BR/images/create-new-aspnet-core-application.png b/docs/pt-BR/images/create-new-aspnet-core-application.png
new file mode 100644
index 0000000000..fe78b9051d
Binary files /dev/null and b/docs/pt-BR/images/create-new-aspnet-core-application.png differ
diff --git a/docs/pt-BR/images/create-new-net-core-console-application.png b/docs/pt-BR/images/create-new-net-core-console-application.png
new file mode 100644
index 0000000000..c5f39bfb37
Binary files /dev/null and b/docs/pt-BR/images/create-new-net-core-console-application.png differ
diff --git a/docs/pt-BR/images/dashboard1.png b/docs/pt-BR/images/dashboard1.png
new file mode 100644
index 0000000000..4102bbd4c1
Binary files /dev/null and b/docs/pt-BR/images/dashboard1.png differ
diff --git a/docs/pt-BR/images/db-migrator-app.png b/docs/pt-BR/images/db-migrator-app.png
new file mode 100644
index 0000000000..ace6abb226
Binary files /dev/null and b/docs/pt-BR/images/db-migrator-app.png differ
diff --git a/docs/pt-BR/images/docs-create-project.jpg b/docs/pt-BR/images/docs-create-project.jpg
new file mode 100644
index 0000000000..742f5e307f
Binary files /dev/null and b/docs/pt-BR/images/docs-create-project.jpg differ
diff --git a/docs/pt-BR/images/docs-module_download-new-abp-project.png b/docs/pt-BR/images/docs-module_download-new-abp-project.png
new file mode 100644
index 0000000000..0da3b7a67a
Binary files /dev/null and b/docs/pt-BR/images/docs-module_download-new-abp-project.png differ
diff --git a/docs/pt-BR/images/docs-module_download-sample-navigation-menu.png b/docs/pt-BR/images/docs-module_download-sample-navigation-menu.png
new file mode 100644
index 0000000000..9a1232f198
Binary files /dev/null and b/docs/pt-BR/images/docs-module_download-sample-navigation-menu.png differ
diff --git a/docs/pt-BR/images/docs-module_solution-explorer.png b/docs/pt-BR/images/docs-module_solution-explorer.png
new file mode 100644
index 0000000000..cafc38f0b0
Binary files /dev/null and b/docs/pt-BR/images/docs-module_solution-explorer.png differ
diff --git a/docs/pt-BR/images/github-access-token-private-repo.jpg b/docs/pt-BR/images/github-access-token-private-repo.jpg
new file mode 100644
index 0000000000..5bc53cc63d
Binary files /dev/null and b/docs/pt-BR/images/github-access-token-private-repo.jpg differ
diff --git a/docs/pt-BR/images/github-access-token-public-repo.jpg b/docs/pt-BR/images/github-access-token-public-repo.jpg
new file mode 100644
index 0000000000..b909c2cfe5
Binary files /dev/null and b/docs/pt-BR/images/github-access-token-public-repo.jpg differ
diff --git a/docs/pt-BR/images/github-myusername.jpg b/docs/pt-BR/images/github-myusername.jpg
new file mode 100644
index 0000000000..4ac57eeed4
Binary files /dev/null and b/docs/pt-BR/images/github-myusername.jpg differ
diff --git a/docs/pt-BR/images/issuemanagement-module-solution.png b/docs/pt-BR/images/issuemanagement-module-solution.png
new file mode 100644
index 0000000000..181924dd90
Binary files /dev/null and b/docs/pt-BR/images/issuemanagement-module-solution.png differ
diff --git a/docs/pt-BR/images/layered-project-dependencies-module.png b/docs/pt-BR/images/layered-project-dependencies-module.png
new file mode 100644
index 0000000000..7592f49878
Binary files /dev/null and b/docs/pt-BR/images/layered-project-dependencies-module.png differ
diff --git a/docs/pt-BR/images/layered-project-dependencies.png b/docs/pt-BR/images/layered-project-dependencies.png
new file mode 100644
index 0000000000..c5fd1b3504
Binary files /dev/null and b/docs/pt-BR/images/layered-project-dependencies.png differ
diff --git a/docs/pt-BR/images/localization-resource-json-files.png b/docs/pt-BR/images/localization-resource-json-files.png
new file mode 100644
index 0000000000..bbbd78c320
Binary files /dev/null and b/docs/pt-BR/images/localization-resource-json-files.png differ
diff --git a/docs/pt-BR/images/microservice-sample-authserver-home.png b/docs/pt-BR/images/microservice-sample-authserver-home.png
new file mode 100644
index 0000000000..7ae62ad6d5
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-authserver-home.png differ
diff --git a/docs/pt-BR/images/microservice-sample-authserver-login.png b/docs/pt-BR/images/microservice-sample-authserver-login.png
new file mode 100644
index 0000000000..f6e8dfaa9f
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-authserver-login.png differ
diff --git a/docs/pt-BR/images/microservice-sample-backend-ui-permissions.png b/docs/pt-BR/images/microservice-sample-backend-ui-permissions.png
new file mode 100644
index 0000000000..02769be3e5
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-backend-ui-permissions.png differ
diff --git a/docs/pt-BR/images/microservice-sample-backend-ui.png b/docs/pt-BR/images/microservice-sample-backend-ui.png
new file mode 100644
index 0000000000..0935a6047a
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-backend-ui.png differ
diff --git a/docs/pt-BR/images/microservice-sample-blogservice-permission-in-database.png b/docs/pt-BR/images/microservice-sample-blogservice-permission-in-database.png
new file mode 100644
index 0000000000..f99cd39893
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-blogservice-permission-in-database.png differ
diff --git a/docs/pt-BR/images/microservice-sample-diagram-2.png b/docs/pt-BR/images/microservice-sample-diagram-2.png
new file mode 100644
index 0000000000..17aea07098
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-diagram-2.png differ
diff --git a/docs/pt-BR/images/microservice-sample-diagram.png b/docs/pt-BR/images/microservice-sample-diagram.png
new file mode 100644
index 0000000000..b1d9f6c66e
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-diagram.png differ
diff --git a/docs/pt-BR/images/microservice-sample-kibana-1.png b/docs/pt-BR/images/microservice-sample-kibana-1.png
new file mode 100644
index 0000000000..f3a51bd349
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-kibana-1.png differ
diff --git a/docs/pt-BR/images/microservice-sample-kibana-2.png b/docs/pt-BR/images/microservice-sample-kibana-2.png
new file mode 100644
index 0000000000..31b281486c
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-kibana-2.png differ
diff --git a/docs/pt-BR/images/microservice-sample-product-module-in-solution.png b/docs/pt-BR/images/microservice-sample-product-module-in-solution.png
new file mode 100644
index 0000000000..27e841cdd5
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-product-module-in-solution.png differ
diff --git a/docs/pt-BR/images/microservice-sample-public-product-list.png b/docs/pt-BR/images/microservice-sample-public-product-list.png
new file mode 100644
index 0000000000..cf8649bbe5
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-public-product-list.png differ
diff --git a/docs/pt-BR/images/microservice-sample-solution.png b/docs/pt-BR/images/microservice-sample-solution.png
new file mode 100644
index 0000000000..4c8344ed68
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-solution.png differ
diff --git a/docs/pt-BR/images/microservice-sample-update-database-authserver.png b/docs/pt-BR/images/microservice-sample-update-database-authserver.png
new file mode 100644
index 0000000000..689019b587
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-update-database-authserver.png differ
diff --git a/docs/pt-BR/images/microservice-sample-update-database-products.png b/docs/pt-BR/images/microservice-sample-update-database-products.png
new file mode 100644
index 0000000000..b49c2a8f8e
Binary files /dev/null and b/docs/pt-BR/images/microservice-sample-update-database-products.png differ
diff --git a/docs/pt-BR/images/module-layers-and-packages.jpg b/docs/pt-BR/images/module-layers-and-packages.jpg
new file mode 100644
index 0000000000..f71a91eb8d
Binary files /dev/null and b/docs/pt-BR/images/module-layers-and-packages.jpg differ
diff --git a/docs/pt-BR/images/night-build-add-nuget-package.png b/docs/pt-BR/images/night-build-add-nuget-package.png
new file mode 100644
index 0000000000..c3621ef7d9
Binary files /dev/null and b/docs/pt-BR/images/night-build-add-nuget-package.png differ
diff --git a/docs/pt-BR/images/night-build-add-nuget-source.png b/docs/pt-BR/images/night-build-add-nuget-source.png
new file mode 100644
index 0000000000..8fd4b9365a
Binary files /dev/null and b/docs/pt-BR/images/night-build-add-nuget-source.png differ
diff --git a/docs/pt-BR/images/pcm-update-database-v2.png b/docs/pt-BR/images/pcm-update-database-v2.png
new file mode 100644
index 0000000000..d5bb9c2975
Binary files /dev/null and b/docs/pt-BR/images/pcm-update-database-v2.png differ
diff --git a/docs/pt-BR/images/pcm-update-database.png b/docs/pt-BR/images/pcm-update-database.png
new file mode 100644
index 0000000000..ac53f0db4f
Binary files /dev/null and b/docs/pt-BR/images/pcm-update-database.png differ
diff --git a/docs/pt-BR/images/select-empty-web-application.png b/docs/pt-BR/images/select-empty-web-application.png
new file mode 100644
index 0000000000..b0cd89a27a
Binary files /dev/null and b/docs/pt-BR/images/select-empty-web-application.png differ
diff --git a/docs/pt-BR/images/set-as-startup-project.png b/docs/pt-BR/images/set-as-startup-project.png
new file mode 100644
index 0000000000..13da5caf6c
Binary files /dev/null and b/docs/pt-BR/images/set-as-startup-project.png differ
diff --git a/docs/pt-BR/images/tiered-solution-applications.png b/docs/pt-BR/images/tiered-solution-applications.png
new file mode 100644
index 0000000000..fb6ede7ac5
Binary files /dev/null and b/docs/pt-BR/images/tiered-solution-applications.png differ
diff --git a/docs/pt-BR/images/tiered-solution-servers.png b/docs/pt-BR/images/tiered-solution-servers.png
new file mode 100644
index 0000000000..3c999b4b45
Binary files /dev/null and b/docs/pt-BR/images/tiered-solution-servers.png differ
diff --git a/docs/pt-BR/images/volodocs-iis-add-website.png b/docs/pt-BR/images/volodocs-iis-add-website.png
new file mode 100644
index 0000000000..878b3e8f0c
Binary files /dev/null and b/docs/pt-BR/images/volodocs-iis-add-website.png differ
diff --git a/docs/pt-BR/images/volodocs-iis-application-pool.png b/docs/pt-BR/images/volodocs-iis-application-pool.png
new file mode 100644
index 0000000000..cc5186f50b
Binary files /dev/null and b/docs/pt-BR/images/volodocs-iis-application-pool.png differ
diff --git a/docs/pt-BR/images/widget-basic-files.png b/docs/pt-BR/images/widget-basic-files.png
new file mode 100644
index 0000000000..bf5f122d42
Binary files /dev/null and b/docs/pt-BR/images/widget-basic-files.png differ
diff --git a/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/Post.md b/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/Post.md
new file mode 100644
index 0000000000..7633f3ea33
--- /dev/null
+++ b/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/Post.md
@@ -0,0 +1,21 @@
+# 基于ASP.NET Core 3.0的ABP v0.21已发布
+
+在微软发布仅仅一个小时后, 基于ASP.NET Core 3.0的ABP v0.21也紧跟着[发布了.](https://twitter.com/abpframework/status/1176185493119258624)
+
+v0.21没有新功能.它只是升级到稳定的ASP.NET Core 3.0. 查看[v0.20发行说明](https://github.com/abpframework/abp/releases/tag/0.20.0)以获取新功能,增强功能和错误修复.
+
+## 关于v1.0
+
+ABP框架越来越接近v1.0.我们打算在今年10月中旬发布1.0. 现在,我们将完善测试和文档.
+
+## .NET Conf 2019
+
+微软已经在为期3天的虚拟会议.NET Conf 2019发布了ASP.NET Core 3.0. ABP的首席开发人员[Halil ibrahim Kalkan](https://twitter.com/hibrahimkalkan)在会议上也发表了讲话,介绍了ABP框架.能够参加这一重要活动真是太棒了.
+
+## Techorama荷兰2019
+
+[Techorama NL](https://techorama.nl/)是欧洲最大的会议之一.今年,Volosoft是会议的赞助商,并将有一个展位与软件开发人员讨论ABP框架和软件开发.我们的展位墙如下图所示:
+
+
+
+如果您也参加会议,请到展位讨论ABP框架.我们还为您准备了一些私货:)
diff --git a/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/volosoft-booth.png b/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/volosoft-booth.png
new file mode 100644
index 0000000000..3dca4409e4
Binary files /dev/null and b/docs/zh-Hans/Blog-Posts/2019-09-25 v0_21_Release/volosoft-booth.png differ
diff --git a/docs/zh-Hans/Multi-Tenancy.md b/docs/zh-Hans/Multi-Tenancy.md
index 911803b1be..352190d5cd 100644
--- a/docs/zh-Hans/Multi-Tenancy.md
+++ b/docs/zh-Hans/Multi-Tenancy.md
@@ -115,7 +115,7 @@ namespace MyCompany.MyProject
{
Configure(options =>
{
- options.TenantResolvers.Add(new MyCustomTenantResolver());
+ options.TenantResolvers.Add(new MyCustomTenantResolveContributor());
});
//...
@@ -124,14 +124,14 @@ namespace MyCompany.MyProject
}
````
-MyCustomTenantResolver必须像下面这样实现**ITenantResolver**接口:
+`MyCustomTenantResolveContributor`必须像下面这样实现**ITenantResolveContributor**接口:
````C#
using Volo.Abp.MultiTenancy;
namespace MyCompany.MyProject
{
- public class MyCustomTenantResolver : ITenantResolver
+ public class MyCustomTenantResolveContributor : ITenantResolveContributor
{
public void Resolve(ITenantResolveContext context)
{
diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index de41f864c7..534b7c6d92 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -248,6 +248,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MailKit", "src\Vol
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MailKit.Tests", "test\Volo.Abp.MailKit.Tests\Volo.Abp.MailKit.Tests.csproj", "{70DD6E17-B98B-4B00-8F38-C489E291BB53}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.ObjectMapping.Tests", "test\Volo.Abp.ObjectMapping.Tests\Volo.Abp.ObjectMapping.Tests.csproj", "{667F5544-C1EB-447C-96FD-9B757F04DE2B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -738,6 +740,10 @@ Global
{70DD6E17-B98B-4B00-8F38-C489E291BB53}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70DD6E17-B98B-4B00-8F38-C489E291BB53}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70DD6E17-B98B-4B00-8F38-C489E291BB53}.Release|Any CPU.Build.0 = Release|Any CPU
+ {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {667F5544-C1EB-447C-96FD-9B757F04DE2B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -864,6 +870,7 @@ Global
{E026A085-D881-4AE0-9F08-422AC3903BD7} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{0CAED4CC-1CFD-4092-A326-AFE4DB3A9AB4} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{70DD6E17-B98B-4B00-8F38-C489E291BB53} = {447C8A77-E5F0-4538-8687-7383196D04EA}
+ {667F5544-C1EB-447C-96FD-9B757F04DE2B} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
index 7d8a961507..0ccb29a319 100644
--- a/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer/Volo.Abp.AspNetCore.Authentication.JwtBearer.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Authentication.JwtBearerVolo.Abp.AspNetCore.Authentication.JwtBearer$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
@@ -18,7 +18,7 @@
-
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Properties/launchSettings.json
new file mode 100644
index 0000000000..fcbf86698d
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53450/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Authentication.OAuth": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53451/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj
index 54c93df3ec..8541a681f0 100644
--- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo.Abp.AspNetCore.Authentication.OAuth.csproj
@@ -1,15 +1,17 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Authentication.OAuthVolo.Abp.AspNetCore.Authentication.OAuth$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
@@ -17,8 +19,4 @@
-
-
-
-
-
+
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs
index 742f91d057..074cc936d0 100644
--- a/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OAuth/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction.cs
@@ -1,6 +1,6 @@
using System.Security.Claims;
+using System.Text.Json;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
-using Newtonsoft.Json.Linq;
namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
{
@@ -9,31 +9,30 @@ namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
public MultipleClaimAction(string claimType, string jsonKey)
: base(claimType, jsonKey)
{
+
}
- public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
- {
- var prop = userData?.Property(ValueType);
- if (prop == null)
+ public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
+ {
+ var prop = userData.GetProperty(ValueType);
+ if (prop.ValueKind == JsonValueKind.Null)
{
return;
}
- var propValue = prop.Value;
-
- switch (propValue.Type)
+ switch (prop.ValueKind)
{
- case JTokenType.String:
- identity.AddClaim(new Claim(ClaimType, propValue.Value(), ValueType, issuer));
+ case JsonValueKind.String:
+ identity.AddClaim(new Claim(ClaimType, prop.GetString(), ValueType, issuer));
break;
- case JTokenType.Array:
- foreach (var innterValue in propValue.Values())
+ case JsonValueKind.Array:
+ foreach (var arramItem in prop.EnumerateArray())
{
- identity.AddClaim(new Claim(ClaimType, innterValue, ValueType, issuer));
+ identity.AddClaim(new Claim(ClaimType, arramItem.GetString(), ValueType, issuer));
}
break;
default:
- throw new AbpException("Unhandled JTokenType: " + propValue.Type);
+ throw new AbpException("Unhandled JsonValueKind: " + prop.ValueKind);
}
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Properties/launchSettings.json
new file mode 100644
index 0000000000..67c494aa28
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53760/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.MultiTenancy": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53763/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
index 6904fe07b1..384aaa262e 100644
--- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
@@ -1,15 +1,17 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.MultiTenancyVolo.Abp.AspNetCore.MultiTenancy$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Properties/launchSettings.json
new file mode 100644
index 0000000000..e17b14d87f
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:52302/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc.Client": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:52303/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj
index 9d05c9e34b..253bf0d288 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo.Abp.AspNetCore.Mvc.Client.csproj
@@ -1,15 +1,17 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.ClientVolo.Abp.AspNetCore.Mvc.Client$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
index 4ceb8bdd1c..838150fd49 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/CachedApplicationConfigurationClient.cs
@@ -13,8 +13,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class CachedApplicationConfigurationClient : ICachedApplicationConfigurationClient, ITransientDependency
{
- public IHttpContextAccessor HttpContextAccessor { get; set; }
-
+ protected IHttpContextAccessor HttpContextAccessor { get; }
protected IHttpClientProxy Proxy { get; }
protected ICurrentUser CurrentUser { get; }
protected IDistributedCache Cache { get; }
@@ -42,11 +41,11 @@ namespace Volo.Abp.AspNetCore.Mvc.Client
}
configuration = await Cache.GetOrAddAsync(
- CreateCacheKey(),
+ cacheKey,
async () => await Proxy.Service.GetAsync(),
() => new DistributedCacheEntryOptions
{
- AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) //TODO: Should be configurable. Default value should be higher (5 mins would be good).
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(120) //TODO: Should be configurable. Default value should be higher (5 mins would be good).
}
);
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs
new file mode 100644
index 0000000000..718abbb6a9
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteTenantStore.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Caching.Distributed;
+using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
+using Volo.Abp.Caching;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Http.Client.DynamicProxying;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Threading;
+
+namespace Volo.Abp.AspNetCore.Mvc.Client
+{
+ public class RemoteTenantStore : ITenantStore, ITransientDependency
+ {
+ protected IHttpClientProxy Proxy { get; }
+ protected IHttpContextAccessor HttpContextAccessor { get; }
+ protected IDistributedCache Cache { get; }
+
+ public RemoteTenantStore(
+ IHttpClientProxy proxy,
+ IHttpContextAccessor httpContextAccessor,
+ IDistributedCache cache)
+ {
+ Proxy = proxy;
+ HttpContextAccessor = httpContextAccessor;
+ Cache = cache;
+ }
+
+ public async Task FindAsync(string name)
+ {
+ var cacheKey = CreateCacheKey(name);
+ var httpContext = HttpContextAccessor?.HttpContext;
+
+ if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration)
+ {
+ return tenantConfiguration;
+ }
+
+ tenantConfiguration = await Cache.GetOrAddAsync(
+ cacheKey,
+ async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByNameAsync(name)),
+ () => new DistributedCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow =
+ TimeSpan.FromMinutes(5) //TODO: Should be configurable.
+ }
+ );
+
+ if (httpContext != null)
+ {
+ httpContext.Items[cacheKey] = tenantConfiguration;
+ }
+
+ return tenantConfiguration;
+ }
+
+ public async Task FindAsync(Guid id)
+ {
+ var cacheKey = CreateCacheKey(id);
+ var httpContext = HttpContextAccessor?.HttpContext;
+
+ if (httpContext != null && httpContext.Items[cacheKey] is TenantConfiguration tenantConfiguration)
+ {
+ return tenantConfiguration;
+ }
+
+ tenantConfiguration = await Cache.GetOrAddAsync(
+ cacheKey,
+ async () => CreateTenantConfiguration(await Proxy.Service.FindTenantByIdAsync(id)),
+ () => new DistributedCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow =
+ TimeSpan.FromMinutes(5) //TODO: Should be configurable.
+ }
+ );
+
+ if (httpContext != null)
+ {
+ httpContext.Items[cacheKey] = tenantConfiguration;
+ }
+
+ return tenantConfiguration;
+ }
+
+ public TenantConfiguration Find(string name)
+ {
+ return AsyncHelper.RunSync(() => FindAsync(name));
+ }
+
+ public TenantConfiguration Find(Guid id)
+ {
+ return AsyncHelper.RunSync(() => FindAsync(id));
+ }
+
+ protected virtual TenantConfiguration CreateTenantConfiguration(FindTenantResultDto tenantResultDto)
+ {
+ if (!tenantResultDto.Success || tenantResultDto.TenantId == null)
+ {
+ return null;
+ }
+
+ return new TenantConfiguration(tenantResultDto.TenantId.Value, tenantResultDto.Name);
+ }
+
+ protected virtual string CreateCacheKey(string tenantName)
+ {
+ return $"RemoteTenantStore_Name_{tenantName}";
+ }
+
+ protected virtual string CreateCacheKey(Guid tenantId)
+ {
+ return $"RemoteTenantStore_Id_{tenantId:N}";
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj
index 8141097dc6..173ff3cfbe 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo.Abp.AspNetCore.Mvc.Contracts.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.ContractsVolo.Abp.AspNetCore.Mvc.Contracts$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs
new file mode 100644
index 0000000000..d85622f0cf
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/FindTenantResultDto.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy
+{
+ [Serializable]
+ public class FindTenantResultDto
+ {
+ public bool Success { get; set; }
+
+ public Guid? TenantId { get; set; }
+
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/IAbpTenantAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/IAbpTenantAppService.cs
new file mode 100644
index 0000000000..eb02e84ceb
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/MultiTenancy/IAbpTenantAppService.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Services;
+
+namespace Volo.Abp.AspNetCore.Mvc.MultiTenancy
+{
+ public interface IAbpTenantAppService : IApplicationService
+ {
+ Task FindTenantByNameAsync(string name);
+
+ Task FindTenantByIdAsync(Guid id);
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
index fb549d3067..75fe4f23e7 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
@@ -227,17 +227,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
if (string.IsNullOrEmpty(TagHelper.Label))
{
- return await GetLabelAsHtmlUsingTagHelperAsync(context, output, isCheckbox) + GetRequiredSymbol(context, output, inputTag);
+ return await GetLabelAsHtmlUsingTagHelperAsync(context, output, isCheckbox) + GetRequiredSymbol(context, output);
}
var checkboxClass = isCheckbox ? "class=\"custom-control-label\" " : "";
return "" + GetRequiredSymbol(context, output, inputTag);
+ "" + GetRequiredSymbol(context, output);
}
- protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag)
+ protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output)
{
if (!TagHelper.DisplayRequiredSymbol)
{
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs
index f89d3c1fee..6f71842b61 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@@ -130,7 +130,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
if (!selectItems.Any(si => si.Selected))
{
- var itemToBeSelected = selectItems.FirstOrDefault(si => si.Value.ToString() == selectedValue);
+ var itemToBeSelected = selectItems.FirstOrDefault(si => si.Value == selectedValue);
if (itemToBeSelected != null)
{
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/SelectItems.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/SelectItems.cs
index 4b281770fd..c12eda1b21 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/SelectItems.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/SelectItems.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Rendering;
@@ -23,16 +23,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
while (properties.Count == 0)
{
explorer = explorer.Container;
- properties = explorer.Container.Properties.Where(p => p.Metadata.PropertyName.Equals(ItemsListPropertyName)).ToList();
-
if (explorer.Container == null)
{
return null;
}
+
+ properties = explorer.Container.Properties.Where(p => p.Metadata.PropertyName.Equals(ItemsListPropertyName)).ToList();
}
var selectItems = (properties.First().Model as IEnumerable).ToList();
-
+
return selectItems;
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj
index b9e1538272..f0eabc0025 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj
@@ -1,13 +1,13 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UI.BootstrapVolo.Abp.AspNetCore.Mvc.UI.Bootstrap
- true$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ trueLibrary
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Properties/launchSettings.json
new file mode 100644
index 0000000000..7bcd0a8aff
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53762/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc.UI.Bundling": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53765/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj
index 579d3a659b..4427b40dd6 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj
@@ -1,11 +1,13 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UI.BundlingVolo.Abp.AspNetCore.Mvc.UI.Bundling
+ true
+ Library
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs
index 3f99614aa9..653794bda8 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundleManager.cs
@@ -4,6 +4,7 @@ using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
@@ -23,7 +24,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
protected readonly BundlingOptions Options;
protected readonly BundleContributorOptions ContributorOptions;
protected readonly IWebContentFileProvider WebContentFileProvider;
- protected readonly IHostingEnvironment HostingEnvironment;
+ protected readonly IWebHostEnvironment HostingEnvironment;
protected readonly IScriptBundler ScriptBundler;
protected readonly IStyleBundler StyleBundler;
protected readonly IServiceProvider ServiceProvider;
@@ -36,7 +37,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
IOptions contributorOptions,
IScriptBundler scriptBundler,
IStyleBundler styleBundler,
- IHostingEnvironment hostingEnvironment,
+ IWebHostEnvironment hostingEnvironment,
IServiceProvider serviceProvider,
IDynamicFileProvider dynamicFileProvider,
IBundleCache bundleCache,
@@ -138,11 +139,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
DynamicFileProvider.AddOrUpdate(
new InMemoryFileInfo(
- Encoding.UTF8.GetBytes(bundleResult.Content),
"/wwwroot/" + bundleRelativePath, //TODO: get rid of wwwroot!
+ Encoding.UTF8.GetBytes(bundleResult.Content),
fileName
- )
- );
+ )
+ );
}
protected virtual bool IsBundlingEnabled()
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundlerBase.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundlerBase.cs
index 90e8606833..8c2258e1eb 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundlerBase.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/BundlerBase.cs
@@ -46,28 +46,33 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
private void AddFileToBundle(IBundlerContext context, StringBuilder bundleContentBuilder, string fileName)
{
+ string fileContent = null;
+
if (context.IsMinificationEnabled && !IsMinFile(fileName))
{
var minFileInfo = GetMinFileInfoOrNull(fileName);
if (minFileInfo != null)
{
- Logger.LogDebug($"- {fileName} ({minFileInfo.Length} bytes)");
- bundleContentBuilder.Append(NormalizedCode(minFileInfo.ReadAsString()));
- return;
+ Logger.LogDebug($"- {fileName} ({minFileInfo.Length} bytes) - already minified");
+ fileContent = minFileInfo.ReadAsString();
}
}
- var fileContent = GetFileContent(context, fileName);
- Logger.LogDebug($"- {fileName} ({fileContent.Length} bytes)");
-
- if (context.IsMinificationEnabled)
+ if (fileContent == null)
{
- var nonMinifiedSize = fileContent.Length;
- fileContent = Minifier.Minify(fileContent, context.BundleRelativePath);
- Logger.LogInformation($" -- Minified {context.BundleRelativePath} ({nonMinifiedSize} bytes -> {fileContent.Length} bytes)");
+ fileContent = GetFileContent(context, fileName);
+ Logger.LogDebug($"- {fileName} ({fileContent.Length} bytes) - non minified");
+
+ if (context.IsMinificationEnabled)
+ {
+ var nonMinifiedSize = fileContent.Length;
+ fileContent = Minifier.Minify(fileContent, context.BundleRelativePath);
+ Logger.LogInformation($" > Minified {fileName} ({nonMinifiedSize} bytes -> {fileContent.Length} bytes)");
+ }
}
- bundleContentBuilder.Append(NormalizedCode(fileContent));
+ fileContent = ProcessBeforeAddingToTheBundle(context, fileName, fileContent);
+ bundleContentBuilder.Append(fileContent);
}
protected virtual string GetFileContent(IBundlerContext context, string file)
@@ -99,9 +104,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling
return fileInfo.Exists ? fileInfo : null;
}
- protected virtual string NormalizedCode(string code)
+ protected virtual string ProcessBeforeAddingToTheBundle(IBundlerContext context, string filePath, string fileContent)
{
- return code;
+ return fileContent;
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Scripts/ScriptBundler.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Scripts/ScriptBundler.cs
index f5447dc8a3..7b2887eb90 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Scripts/ScriptBundler.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Scripts/ScriptBundler.cs
@@ -13,9 +13,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.Scripts
{
}
- protected override string NormalizedCode(string code)
+ protected override string ProcessBeforeAddingToTheBundle(IBundlerContext context, string filePath, string fileContent)
{
- return code.EnsureEndsWith(';') + Environment.NewLine;
+ return fileContent.EnsureEndsWith(';') + Environment.NewLine;
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Styles/StyleBundler.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Styles/StyleBundler.cs
index 768a1bb136..ac33211860 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Styles/StyleBundler.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/Styles/StyleBundler.cs
@@ -8,27 +8,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.Styles
{
public class StyleBundler : BundlerBase, IStyleBundler
{
- private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly IWebHostEnvironment _hostingEnvironment;
public override string FileExtension => "css";
- public StyleBundler(IWebContentFileProvider webContentFileProvider, ICssMinifier minifier, IHostingEnvironment hostingEnvironment)
+ public StyleBundler(IWebContentFileProvider webContentFileProvider, ICssMinifier minifier, IWebHostEnvironment hostingEnvironment)
: base(webContentFileProvider, minifier)
{
_hostingEnvironment = hostingEnvironment;
}
- protected override string GetFileContent(IBundlerContext context, string file)
+ public string GetAbsolutePath(string relativePath)
{
- return CssRelativePath.Adjust(
- base.GetFileContent(context, file),
- GetAbsolutePath(file),
- GetAbsolutePath(context.BundleRelativePath)
- );
+ return Path.Combine(_hostingEnvironment.ContentRootPath, "wwwroot", relativePath.RemovePreFix("/"));
}
- public string GetAbsolutePath(string relativePath)
+ protected override string ProcessBeforeAddingToTheBundle(IBundlerContext context, string filePath, string fileContent)
{
- return Path.Combine(_hostingEnvironment.ContentRootPath, "wwwroot", relativePath.RemovePreFix("/"));
+ return CssRelativePath.Adjust(
+ fileContent,
+ GetAbsolutePath(filePath),
+ GetAbsolutePath(context.BundleRelativePath)
+ );
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs
index 2224198dc4..981da4e4da 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperResourceService.cs
@@ -19,14 +19,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
protected IBundleManager BundleManager { get; }
protected IWebContentFileProvider WebContentFileProvider { get; }
- protected IHostingEnvironment HostingEnvironment { get; }
+ protected IWebHostEnvironment HostingEnvironment { get; }
protected readonly BundlingOptions Options;
protected AbpTagHelperResourceService(
IBundleManager bundleManager,
IWebContentFileProvider webContentFileProvider,
- IOptions options,
- IHostingEnvironment hostingEnvironment)
+ IOptions options,
+ IWebHostEnvironment hostingEnvironment)
{
BundleManager = bundleManager;
WebContentFileProvider = webContentFileProvider;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs
index b4f2ba1b77..8c8e2abc5a 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperScriptService.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Razor.TagHelpers;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.VirtualFileSystem;
@@ -14,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
IBundleManager bundleManager,
IWebContentFileProvider webContentFileProvider,
IOptions options,
- IHostingEnvironment hostingEnvironment
+ IWebHostEnvironment hostingEnvironment
) : base(
bundleManager,
webContentFileProvider,
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs
index 2a0946cfd2..400a75553f 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bundling/Volo/Abp/AspNetCore/Mvc/UI/Bundling/TagHelpers/AbpTagHelperStyleService.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Razor.TagHelpers;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.VirtualFileSystem;
@@ -14,7 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers
IBundleManager bundleManager,
IWebContentFileProvider webContentFileProvider,
IOptions options,
- IHostingEnvironment hostingEnvironment
+ IWebHostEnvironment hostingEnvironment
) : base(
bundleManager,
webContentFileProvider,
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs
new file mode 100644
index 0000000000..d0bea87196
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantAppService.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Services;
+using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
+using Volo.Abp.MultiTenancy;
+
+namespace Pages.Abp.MultiTenancy
+{
+ public class AbpTenantAppService : ApplicationService, IAbpTenantAppService
+ {
+ protected ITenantStore TenantStore { get; }
+
+ public AbpTenantAppService(ITenantStore tenantStore)
+ {
+ TenantStore = tenantStore;
+ }
+
+ public async Task FindTenantByNameAsync(string name)
+ {
+ var tenant = await TenantStore.FindAsync(name);
+
+ if (tenant == null)
+ {
+ return new FindTenantResultDto { Success = false };
+ }
+
+ return new FindTenantResultDto
+ {
+ Success = true,
+ TenantId = tenant.Id,
+ Name = tenant.Name
+ };
+ }
+
+ public async Task FindTenantByIdAsync(Guid id)
+ {
+ var tenant = await TenantStore.FindAsync(id);
+
+ if (tenant == null)
+ {
+ return new FindTenantResultDto { Success = false };
+ }
+
+ return new FindTenantResultDto
+ {
+ Success = true,
+ TenantId = tenant.Id,
+ Name = tenant.Name
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantController.cs
index d42cf82f9b..5da47875d9 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantController.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/AbpTenantController.cs
@@ -1,37 +1,34 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
-using Volo.Abp.MultiTenancy;
+using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
namespace Pages.Abp.MultiTenancy
{
[Route("api/abp/multi-tenancy")]
- public class AbpTenantController : AbpController
+ public class AbpTenantController : AbpController, IAbpTenantAppService
{
+ private readonly IAbpTenantAppService _abpTenantAppService;
- protected ITenantStore TenantStore { get; }
-
- public AbpTenantController(ITenantStore tenantStore)
+ public AbpTenantController(IAbpTenantAppService abpTenantAppService)
{
- TenantStore = tenantStore;
+ _abpTenantAppService = abpTenantAppService;
}
[HttpGet]
- [Route("find-tenant/{name}")]
- public async Task FindTenantAsync(string name)
+ [Route("find-tenant/{name}")] //TODO: Remove on v1.0
+ [Route("tenants/by-name/{name}")]
+ public async Task FindTenantByNameAsync(string name)
{
- var tenant = await TenantStore.FindAsync(name);
-
- if (tenant == null)
- {
- return new FindTenantResult{Success = false};
- }
+ return await _abpTenantAppService.FindTenantByNameAsync(name);
+ }
- return new FindTenantResult
- {
- Success = true,
- TenantId = tenant.Id
- };
+ [HttpGet]
+ [Route("tenants/by-id/{id}")]
+ public async Task FindTenantByIdAsync(Guid id)
+ {
+ return await _abpTenantAppService.FindTenantByIdAsync(id);
}
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/FindTenantResult.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/FindTenantResult.cs
deleted file mode 100644
index 59aef8335e..0000000000
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/FindTenantResult.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-
-namespace Pages.Abp.MultiTenancy
-{
- public class FindTenantResult
- {
- public bool Success { get; set; }
-
- public Guid? TenantId { get; set; }
- }
-}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj
index d0015b0e57..d55e9ec2df 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj
@@ -1,9 +1,9 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UI.MultiTenancyVolo.Abp.AspNetCore.Mvc.UI.MultiTenancy$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es-mx.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es-mx.json
new file mode 100644
index 0000000000..746f1dec0f
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/es-mx.json
@@ -0,0 +1,12 @@
+{
+ "culture": "es-MX",
+ "texts": {
+ "GivenTenantIsNotAvailable": "El inquilino {0} no está disponible",
+ "Tenant": "Inquilino",
+ "Switch": "cambiar",
+ "Name": "Nombre",
+ "SwitchTenant": "Cambiar inquilino",
+ "SwitchTenantHint": "Deje en blanco el campo nombre para cambiar el lado del host.",
+ "NotSelected": "No seleccionado"
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json
index 2acb0a275b..3b1643f03e 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/pt-BR.json
@@ -5,7 +5,7 @@
"Tenant": "Inquilino",
"Switch": "trocar",
"Name": "Nome",
- "SwitchTenantHint": "Deixe o campo de nome em branco para alternar para o lado do host.",
+ "SwitchTenantHint": "Deixe o campo de nome em branco para acessar o host.",
"NotSelected": "Não selecionado"
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Properties/launchSettings.json
new file mode 100644
index 0000000000..4ae9c1d2f1
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53766/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc.UI.Packages": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53768/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj
index cc4db153d6..b91f36abf0 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj
@@ -1,11 +1,13 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UI.PackagesVolo.Abp.AspNetCore.Mvc.UI.Packages
+ true
+ Library
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs
new file mode 100644
index 0000000000..e605f6e6ae
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Luxon/LuxonScriptContributor.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
+
+namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Luxon
+{
+ public class LuxonScriptContributor : BundleContributor
+ {
+ public override void ConfigureBundle(BundleConfigurationContext context)
+ {
+ context.Files.AddIfNotContains("/libs/luxon/luxon.min.js");
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml
index 329737c3d2..9f8c9856f5 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/UserMenu/Default.cshtml
@@ -21,7 +21,7 @@
var cssClass = string.IsNullOrEmpty(menuItem.CssClass) ? string.Empty : menuItem.CssClass;
var disabled = menuItem.IsDisabled ? "disabled" : string.Empty;
-
+
@menuItem.DisplayName
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj
index 654b191bec..f12072816a 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj
@@ -1,9 +1,9 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UI.Theme.BasicVolo.Abp.AspNetCore.Mvc.UI.Theme.Basic$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs
index e722de8ee3..d067281978 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Bundling/SharedThemeGlobalScriptContributor.cs
@@ -5,6 +5,7 @@ using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQuery;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryForm;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.JQueryValidationUnobtrusive;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Lodash;
+using Volo.Abp.AspNetCore.Mvc.UI.Packages.Luxon;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Select2;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.SweetAlert;
@@ -25,6 +26,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling
typeof(SweetalertScriptContributor),
typeof(ToastrScriptBundleContributor),
typeof(MalihuCustomScrollbarPluginScriptBundleContributor),
+ typeof(LuxonScriptContributor),
typeof(TimeagoScriptContributor)
)]
public class SharedThemeGlobalScriptContributor : BundleContributor
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj
index 898d7c1a0d..258feaf64a 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj
@@ -1,9 +1,9 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UI.Theme.SharedVolo.Abp.AspNetCore.Mvc.UI.Theme.Shared$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
@@ -32,10 +32,6 @@
-
-
-
-
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Properties/launchSettings.json
new file mode 100644
index 0000000000..e9779c3c37
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53761/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc.UI.Widgets": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53764/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj
index ae41d65026..75b83faaf2 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Widgets/Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj
@@ -1,11 +1,13 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UI.WidgetsVolo.Abp.AspNetCore.Mvc.UI.Widgets
+ true
+ Library
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
index 34367260f9..03e3d2bbd8 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
@@ -1,12 +1,14 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.Mvc.UIVolo.Abp.AspNetCore.Mvc.UI$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
+ true
+ Library
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs
index 62258329ad..8d62a4e188 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/RazorPages/AbpPageModel.cs
@@ -24,7 +24,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages
{
public IServiceProvider ServiceProvider { get; set; }
protected readonly object ServiceProviderLock = new object();
+
protected TService LazyGetRequiredService(ref TService reference)
+ => LazyGetRequiredService(typeof(TService), ref reference);
+
+ protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference)
{
if (reference == null)
{
@@ -32,7 +36,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages
{
if (reference == null)
{
- reference = ServiceProvider.GetRequiredService();
+ reference = (TRef)ServiceProvider.GetRequiredService(serviceType);
}
}
}
@@ -48,7 +52,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.RazorPages
public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager);
private IUnitOfWorkManager _unitOfWorkManager;
- public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper);
+ protected Type ObjectMapperContext { get; set; }
+ public IObjectMapper ObjectMapper
+ {
+ get
+ {
+ if (_objectMapper != null)
+ {
+ return _objectMapper;
+ }
+
+ if (ObjectMapperContext == null)
+ {
+ return LazyGetRequiredService(ref _objectMapper);
+ }
+
+ return LazyGetRequiredService(
+ typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext),
+ ref _objectMapper
+ );
+ }
+ }
private IObjectMapper _objectMapper;
public IGuidGenerator GuidGenerator => LazyGetRequiredService(ref _guidGenerator);
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Builder/AbpAspNetCoreMvcApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Builder/AbpAspNetCoreMvcApplicationBuilderExtensions.cs
index 8b1f6e9d49..9a19337c5f 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Builder/AbpAspNetCoreMvcApplicationBuilderExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Builder/AbpAspNetCoreMvcApplicationBuilderExtensions.cs
@@ -17,19 +17,15 @@ namespace Microsoft.AspNetCore.Builder
/// A reference to this instance after the operation has completed.
public static IApplicationBuilder UseMvcWithDefaultRouteAndArea(
this IApplicationBuilder app,
- Action additionalConfigurationAction = null)
+ Action additionalConfigurationAction = null)
{
- return app.UseMvc(routes =>
+ return app.UseEndpoints(endpoints =>
{
- routes.MapRoute(
- name: "defaultWithArea",
- template: "{area}/{controller=Home}/{action=Index}/{id?}");
+ endpoints.MapControllerRoute("defaultWithArea", "{area}/{controller=Home}/{action=Index}/{id?}");
+ endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
+ endpoints.MapRazorPages();
- routes.MapRoute(
- name: "default",
- template: "{controller=Home}/{action=Index}/{id?}");
-
- additionalConfigurationAction?.Invoke(routes);
+ additionalConfigurationAction?.Invoke(endpoints);
});
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.Mvc/Properties/launchSettings.json
new file mode 100644
index 0000000000..3c84fd21f2
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53767/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53769/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
index 138189864b..a90b113dc3 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
@@ -1,15 +1,17 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.MvcVolo.Abp.AspNetCore.Mvc$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
@@ -22,8 +24,8 @@
-
-
+
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
index fa317d7211..b094505f6c 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
@@ -3,12 +3,11 @@ using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Infrastructure;
-using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
-using Newtonsoft.Json.Serialization;
+using Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -16,7 +15,6 @@ using System.Reflection;
using Volo.Abp.ApiVersioning;
using Volo.Abp.AspNetCore.Mvc.Conventions;
using Volo.Abp.AspNetCore.Mvc.DependencyInjection;
-using Volo.Abp.AspNetCore.Mvc.Json;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.DependencyInjection;
@@ -45,8 +43,8 @@ namespace Volo.Abp.AspNetCore.Mvc
{
//Configure Razor
context.Services.Insert(0,
- ServiceDescriptor.Singleton>(
- new ConfigureOptions(options =>
+ ServiceDescriptor.Singleton>(
+ new ConfigureOptions(options =>
{
options.FileProviders.Add(
new RazorViewEngineVirtualFileProvider(
@@ -78,6 +76,7 @@ namespace Volo.Abp.AspNetCore.Mvc
);
var mvcBuilder = context.Services.AddMvc()
+ .AddRazorRuntimeCompilation()
.AddDataAnnotationsLocalization(options =>
{
@@ -86,7 +85,7 @@ namespace Volo.Abp.AspNetCore.Mvc
var resourceType = abpMvcDataAnnotationsLocalizationOptions.AssemblyResources.GetOrDefault(type.Assembly);
return factory.Create(resourceType ?? type);
};
- })
+ })
.AddViewLocalization(); //TODO: How to configure from the application? Also, consider to move to a UI module since APIs does not care about it.
context.Services.ExecutePreConfiguredActions(mvcBuilder);
@@ -112,10 +111,10 @@ namespace Volo.Abp.AspNetCore.Mvc
mvcOptions.AddAbp(context.Services);
});
- Configure(jsonOptions =>
- {
- jsonOptions.SerializerSettings.ContractResolver = new AbpMvcJsonContractResolver(context.Services);
- });
+ //Configure(jsonOptions => @3.0.0!
+ //{
+ // jsonOptions.SerializerSettings.ContractResolver = new AbpMvcJsonContractResolver(context.Services);
+ //});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs
index 943d0d6e3f..c3e5c61f36 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs
@@ -23,7 +23,11 @@ namespace Volo.Abp.AspNetCore.Mvc
{
public IServiceProvider ServiceProvider { get; set; }
protected readonly object ServiceProviderLock = new object();
+
protected TService LazyGetRequiredService(ref TService reference)
+ => LazyGetRequiredService(typeof(TService), ref reference);
+
+ protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference)
{
if (reference == null)
{
@@ -31,7 +35,7 @@ namespace Volo.Abp.AspNetCore.Mvc
{
if (reference == null)
{
- reference = ServiceProvider.GetRequiredService();
+ reference = (TRef)ServiceProvider.GetRequiredService(serviceType);
}
}
}
@@ -42,7 +46,27 @@ namespace Volo.Abp.AspNetCore.Mvc
public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager);
private IUnitOfWorkManager _unitOfWorkManager;
- public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper);
+ protected Type ObjectMapperContext { get; set; }
+ public IObjectMapper ObjectMapper
+ {
+ get
+ {
+ if (_objectMapper != null)
+ {
+ return _objectMapper;
+ }
+
+ if (ObjectMapperContext == null)
+ {
+ return LazyGetRequiredService(ref _objectMapper);
+ }
+
+ return LazyGetRequiredService(
+ typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext),
+ ref _objectMapper
+ );
+ }
+ }
private IObjectMapper _objectMapper;
public IGuidGenerator GuidGenerator => LazyGetRequiredService(ref _guidGenerator);
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs
index 883fea8046..e29cb5fbef 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs
@@ -1,15 +1,55 @@
-using Microsoft.AspNetCore.Mvc;
+using System;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.ObjectMapping;
namespace Volo.Abp.AspNetCore.Mvc
{
public abstract class AbpViewComponent : ViewComponent
{
- public IObjectMapper ObjectMapper { get; set; }
+ public IServiceProvider ServiceProvider { get; set; }
+ protected readonly object ServiceProviderLock = new object();
- protected AbpViewComponent()
+ protected TService LazyGetRequiredService(ref TService reference)
+ => LazyGetRequiredService(typeof(TService), ref reference);
+
+ protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference)
{
-
+ if (reference == null)
+ {
+ lock (ServiceProviderLock)
+ {
+ if (reference == null)
+ {
+ reference = (TRef)ServiceProvider.GetRequiredService(serviceType);
+ }
+ }
+ }
+
+ return reference;
+ }
+
+ protected Type ObjectMapperContext { get; set; }
+ public IObjectMapper ObjectMapper
+ {
+ get
+ {
+ if (_objectMapper != null)
+ {
+ return _objectMapper;
+ }
+
+ if (ObjectMapperContext == null)
+ {
+ return LazyGetRequiredService(ref _objectMapper);
+ }
+
+ return LazyGetRequiredService(
+ typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext),
+ ref _objectMapper
+ );
+ }
}
+ private IObjectMapper _objectMapper;
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
index 2d04e316cb..621072b6ba 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs
@@ -4,8 +4,8 @@ using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
-using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.Options;
using Volo.Abp.Application.Services;
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs
index d49cb6d142..526470b3ad 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs
@@ -7,24 +7,43 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
{
- public class AbpAspNetCoreMvcConventionalRegistrar : DefaultConventionalRegistrar
+ public class AbpAspNetCoreMvcConventionalRegistrar : ConventionalRegistrarBase
{
- protected override ServiceLifetime? GetServiceLifetimeFromClassHierarcy(Type type)
+ public override void AddType(IServiceCollection services, Type type)
{
- var lifeTime = base.GetServiceLifetimeFromClassHierarcy(type);
- if (lifeTime != null)
+ if (IsConventionalRegistrationDisabled(type))
{
- return lifeTime;
+ return;
}
- if (IsController(type) ||
- IsPageModel(type) ||
- IsViewComponent(type))
+ if (!IsMvcService(type))
{
- return ServiceLifetime.Transient;
+ return;
}
- return null;
+ var lifeTime = GetMvcServiceLifetime(type);
+
+ var serviceTypes = ExposedServiceExplorer.GetExposedServices(type);
+
+ TriggerServiceExposing(services, type, serviceTypes);
+
+ foreach (var serviceType in serviceTypes)
+ {
+ var serviceDescriptor = ServiceDescriptor.Describe(serviceType, type, lifeTime);
+ services.Add(serviceDescriptor);
+ }
+ }
+
+ protected virtual bool IsMvcService(Type type)
+ {
+ return IsController(type) ||
+ IsPageModel(type) ||
+ IsViewComponent(type);
+ }
+
+ protected virtual ServiceLifetime GetMvcServiceLifetime(Type type)
+ {
+ return ServiceLifetime.Transient;
}
private static bool IsPageModel(Type type)
diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore.TestBase/Properties/launchSettings.json
new file mode 100644
index 0000000000..fca5708e7b
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53783/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.TestBase": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53784/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj
index 291a36d6b6..7ec3846531 100644
--- a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo.Abp.AspNetCore.TestBase.csproj
@@ -1,15 +1,17 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCore.TestBaseVolo.Abp.AspNetCore.TestBase$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
@@ -20,7 +22,7 @@
-
+
diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/DynamicProxying/AspNetCoreTestDynamicProxyHttpClientFactory.cs b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/DynamicProxying/AspNetCoreTestDynamicProxyHttpClientFactory.cs
index e8463e16cc..71de80b018 100644
--- a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/DynamicProxying/AspNetCoreTestDynamicProxyHttpClientFactory.cs
+++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/DynamicProxying/AspNetCoreTestDynamicProxyHttpClientFactory.cs
@@ -8,11 +8,11 @@ namespace Volo.Abp.AspNetCore.TestBase.DynamicProxying
public class AspNetCoreTestDynamicProxyHttpClientFactory : IDynamicProxyHttpClientFactory, ITransientDependency
{
private readonly ITestServerAccessor _testServerAccessor;
- private readonly IHttpClientFactory _httpClientFactory;
- public AspNetCoreTestDynamicProxyHttpClientFactory(ITestServerAccessor testServerAccessor, IHttpClientFactory httpClientFactory) {
+ public AspNetCoreTestDynamicProxyHttpClientFactory(
+ ITestServerAccessor testServerAccessor)
+ {
_testServerAccessor = testServerAccessor;
- _httpClientFactory = httpClientFactory;
}
public HttpClient Create()
@@ -20,7 +20,8 @@ namespace Volo.Abp.AspNetCore.TestBase.DynamicProxying
return _testServerAccessor.Server.CreateClient();
}
- public HttpClient Create(string name) {
+ public HttpClient Create(string name)
+ {
return Create();
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
index c139c49ba1..e2c930f39c 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
@@ -1,9 +1,6 @@
using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
using JetBrains.Annotations;
-using Microsoft.AspNetCore.Localization;
+using Microsoft.AspNetCore.RequestLocalization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.AspNetCore.Auditing;
@@ -11,9 +8,6 @@ using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Tracing;
using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.DependencyInjection;
-using Volo.Abp.Localization;
-using Volo.Abp.Settings;
-using Volo.Abp.Threading;
namespace Microsoft.AspNetCore.Builder
{
@@ -50,40 +44,11 @@ namespace Microsoft.AspNetCore.Builder
public static IApplicationBuilder UseAbpRequestLocalization(this IApplicationBuilder app, Action optionsAction = null)
{
- IReadOnlyList languages;
- string defaultLanguage;
+ app.ApplicationServices
+ .GetRequiredService()
+ .InitLocalizationOptions(optionsAction);
- using (var scope = app.ApplicationServices.CreateScope())
- {
- var languageProvider = scope.ServiceProvider.GetRequiredService();
- languages = AsyncHelper.RunSync(() => languageProvider.GetLanguagesAsync());
-
- var settingProvider = scope.ServiceProvider.GetRequiredService();
- defaultLanguage = AsyncHelper.RunSync(() => settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage));
- }
-
- var options = !languages.Any()
- ? new RequestLocalizationOptions()
- : new RequestLocalizationOptions
- {
- DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages),
-
- SupportedCultures = languages
- .Select(l => l.CultureName)
- .Distinct()
- .Select(c => new CultureInfo(c))
- .ToArray(),
-
- SupportedUICultures = languages
- .Select(l => l.UiCultureName)
- .Distinct()
- .Select(c => new CultureInfo(c))
- .ToArray()
- };
-
- optionsAction?.Invoke(options);
-
- return app.UseRequestLocalization(options);
+ return app.UseMiddleware();
}
public static IApplicationBuilder UseAbpExceptionHandling(this IApplicationBuilder app)
@@ -96,17 +61,5 @@ namespace Microsoft.AspNetCore.Builder
app.Properties[ExceptionHandlingMiddlewareMarker] = true;
return app.UseMiddleware();
}
-
- private static RequestCulture DefaultGetRequestCulture(string defaultLanguage, IReadOnlyList languages)
- {
- if (defaultLanguage == null)
- {
- var firstLanguage = languages.First();
- return new RequestCulture(firstLanguage.CultureName, firstLanguage.UiCultureName);
- }
-
- var (cultureName, uiCultureName) = LocalizationSettingHelper.ParseLanguageSetting(defaultLanguage);
- return new RequestCulture(cultureName, uiCultureName);
- }
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Hosting/AbpHostingEnvironmentExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Hosting/AbpHostingEnvironmentExtensions.cs
index 7e8bd32055..039e819b38 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Hosting/AbpHostingEnvironmentExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Hosting/AbpHostingEnvironmentExtensions.cs
@@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Hosting
public static class AbpHostingEnvironmentExtensions
{
public static IConfigurationRoot BuildConfiguration(
- this IHostingEnvironment env,
+ this IWebHostEnvironment env,
ConfigurationBuilderOptions options = null)
{
options = options ?? new ConfigurationBuilderOptions();
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
new file mode 100644
index 0000000000..75d903557e
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
@@ -0,0 +1,35 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Localization;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Volo.Abp.DependencyInjection;
+
+namespace Microsoft.AspNetCore.RequestLocalization
+{
+ public class AbpRequestLocalizationMiddleware : IMiddleware, ITransientDependency
+ {
+ private readonly IAbpRequestLocalizationOptionsProvider _requestLocalizationOptionsProvider;
+ private readonly ILoggerFactory _loggerFactory;
+
+ public AbpRequestLocalizationMiddleware(
+ IAbpRequestLocalizationOptionsProvider requestLocalizationOptionsProvider,
+ ILoggerFactory loggerFactory)
+ {
+ _requestLocalizationOptionsProvider = requestLocalizationOptionsProvider;
+ _loggerFactory = loggerFactory;
+ }
+
+ public async Task InvokeAsync(HttpContext context, RequestDelegate next)
+ {
+ var middleware = new RequestLocalizationMiddleware(
+ next,
+ new OptionsWrapper(_requestLocalizationOptionsProvider.GetLocalizationOptions()),
+ _loggerFactory
+ );
+
+ await middleware.Invoke(context);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
new file mode 100644
index 0000000000..730f6e3937
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Localization;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Localization;
+using Volo.Abp.Settings;
+using Volo.Abp.Threading;
+
+namespace Microsoft.AspNetCore.RequestLocalization
+{
+ public class DefaultAbpRequestLocalizationOptionsProvider : IAbpRequestLocalizationOptionsProvider, ISingletonDependency
+ {
+ private readonly IServiceProvider _serviceProvider;
+ private Lazy _lazyRequestLocalizationOptions;
+
+ public DefaultAbpRequestLocalizationOptionsProvider(IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ public void InitLocalizationOptions(Action optionsAction = null)
+ {
+ _lazyRequestLocalizationOptions = new Lazy(() =>
+ {
+ using (var serviceScope = _serviceProvider.CreateScope())
+ {
+ var languageProvider = serviceScope.ServiceProvider.GetRequiredService();
+ var settingProvider = serviceScope.ServiceProvider.GetRequiredService();
+
+ var languages = AsyncHelper.RunSync(languageProvider.GetLanguagesAsync);
+ var defaultLanguage = AsyncHelper.RunSync(() =>
+ settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage));
+
+ var options = !languages.Any()
+ ? new RequestLocalizationOptions()
+ : new RequestLocalizationOptions
+ {
+ DefaultRequestCulture = DefaultGetRequestCulture(defaultLanguage, languages),
+
+ SupportedCultures = languages
+ .Select(l => l.CultureName)
+ .Distinct()
+ .Select(c => new CultureInfo(c))
+ .ToArray(),
+
+ SupportedUICultures = languages
+ .Select(l => l.UiCultureName)
+ .Distinct()
+ .Select(c => new CultureInfo(c))
+ .ToArray()
+ };
+
+ optionsAction?.Invoke(options);
+ return options;
+ }
+ }, true);
+ }
+
+ public RequestLocalizationOptions GetLocalizationOptions()
+ {
+ return _lazyRequestLocalizationOptions.Value;
+ }
+
+ private static RequestCulture DefaultGetRequestCulture(string defaultLanguage, IReadOnlyList languages)
+ {
+ if (defaultLanguage == null)
+ {
+ var firstLanguage = languages.First();
+ return new RequestCulture(firstLanguage.CultureName, firstLanguage.UiCultureName);
+ }
+
+ var (cultureName, uiCultureName) = LocalizationSettingHelper.ParseLanguageSetting(defaultLanguage);
+ return new RequestCulture(cultureName, uiCultureName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs
new file mode 100644
index 0000000000..5179bb48ee
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/IAbpRequestLocalizationOptionsProvider.cs
@@ -0,0 +1,12 @@
+using System;
+using Microsoft.AspNetCore.Builder;
+
+namespace Microsoft.AspNetCore.RequestLocalization
+{
+ public interface IAbpRequestLocalizationOptionsProvider
+ {
+ void InitLocalizationOptions(Action optionsAction = null);
+
+ RequestLocalizationOptions GetLocalizationOptions();
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/Extensions/DependencyInjection/AbpAspNetCoreServiceCollectionExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/Extensions/DependencyInjection/AbpAspNetCoreServiceCollectionExtensions.cs
index 859bdcdbaf..cf11ab32c3 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/Extensions/DependencyInjection/AbpAspNetCoreServiceCollectionExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/Extensions/DependencyInjection/AbpAspNetCoreServiceCollectionExtensions.cs
@@ -5,9 +5,9 @@ namespace Microsoft.Extensions.DependencyInjection
{
public static class AbpAspNetCoreServiceCollectionExtensions
{
- public static IHostingEnvironment GetHostingEnvironment(this IServiceCollection services)
+ public static IWebHostEnvironment GetHostingEnvironment(this IServiceCollection services)
{
- return services.GetSingletonInstance();
+ return services.GetSingletonInstance();
}
public static IConfigurationRoot BuildConfiguration(this IServiceCollection services, ConfigurationBuilderOptions options = null)
diff --git a/framework/src/Volo.Abp.AspNetCore/Properties/launchSettings.json b/framework/src/Volo.Abp.AspNetCore/Properties/launchSettings.json
new file mode 100644
index 0000000000..4098e788cd
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:53374/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:53375/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
index 2584654ce8..d6a67c14be 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
+++ b/framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
@@ -1,15 +1,17 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.AspNetCoreVolo.Abp.AspNetCore$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
@@ -26,13 +28,4 @@
-
-
-
-
-
-
-
-
-
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/ApplicationInitializationContextExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/ApplicationInitializationContextExtensions.cs
index ed41314209..616afc8427 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/ApplicationInitializationContextExtensions.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/ApplicationInitializationContextExtensions.cs
@@ -13,9 +13,9 @@ namespace Volo.Abp
return context.ServiceProvider.GetRequiredService>().Value;
}
- public static IHostingEnvironment GetEnvironment(this ApplicationInitializationContext context)
+ public static IWebHostEnvironment GetEnvironment(this ApplicationInitializationContext context)
{
- return context.ServiceProvider.GetRequiredService();
+ return context.ServiceProvider.GetRequiredService();
}
public static ILoggerFactory GetLoggerFactory(this ApplicationInitializationContext context)
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
index c7f4252352..af22ff2f7e 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -42,9 +42,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
{
var errorInfo = CreateErrorInfoWithoutCode(exception);
- if (exception is IHasErrorCode)
+ if (exception is IHasErrorCode hasErrorCodeException)
{
- errorInfo.Code = (exception as IHasErrorCode).Code;
+ errorInfo.Code = hasErrorCodeException.Code;
}
return errorInfo;
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs
index b837007996..ebc7446d68 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs
@@ -14,14 +14,14 @@ namespace Volo.Abp.AspNetCore.VirtualFileSystem
{
private readonly IVirtualFileProvider _virtualFileProvider;
private readonly IFileProvider _fileProvider;
- private readonly IHostingEnvironment _hostingEnvironment;
+ private readonly IWebHostEnvironment _hostingEnvironment;
private string _rootPath = "/wwwroot"; //TODO: How to handle wwwroot naming?
protected AspNetCoreContentOptions Options { get; }
public WebContentFileProvider(
- IVirtualFileProvider virtualFileProvider,
- IHostingEnvironment hostingEnvironment,
+ IVirtualFileProvider virtualFileProvider,
+ IWebHostEnvironment hostingEnvironment,
IOptions options)
{
_virtualFileProvider = virtualFileProvider;
diff --git a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj
index 1be1b27c4f..04a5494625 100644
--- a/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj
+++ b/framework/src/Volo.Abp.Authorization/Volo.Abp.Authorization.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
index 060fe03dc4..5a9c3fa4db 100644
--- a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
+++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/AbpAuthorizationModule.cs
@@ -25,7 +25,7 @@ namespace Volo.Abp.Authorization
public override void ConfigureServices(ServiceConfigurationContext context)
{
- context.Services.AddAuthorization();
+ context.Services.AddAuthorizationCore();
context.Services.AddSingleton();
diff --git a/framework/src/Volo.Abp.AutoMapper/Microsoft/Extensions/DependencyInjection/AbpAutoMapperServiceCollectionExtensions.cs b/framework/src/Volo.Abp.AutoMapper/Microsoft/Extensions/DependencyInjection/AbpAutoMapperServiceCollectionExtensions.cs
new file mode 100644
index 0000000000..c3e909486b
--- /dev/null
+++ b/framework/src/Volo.Abp.AutoMapper/Microsoft/Extensions/DependencyInjection/AbpAutoMapperServiceCollectionExtensions.cs
@@ -0,0 +1,23 @@
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Volo.Abp.AutoMapper;
+using Volo.Abp.ObjectMapping;
+
+namespace Microsoft.Extensions.DependencyInjection
+{
+ public static class AbpAutoMapperServiceCollectionExtensions
+ {
+ public static IServiceCollection AddAutoMapperObjectMapper(this IServiceCollection services)
+ {
+ return services.Replace(
+ ServiceDescriptor.Transient()
+ );
+ }
+
+ public static IServiceCollection AddAutoMapperObjectMapper(this IServiceCollection services)
+ {
+ return services.Replace(
+ ServiceDescriptor.Transient, AutoMapperAutoObjectMappingProvider>()
+ );
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs
index ebf517dc65..ba3ef2ada8 100644
--- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs
+++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AbpAutoMapperModule.cs
@@ -12,6 +12,8 @@ namespace Volo.Abp.AutoMapper
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
+ context.Services.AddAutoMapperObjectMapper();
+
var mapperAccessor = new MapperAccessor();
context.Services.AddSingleton(_ => mapperAccessor);
context.Services.AddSingleton(_ => mapperAccessor);
diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperAutoObjectMappingProvider.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperAutoObjectMappingProvider.cs
new file mode 100644
index 0000000000..ca5b7c0ea1
--- /dev/null
+++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperAutoObjectMappingProvider.cs
@@ -0,0 +1,32 @@
+using Volo.Abp.ObjectMapping;
+
+namespace Volo.Abp.AutoMapper
+{
+ public class AutoMapperAutoObjectMappingProvider : AutoMapperAutoObjectMappingProvider, IAutoObjectMappingProvider
+ {
+ public AutoMapperAutoObjectMappingProvider(IMapperAccessor mapperAccessor)
+ : base(mapperAccessor)
+ {
+ }
+ }
+
+ public class AutoMapperAutoObjectMappingProvider : IAutoObjectMappingProvider
+ {
+ public IMapperAccessor MapperAccessor { get; }
+
+ public AutoMapperAutoObjectMappingProvider(IMapperAccessor mapperAccessor)
+ {
+ MapperAccessor = mapperAccessor;
+ }
+
+ public virtual TDestination Map(object source)
+ {
+ return MapperAccessor.Mapper.Map(source);
+ }
+
+ public virtual TDestination Map(TSource source, TDestination destination)
+ {
+ return MapperAccessor.Mapper.Map(source, destination);
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperObjectMapper.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperObjectMapper.cs
deleted file mode 100644
index 73fad64113..0000000000
--- a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/AutoMapper/AutoMapperObjectMapper.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.DependencyInjection;
-using Volo.Abp.ObjectMapping;
-
-namespace Volo.Abp.AutoMapper
-{
- [Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
- public class AutoMapperObjectMapper : DefaultObjectMapper
- {
- protected IMapperAccessor MapperAccessor { get; }
-
- public AutoMapperObjectMapper(IMapperAccessor mapperAccessor, IServiceProvider serviceProvider)
- : base(serviceProvider)
- {
- MapperAccessor = mapperAccessor;
- }
-
- protected override TDestination AutoMap(object source)
- {
- return MapperAccessor.Mapper.Map(source);
- }
-
- protected override TDestination AutoMap(TSource source, TDestination destination)
- {
- return MapperAccessor.Mapper.Map(source, destination);
- }
- }
-}
diff --git a/framework/src/Volo.Abp.AutoMapper/Volo/Abp/ObjectMapping/AbpAutoMapperObjectMapperExtensions.cs b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/ObjectMapping/AbpAutoMapperObjectMapperExtensions.cs
new file mode 100644
index 0000000000..7e4e91751f
--- /dev/null
+++ b/framework/src/Volo.Abp.AutoMapper/Volo/Abp/ObjectMapping/AbpAutoMapperObjectMapperExtensions.cs
@@ -0,0 +1,23 @@
+using AutoMapper;
+using Volo.Abp.AutoMapper;
+
+namespace Volo.Abp.ObjectMapping
+{
+ public static class AbpAutoMapperObjectMapperExtensions
+ {
+ public static IMapper GetMapper(this IObjectMapper objectMapper)
+ {
+ return objectMapper.AutoObjectMappingProvider.GetMapper();
+ }
+
+ public static IMapper GetMapper(this IAutoObjectMappingProvider autoObjectMappingProvider)
+ {
+ if (autoObjectMappingProvider is AutoMapperAutoObjectMappingProvider autoMapperAutoObjectMappingProvider)
+ {
+ return autoMapperAutoObjectMappingProvider.MapperAccessor.Mapper;
+ }
+
+ throw new AbpException($"Given object is not an instance of {typeof(AutoMapperAutoObjectMappingProvider).AssemblyQualifiedName}. The type of the given object it {autoObjectMappingProvider.GetType().AssemblyQualifiedName}");
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj
index 9470f72e19..bc7c696c3d 100644
--- a/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj
+++ b/framework/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj b/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
index f4417ae910..d064b3c0ea 100644
--- a/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
+++ b/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
@@ -1,4 +1,4 @@
-
+
@@ -14,7 +14,7 @@
-
+
diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs
index 6be122be8f..0400da8c72 100644
--- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs
+++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheOptions.cs
@@ -6,6 +6,11 @@ namespace Volo.Abp.Caching
{
public class CacheOptions
{
+ ///
+ /// Cache key prefix.
+ ///
+ public string KeyPrefix { get; set; }
+
///
/// Global Cache entry options.
///
@@ -21,6 +26,7 @@ namespace Volo.Abp.Caching
{
CacheConfigurators = new List>();
GlobalCacheEntryOptions = new DistributedCacheEntryOptions();
+ KeyPrefix = "";
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
index 7b93dc5c23..caa51aeac1 100644
--- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
+++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
@@ -405,7 +405,7 @@ namespace Volo.Abp.Caching
protected virtual string NormalizeKey(string key)
{
- var normalizedKey = "c:" + CacheName + ",k:" + key;
+ var normalizedKey = "c:" + CacheName + ",k:" + _cacheOption.KeyPrefix + key;
if (!IgnoreMultiTenancy && CurrentTenant.Id.HasValue)
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
index 056f87f897..f02f03d502 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliService.cs
@@ -169,33 +169,42 @@ namespace Volo.Abp.Cli
}
}
+ private static bool IsGlobalTool(string toolPath)
+ {
+ var globalPaths = new[] { @"%USERPROFILE%\.dotnet\tools\", "%HOME%/.dotnet/tools/", };
+ return globalPaths.Select(Environment.ExpandEnvironmentVariables).Contains(toolPath);
+ }
+
private void LogNewVersionInfo(UpdateChannel updateChannel, SemanticVersion latestVersion, string toolPath)
{
- Logger.LogWarning(
- $"ABP CLI has a newer {updateChannel.ToString().ToLowerInvariant()} version {latestVersion}, please update to get the latest features and fixes.");
- Logger.LogWarning("");
+ var toolPathArg = IsGlobalTool(toolPath) ? "-g" : $"--tool-path {toolPath}";
+
+ Logger.LogWarning($"ABP CLI has a newer {updateChannel.ToString().ToLowerInvariant()} version {latestVersion}, please update to get the latest features and fixes.");
+ Logger.LogWarning(string.Empty);
Logger.LogWarning("Update Command: ");
// Update command doesn't support prerelease versions https://github.com/dotnet/sdk/issues/2551 workaround is to uninstall & install
switch (updateChannel)
{
case UpdateChannel.Stable:
- Logger.LogWarning($" dotnet tool update --tool-path {toolPath} Volo.Abp.Cli");
+ Logger.LogWarning($"dotnet tool update {toolPathArg} Volo.Abp.Cli");
break;
case UpdateChannel.Prerelease:
- Logger.LogWarning($" dotnet tool uninstall --tool-path {toolPath} Volo.Abp.Cli");
- Logger.LogWarning($" dotnet tool install --tool-path {toolPath} --version {latestVersion} Volo.Abp.Cli");
+ Logger.LogWarning($"dotnet tool uninstall {toolPathArg} Volo.Abp.Cli");
+ Logger.LogWarning($"dotnet tool install {toolPathArg} Volo.Abp.Cli --version {latestVersion}");
break;
case UpdateChannel.Nightly:
- Logger.LogWarning($" dotnet tool uninstall --tool-path {toolPath} Volo.Abp.Cli");
- Logger.LogWarning(
- $" dotnet tool install --tool-path {toolPath} --add-source https://www.myget.org/F/abp-nightly/api/v3/index.json --version {latestVersion} Volo.Abp.Cli");
+ case UpdateChannel.Development:
+ Logger.LogWarning($"dotnet tool uninstall {toolPathArg} Volo.Abp.Cli");
+ Logger.LogWarning($"dotnet tool install {toolPathArg} Volo.Abp.Cli --add-source https://www.myget.org/F/abp-nightly/api/v3/index.json --version {latestVersion}");
break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(updateChannel), updateChannel, null);
}
- Logger.LogWarning("");
+ Logger.LogWarning(string.Empty);
}
protected enum UpdateChannel
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
index 030f474c96..5efbc358f0 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/LoginCommand.cs
@@ -38,7 +38,7 @@ namespace Volo.Abp.Cli.Commands
if (password.IsNullOrWhiteSpace())
{
throw new CliUsageException(
- "Password name is missing!" +
+ "Password is missing!" +
Environment.NewLine + Environment.NewLine +
GetUsageInfo()
);
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
index f75a2eae4c..6921f8e4d8 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
@@ -37,21 +37,32 @@ namespace Volo.Abp.Cli.Commands
);
}
- Logger.LogInformation("Creating a new project...");
+ Logger.LogInformation("Creating your project...");
Logger.LogInformation("Project name: " + commandLineArgs.Target);
- commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
+ var template = commandLineArgs.Options.GetOrNull(Options.Template.Short, Options.Template.Long);
+ if (template != null)
+ {
+ Logger.LogInformation("Template: " + template);
+ }
- var result = await ProjectBuilder.BuildAsync(
- new ProjectBuildArgs(
- SolutionName.Parse(commandLineArgs.Target),
- commandLineArgs.Options.GetOrNull(Options.Template.Short, Options.Template.Long),
- commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long),
- GetDatabaseProvider(commandLineArgs),
- GetUiFramework(commandLineArgs),
- commandLineArgs.Options
- )
- );
+ var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
+ if (version != null)
+ {
+ Logger.LogInformation("Version: " + version);
+ }
+
+ var databaseProvider = GetDatabaseProvider(commandLineArgs);
+ if (databaseProvider != DatabaseProvider.NotSpecified)
+ {
+ Logger.LogInformation("Database provider: " + databaseProvider);
+ }
+
+ var uiFramework = GetUiFramework(commandLineArgs);
+ if (uiFramework != UiFramework.NotSpecified)
+ {
+ Logger.LogInformation("UI Framework: " + uiFramework);
+ }
var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
if (outputFolder != null)
@@ -68,6 +79,21 @@ namespace Volo.Abp.Cli.Commands
outputFolder = Directory.GetCurrentDirectory();
}
+ Logger.LogInformation("Output folder: " + outputFolder);
+
+ commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
+
+ var result = await ProjectBuilder.BuildAsync(
+ new ProjectBuildArgs(
+ SolutionName.Parse(commandLineArgs.Target),
+ template,
+ version,
+ databaseProvider,
+ uiFramework,
+ commandLineArgs.Options
+ )
+ );
+
using (var templateFileStream = new MemoryStream(result.ZipContent))
{
using (var zipInputStream = new ZipInputStream(templateFileStream))
@@ -101,8 +127,7 @@ namespace Volo.Abp.Cli.Commands
}
}
- Logger.LogInformation($"Successfully created the project '{commandLineArgs.Target}'");
- Logger.LogInformation($"The output folder is: '{outputFolder}'");
+ Logger.LogInformation($"'{commandLineArgs.Target}' has been successfully created to '{outputFolder}'");
}
public string GetUsageInfo()
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
index d6983a5db1..bc0b39a85a 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Http/CliHttpClient.cs
@@ -2,6 +2,7 @@
using System.IO;
using System.Net.Http;
using System.Text;
+using IdentityModel.Client;
namespace Volo.Abp.Cli.Http
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
index e48e7853d4..22cd692ec3 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/AbpIoApiKeyService.cs
@@ -15,7 +15,7 @@ namespace Volo.Abp.Cli.Licensing
protected IJsonSerializer JsonSerializer { get; }
- public async Task GetApiKeyOrNullAsync()
+ public async Task GetApiKeyOrNullAsync()
{
using (var client = new CliHttpClient())
{
@@ -29,7 +29,7 @@ namespace Volo.Abp.Cli.Licensing
}
var responseContent = await response.Content.ReadAsStringAsync();
- return JsonSerializer.Deserialize(responseContent).ApiKey;
+ return JsonSerializer.Deserialize(responseContent);
}
}
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs
index 9e97859148..0fb8058c61 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/IApiKeyService.cs
@@ -5,6 +5,6 @@ namespace Volo.Abp.Cli.Licensing
{
public interface IApiKeyService
{
- Task GetApiKeyOrNullAsync();
+ Task GetApiKeyOrNullAsync();
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs
index 5f763b15f9..49cb44d13a 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/ProjectBuildPipelineBuilder.cs
@@ -1,4 +1,5 @@
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
+using Volo.Abp.Cli.ProjectBuilding.Templates.App;
namespace Volo.Abp.Cli.ProjectBuilding.Building
{
@@ -19,6 +20,12 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
pipeline.Steps.Add(new TemplateCodeDeleteStep());
pipeline.Steps.Add(new SolutionRenameStep());
+
+ if (context.Template.Name == AppProTemplate.TemplateName)
+ {
+ pipeline.Steps.Add(new LicenseCodeReplaceStep());
+ }
+
pipeline.Steps.Add(new CreateProjectResultZipStep());
return pipeline;
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/LicenseCodeReplaceStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/LicenseCodeReplaceStep.cs
new file mode 100644
index 0000000000..b2dee80867
--- /dev/null
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/LicenseCodeReplaceStep.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Volo.Abp.Cli.ProjectBuilding.Files;
+
+namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
+{
+ public class LicenseCodeReplaceStep : ProjectBuildPipelineStep
+ {
+ public override void Execute(ProjectBuildContext context)
+ {
+ var licenseCode = context.BuildArgs.ExtraProperties.GetOrDefault("license-code");
+
+ var appSettingsJsonFiles = context.Files.Where(f =>
+ f.Name.EndsWith("appsettings.json", StringComparison.OrdinalIgnoreCase));
+
+ foreach (var appSettingsJson in appSettingsJsonFiles)
+ {
+ appSettingsJson.ReplaceText(@"", licenseCode);
+ }
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs
index 057b03370e..cb790ba91f 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/NugetReferenceReplaceStep.cs
@@ -19,8 +19,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
new NugetReferenceReplacer(
context.Files,
- "MyCompanyName",
- "MyProjectName",
+ "MyCompanyName.MyProjectName",
nugetPackageVersion
).Run();
}
@@ -47,19 +46,16 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
private class NugetReferenceReplacer
{
private readonly List _entries;
- private readonly string _companyNamePlaceHolder;
- private readonly string _projectNamePlaceHolder;
+ private readonly string _companyAndProjectNamePlaceHolder;
private readonly string _nugetPackageVersion;
public NugetReferenceReplacer(
List entries,
- string companyNamePlaceHolder,
- string projectNamePlaceHolder,
+ string companyAndProjectNamePlaceHolder,
string nugetPackageVersion)
{
_entries = entries;
- _companyNamePlaceHolder = companyNamePlaceHolder;
- _projectNamePlaceHolder = projectNamePlaceHolder;
+ _companyAndProjectNamePlaceHolder = companyAndProjectNamePlaceHolder;
_nugetPackageVersion = nugetPackageVersion;
}
@@ -96,7 +92,7 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
var oldNodeIncludeValue = oldNode.Attributes["Include"].Value;
// ReSharper disable once PossibleNullReferenceException : Can not be null because nodes are selected with include attribute filter in previous method
- if (oldNodeIncludeValue.Contains($"{_companyNamePlaceHolder}.{_projectNamePlaceHolder}"))
+ if (oldNodeIncludeValue.Contains($"{_companyAndProjectNamePlaceHolder}"))
{
continue;
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
index 076ee084d1..cb6f29de7e 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/SolutionRenameStep.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using Volo.Abp.Cli.ProjectBuilding.Files;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs
index 1807e8345a..6c9b6fa145 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuilder.cs
@@ -53,10 +53,15 @@ namespace Volo.Abp.Cli.ProjectBuilding
args.Version
);
- var apiKey = await ApiKeyService.GetApiKeyOrNullAsync();
- if (apiKey != null)
+ var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync();
+ if (apiKeyResult?.ApiKey != null)
{
- args.ExtraProperties["api-key"] = apiKey;
+ args.ExtraProperties["api-key"] = apiKeyResult.ApiKey;
+ }
+
+ if (apiKeyResult?.LicenseCode != null)
+ {
+ args.ExtraProperties["license-code"] = apiKeyResult.LicenseCode;
}
var context = new ProjectBuildContext(
@@ -69,7 +74,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
if (!templateInfo.DocumentUrl.IsNullOrEmpty())
{
- Logger.LogInformation("Check the documentation of this template: " + templateInfo.DocumentUrl);
+ Logger.LogInformation("Check out the documents at " + templateInfo.DocumentUrl);
}
// Exclude unwanted or known options.
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/UpdateNuGetConfigStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/UpdateNuGetConfigStep.cs
index 428aaa6c96..1a40eff341 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/UpdateNuGetConfigStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/UpdateNuGetConfigStep.cs
@@ -29,7 +29,10 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.App
return;
}
- file.ReplaceText("{api-key}", apiKey);
+ const string placeHolder = "";
+ var nugetSourceTag = $"";
+
+ file.ReplaceText(placeHolder, nugetSourceTag);
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs
index db39a660ce..4cf3209955 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs
@@ -29,8 +29,7 @@ namespace Volo.Abp.Cli.ProjectModification
var csFiles = new DirectoryInfo(csprojFileDirectory)
.GetFiles("*.cs", SearchOption.AllDirectories)
- .Where(f => !f.DirectoryName.StartsWith(binFile))
- .Where(f => !f.DirectoryName.StartsWith(objFile))
+ .Where(f => f.DirectoryName != null && (!f.DirectoryName.StartsWith(binFile) || !f.DirectoryName.StartsWith(objFile)))
.Select(f => f.FullName)
.ToList();
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs
index 548290df5c..4a313e784d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectFinder.cs
@@ -83,8 +83,11 @@ namespace Volo.Abp.Cli.ProjectModification
public static string[] GetProjectFiles(string solutionFile)
{
- var baseProjectFolder = GetBaseProjectFolder(solutionFile);
- return Directory.GetFiles(baseProjectFolder, "*.csproj", SearchOption.AllDirectories);
+ return GetBaseProjectFolders(solutionFile)
+ .Select(baseProjectFolder =>
+ Directory.GetFiles(baseProjectFolder, "*.csproj", SearchOption.AllDirectories))
+ .SelectMany(files => files)
+ .ToArray();
}
public static string[] GetAssemblyNames(string[] projectFiles)
@@ -118,16 +121,33 @@ namespace Volo.Abp.Cli.ProjectModification
return null;
}
- private static string GetBaseProjectFolder(string solutionFile)
+ private static string[] GetBaseProjectFolders(string solutionFile)
{
+ var projectFolders = new List();
var baseFolder = Path.GetDirectoryName(solutionFile);
+ if (baseFolder == null)
+ {
+ return projectFolders.ToArray();
+ }
+
var srcFolder = Path.Combine(baseFolder, "src");
if (Directory.Exists(srcFolder))
{
- baseFolder = srcFolder;
+ projectFolders.Add(srcFolder);
+ }
+
+ var testFolder = Path.Combine(baseFolder, "test");
+ if (Directory.Exists(testFolder))
+ {
+ projectFolders.Add(testFolder);
+ }
+
+ if (!projectFolders.Any())
+ {
+ projectFolders.Add(baseFolder);
}
- return baseFolder;
+ return projectFolders.ToArray();
}
}
}
diff --git a/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj b/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj
index f28c2554b2..01d1a210ef 100644
--- a/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj
+++ b/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj
@@ -4,7 +4,7 @@
Exe
- netcoreapp2.2
+ netcoreapp3.0trueabp
diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationBuilderOptions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationBuilderOptions.cs
index 101dad5c95..aa55c0e876 100644
--- a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationBuilderOptions.cs
+++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationBuilderOptions.cs
@@ -30,5 +30,10 @@ namespace Microsoft.Extensions.Configuration
/// Base path to read the configuration file indicated by .
///
public string BasePath { get; set; }
+
+ ///
+ /// Prefix for the environment variables.
+ ///
+ public string EnvironmentVariablesPrefix { get; set; }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs
index b2d005685e..37e721f1af 100644
--- a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs
+++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs
@@ -23,7 +23,7 @@ namespace Microsoft.Extensions.Configuration
builder = builder.AddJsonFile($"{options.FileName}.{options.EnvironmentName}.json", optional: true, reloadOnChange: true);
}
- builder = builder.AddEnvironmentVariables();
+ builder = builder.AddEnvironmentVariables(options.EnvironmentVariablesPrefix);
if (options.EnvironmentName == "Development")
{
diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
index a7a2a4a55a..b405e10f59 100644
--- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
+++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
@@ -11,18 +11,18 @@
-
-
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs
index f9cbf3c13c..8a47e7fa17 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/ConventionalRegistrarBase.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
@@ -31,5 +32,23 @@ namespace Volo.Abp.DependencyInjection
}
public abstract void AddType(IServiceCollection services, Type type);
+
+ protected virtual bool IsConventionalRegistrationDisabled(Type type)
+ {
+ return type.IsDefined(typeof(DisableConventionalRegistrationAttribute), true);
+ }
+
+ protected virtual void TriggerServiceExposing(IServiceCollection services, Type implementationType, List serviceTypes)
+ {
+ var exposeActions = services.GetExposingActionList();
+ if (exposeActions.Any())
+ {
+ var args = new OnServiceExposingContext(implementationType, serviceTypes);
+ foreach (var action in exposeActions)
+ {
+ action(args);
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs
index 9c5ee06d81..15361ece62 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
@@ -48,25 +46,7 @@ namespace Volo.Abp.DependencyInjection
}
}
}
-
- protected virtual void TriggerServiceExposing(IServiceCollection services, Type type, List serviceTypes)
- {
- var exposeActions = services.GetExposingActionList();
- if (exposeActions.Any())
- {
- var args = new OnServiceExposingContext(type, serviceTypes);
- foreach (var action in exposeActions)
- {
- action(args);
- }
- }
- }
-
- protected virtual bool IsConventionalRegistrationDisabled(Type type)
- {
- return type.IsDefined(typeof(DisableConventionalRegistrationAttribute), true);
- }
-
+
protected virtual DependencyAttribute GetDependencyAttributeOrNull(Type type)
{
return type.GetCustomAttribute(true);
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs
index 32c8980c54..45f02e08c8 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/IAbpModule.cs
@@ -2,7 +2,7 @@
namespace Volo.Abp.Modularity
{
- public interface IAbpModule : ISingletonDependency
+ public interface IAbpModule
{
void ConfigureServices(ServiceConfigurationContext context);
}
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Threading/AsyncHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Threading/AsyncHelper.cs
index 2b40cd6790..dc678b8fd4 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/Threading/AsyncHelper.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/Threading/AsyncHelper.cs
@@ -24,7 +24,7 @@ namespace Volo.Abp.Threading
public static bool IsTaskOrTaskOfT([NotNull] this Type type)
{
- return type == typeof(Task) || type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>);
+ return type == typeof(Task) || (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>));
}
///
diff --git a/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj b/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj
index 849dc33c60..0b9ba3f9a9 100644
--- a/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj
+++ b/framework/src/Volo.Abp.Dapper/Volo.Abp.Dapper.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netstandard2.1Volo.Abp.DapperVolo.Abp.Dapper$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs
index 698f2c0ea3..0de23c826b 100644
--- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs
+++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs
@@ -34,7 +34,11 @@ namespace Volo.Abp.Application.Services
{
public IServiceProvider ServiceProvider { get; set; }
protected readonly object ServiceProviderLock = new object();
+
protected TService LazyGetRequiredService(ref TService reference)
+ => LazyGetRequiredService(typeof(TService), ref reference);
+
+ protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference)
{
if (reference == null)
{
@@ -42,7 +46,7 @@ namespace Volo.Abp.Application.Services
{
if (reference == null)
{
- reference = ServiceProvider.GetRequiredService();
+ reference = (TRef)ServiceProvider.GetRequiredService(serviceType);
}
}
}
@@ -57,7 +61,27 @@ namespace Volo.Abp.Application.Services
public IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager);
private IUnitOfWorkManager _unitOfWorkManager;
- public IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper);
+ protected Type ObjectMapperContext { get; set; }
+ public IObjectMapper ObjectMapper
+ {
+ get
+ {
+ if (_objectMapper != null)
+ {
+ return _objectMapper;
+ }
+
+ if (ObjectMapperContext == null)
+ {
+ return LazyGetRequiredService(ref _objectMapper);
+ }
+
+ return LazyGetRequiredService(
+ typeof(IObjectMapper<>).MakeGenericType(ObjectMapperContext),
+ ref _objectMapper
+ );
+ }
+ }
private IObjectMapper _objectMapper;
public IGuidGenerator GuidGenerator { get; set; }
diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs
index 3a64760a0f..237e89aa53 100644
--- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs
+++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/CrudAppService.cs
@@ -188,8 +188,7 @@ namespace Volo.Abp.Application.Services
protected virtual IQueryable ApplySorting(IQueryable query, TGetListInput input)
{
//Try to sort query if available
- var sortInput = input as ISortedResultRequest;
- if (sortInput != null)
+ if (input is ISortedResultRequest sortInput)
{
if (!sortInput.Sorting.IsNullOrWhiteSpace())
{
@@ -215,15 +214,13 @@ namespace Volo.Abp.Application.Services
protected virtual IQueryable ApplyPaging(IQueryable query, TGetListInput input)
{
//Try to use paging if available
- var pagedInput = input as IPagedResultRequest;
- if (pagedInput != null)
+ if (input is IPagedResultRequest pagedInput)
{
return query.PageBy(pagedInput);
}
//Try to limit query result if available
- var limitedInput = input as ILimitedResultRequest;
- if (limitedInput != null)
+ if (input is ILimitedResultRequest limitedInput)
{
return query.Take(limitedInput.MaxResultCount);
}
@@ -289,7 +286,11 @@ namespace Volo.Abp.Application.Services
return;
}
- entityWithGuidId.Id = GuidGenerator.Create();
+ EntityHelper.TrySetId(
+ entityWithGuidId,
+ () => GuidGenerator.Create(),
+ true
+ );
}
///
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRoot.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRoot.cs
index 8f566f1b6b..bc4830bc03 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRoot.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRoot.cs
@@ -28,5 +28,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual Guid? LastModifierId { get; set; }
+
+ protected AuditedAggregateRoot()
+ {
+
+ }
+
+ protected AuditedAggregateRoot(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRootWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRootWithUser.cs
index 107fb35b68..ec490fbb50 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRootWithUser.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedAggregateRootWithUser.cs
@@ -32,5 +32,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual TUser LastModifier { get; set; }
+
+ protected AuditedAggregateRootWithUser()
+ {
+
+ }
+
+ protected AuditedAggregateRootWithUser(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntity.cs
index 2ccc1aa1e2..0423551509 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntity.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntity.cs
@@ -28,5 +28,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual Guid? LastModifierId { get; set; }
+
+ protected AuditedEntity()
+ {
+
+ }
+
+ protected AuditedEntity(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntityWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntityWithUser.cs
index 76002b2114..fd6aeb9dd9 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntityWithUser.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/AuditedEntityWithUser.cs
@@ -32,5 +32,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual TUser LastModifier { get; set; }
+
+ protected AuditedEntityWithUser()
+ {
+
+ }
+
+ protected AuditedEntityWithUser(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs
index 29c01bd466..084c907606 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRoot.cs
@@ -28,5 +28,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual Guid? CreatorId { get; set; }
+
+ protected CreationAuditedAggregateRoot()
+ {
+
+ }
+
+ protected CreationAuditedAggregateRoot(TKey id)
+ : base(id)
+ {
+
+ }
}
}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRootWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRootWithUser.cs
index 1084360749..7d491d7be1 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRootWithUser.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedAggregateRootWithUser.cs
@@ -24,5 +24,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
{
///
public virtual TUser Creator { get; set; }
+
+ protected CreationAuditedAggregateRootWithUser()
+ {
+
+ }
+
+ protected CreationAuditedAggregateRootWithUser(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntity.cs
index 1ab527dc2a..41802c78b7 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntity.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntity.cs
@@ -28,5 +28,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual Guid? CreatorId { get; set; }
+
+ protected CreationAuditedEntity()
+ {
+
+ }
+
+ protected CreationAuditedEntity(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntityWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntityWithUser.cs
index 0989dfeac4..45d844efa7 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntityWithUser.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/CreationAuditedEntityWithUser.cs
@@ -24,5 +24,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
{
///
public virtual TUser Creator { get; set; }
+
+ protected CreationAuditedEntityWithUser()
+ {
+
+ }
+
+ protected CreationAuditedEntityWithUser(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs
index 397a425629..9231efd3ab 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRoot.cs
@@ -34,5 +34,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual DateTime? DeletionTime { get; set; }
+
+ protected FullAuditedAggregateRoot()
+ {
+
+ }
+
+ protected FullAuditedAggregateRoot(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs
index d379a78240..cb0be46421 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs
@@ -38,5 +38,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public TUser LastModifier { get; set; }
+
+ protected FullAuditedAggregateRootWithUser()
+ {
+
+ }
+
+ protected FullAuditedAggregateRootWithUser(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntity.cs
index 20b07b85b5..ada5cc9eed 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntity.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntity.cs
@@ -34,5 +34,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public virtual DateTime? DeletionTime { get; set; }
+
+ protected FullAuditedEntity()
+ {
+
+ }
+
+ protected FullAuditedEntity(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs
index 9aba520480..12458ebf99 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs
@@ -38,5 +38,16 @@ namespace Volo.Abp.Domain.Entities.Auditing
///
public TUser LastModifier { get; set; }
+
+ protected FullAuditedEntityWithUser()
+ {
+
+ }
+
+ protected FullAuditedEntityWithUser(TKey id)
+ : base(id)
+ {
+
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/DisableIdGenerationAttribute.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/DisableIdGenerationAttribute.cs
new file mode 100644
index 0000000000..1d823ca177
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/DisableIdGenerationAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Volo.Abp.Domain.Entities
+{
+ public class DisableIdGenerationAttribute : Attribute
+ {
+
+ }
+}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs
index c96e305d45..b78a5aa400 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Entity.cs
@@ -23,7 +23,7 @@ namespace Volo.Abp.Domain.Entities
public abstract class Entity : Entity, IEntity
{
///
- public virtual TKey Id { get; set; }
+ public virtual TKey Id { get; protected set; }
protected Entity()
{
@@ -35,8 +35,7 @@ namespace Volo.Abp.Domain.Entities
Id = id;
}
- ///
- public override bool Equals(object obj)
+ public bool EntityEquals(object obj)
{
if (obj == null || !(obj is Entity))
{
@@ -73,33 +72,7 @@ namespace Volo.Abp.Domain.Entities
return Id.Equals(other.Id);
}
-
- ///
- public override int GetHashCode()
- {
- if (Id == null)
- {
- return 0;
- }
-
- return Id.GetHashCode();
- }
-
- public static bool operator ==(Entity left, Entity right)
- {
- if (Equals(left, null))
- {
- return Equals(right, null);
- }
-
- return left.Equals(right);
- }
-
- public static bool operator !=(Entity left, Entity right)
- {
- return !(left == right);
- }
-
+
public override object[] GetKeys()
{
return new object[] {Id};
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs
index b6558f34d1..dd483f5d7b 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/EntityHelper.cs
@@ -81,5 +81,32 @@ namespace Volo.Abp.Domain.Entities
var lambdaBody = Expression.Equal(leftExpression, rightExpression);
return Expression.Lambda>(lambdaBody, lambdaParam);
}
+
+ public static void TrySetId(
+ IEntity entity,
+ Func idFactory,
+ bool checkForDisableGuidGenerationAttribute = false)
+ {
+ //TODO: Can be optimized (by caching per entity type)?
+ var entityType = entity.GetType();
+ var idProperty = entityType.GetProperty(
+ nameof(entity.Id)
+ );
+
+ if (idProperty == null)
+ {
+ return;
+ }
+
+ if (checkForDisableGuidGenerationAttribute)
+ {
+ if (idProperty.IsDefined(typeof(DisableIdGenerationAttribute), true))
+ {
+ return;
+ }
+ }
+
+ idProperty.SetValue(entity, idFactory());
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs
index 5b386599ef..b15ea3d6a4 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Options;
using System.Collections.Generic;
+using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.EventBus.Distributed;
@@ -9,14 +10,14 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
{
public class EntityToEtoMapper : IEntityToEtoMapper, ITransientDependency
{
- protected IObjectMapper ObjectMapper { get; }
+ protected IHybridServiceScopeFactory HybridServiceScopeFactory { get; }
protected DistributedEventBusOptions Options { get; }
public EntityToEtoMapper(
IOptions options,
- IObjectMapper objectMapper)
+ IHybridServiceScopeFactory hybridServiceScopeFactory)
{
- ObjectMapper = objectMapper;
+ HybridServiceScopeFactory = hybridServiceScopeFactory;
Options = options.Value;
}
@@ -31,15 +32,23 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
}
var entityType = ProxyHelper.UnProxy(entity).GetType();
- var etoType = Options.EtoMappings.GetOrDefault(entityType);
- if (etoType == null)
+ var etoMappingItem = Options.EtoMappings.GetOrDefault(entityType);
+ if (etoMappingItem == null)
{
var keys = entity.GetKeys().JoinAsString(",");
return new EntityEto(entityType.FullName, keys);
}
- //TODO: Also add KeysAsString property to resulting json for compatibility with the EntityEto!
- return ObjectMapper.Map(entityType, etoType, entityObj);
+ using (var scope = HybridServiceScopeFactory.CreateScope())
+ {
+ var objectMapperType = etoMappingItem.ObjectMappingContextType == null
+ ? typeof(IObjectMapper)
+ : typeof(IObjectMapper<>).MakeGenericType(etoMappingItem.ObjectMappingContextType);
+
+ var objectMapper = (IObjectMapper) scope.ServiceProvider.GetRequiredService(objectMapperType);
+
+ return objectMapper.Map(entityType, etoMappingItem.EtoType, entityObj);
+ }
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntity.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntity.cs
index 58e607b120..890c5227bd 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntity.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/IEntity.cs
@@ -22,6 +22,6 @@
///
/// Unique identifier for this entity.
///
- TKey Id { get; set; }
+ TKey Id { get; }
}
}
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs
index ea84b41792..00a4c7ddd3 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Values/ValueObject.cs
@@ -7,23 +7,9 @@ namespace Volo.Abp.Domain.Values
public abstract class ValueObject
{
- protected static bool EqualOperator(ValueObject left, ValueObject right)
- {
- if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
- {
- return false;
- }
- return ReferenceEquals(left, null) || left.Equals(right);
- }
-
- protected static bool NotEqualOperator(ValueObject left, ValueObject right)
- {
- return !(EqualOperator(left, right));
- }
-
protected abstract IEnumerable
-
+
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj
index 458ffda849..ab658d9e75 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj
+++ b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo.Abp.EntityFrameworkCore.SqlServer.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netstandard2.1Volo.Abp.EntityFrameworkCore.SqlServerVolo.Abp.EntityFrameworkCore.SqlServer$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
@@ -18,7 +18,7 @@
-
+
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj
index b22bc48301..37f80a5b44 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj
+++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo.Abp.EntityFrameworkCore.Sqlite.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netstandard2.1Volo.Abp.EntityFrameworkCore.SqliteVolo.Abp.EntityFrameworkCore.Sqlite$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
@@ -14,7 +14,7 @@
-
+
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj
index a472c09690..03602ee77b 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo.Abp.EntityFrameworkCore.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netstandard2.1Volo.Abp.EntityFrameworkCoreVolo.Abp.EntityFrameworkCore$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
@@ -19,8 +19,8 @@
-
-
+
+
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
index 23b4e36b75..e26624747c 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
@@ -258,14 +258,14 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
public virtual TEntity Find(TKey id, bool includeDetails = true)
{
return includeDetails
- ? WithDetails().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id))
+ ? WithDetails().FirstOrDefault(e => e.Id.Equals(id))
: DbSet.Find(id);
}
public virtual async Task FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return includeDetails
- ? await WithDetails().FirstOrDefaultAsync(EntityHelper.CreateEqualityExpressionForId(id), GetCancellationToken(cancellationToken))
+ ? await WithDetails().FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken))
: await DbSet.FindAsync(new object[] { id }, GetCancellationToken(cancellationToken));
}
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
index 1ed5f3eaed..3604913301 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
@@ -9,7 +9,6 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Newtonsoft.Json;
@@ -282,20 +281,37 @@ namespace Volo.Abp.EntityFrameworkCore
protected virtual void CheckAndSetId(EntityEntry entry)
{
- //Set GUID Ids
- var entity = entry.Entity as IEntity;
- if (entity != null && entity.Id == Guid.Empty)
+ if (entry.Entity is IEntity entityWithGuidId)
{
- var dbGeneratedAttr = ReflectionHelper
- .GetSingleAttributeOrDefault(
- entry.Property("Id").Metadata.PropertyInfo
- );
+ TrySetGuidId(entry, entityWithGuidId);
+ }
+ }
- if (dbGeneratedAttr == null || dbGeneratedAttr.DatabaseGeneratedOption == DatabaseGeneratedOption.None)
- {
- entity.Id = GuidGenerator.Create();
- }
+ protected virtual void TrySetGuidId(EntityEntry entry, IEntity entity)
+ {
+ if (entity.Id != default)
+ {
+ return;
}
+
+ var idProperty = entry.Property("Id").Metadata.PropertyInfo;
+
+ //Check for DatabaseGeneratedAttribute
+ var dbGeneratedAttr = ReflectionHelper
+ .GetSingleAttributeOrDefault(
+ idProperty
+ );
+
+ if (dbGeneratedAttr != null && dbGeneratedAttr.DatabaseGeneratedOption != DatabaseGeneratedOption.None)
+ {
+ return;
+ }
+
+ EntityHelper.TrySetId(
+ entity,
+ () => GuidGenerator.Create(),
+ true
+ );
}
protected virtual void SetCreationAuditProperties(EntityEntry entry)
@@ -494,12 +510,12 @@ namespace Volo.Abp.EntityFrameworkCore
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
{
- expression = e => !IsSoftDeleteFilterEnabled || !((ISoftDelete) e).IsDeleted;
+ expression = e => !IsSoftDeleteFilterEnabled || !EF.Property(e, "IsDeleted");
}
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity)))
{
- Expression> multiTenantFilter = e => !IsMultiTenantFilterEnabled || ((IMultiTenant) e).TenantId == CurrentTenantId;
+ Expression> multiTenantFilter = e => !IsMultiTenantFilterEnabled || EF.Property(e, "TenantId") == CurrentTenantId;
expression = expression == null ? multiTenantFilter : CombineExpressions(expression, multiTenantFilter);
}
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IEfCoreDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IEfCoreDbContext.cs
index 7cba957724..761e15b6f2 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IEfCoreDbContext.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/IEfCoreDbContext.cs
@@ -35,9 +35,9 @@ namespace Volo.Abp.EntityFrameworkCore
EntityEntry Add([NotNull] TEntity entity) where TEntity : class;
- Task AddAsync([NotNull] object entity, CancellationToken cancellationToken = default);
+ ValueTask AddAsync([NotNull] object entity, CancellationToken cancellationToken = default);
- Task> AddAsync([NotNull] TEntity entity, CancellationToken cancellationToken = default) where TEntity : class;
+ ValueTask> AddAsync([NotNull] TEntity entity, CancellationToken cancellationToken = default) where TEntity : class;
void AddRange([NotNull] IEnumerable entities);
@@ -59,13 +59,13 @@ namespace Volo.Abp.EntityFrameworkCore
TEntity Find([NotNull] params object[] keyValues) where TEntity : class;
- Task FindAsync([NotNull] Type entityType, [NotNull] object[] keyValues, CancellationToken cancellationToken);
+ ValueTask FindAsync([NotNull] Type entityType, [NotNull] object[] keyValues, CancellationToken cancellationToken);
- Task FindAsync([NotNull] object[] keyValues, CancellationToken cancellationToken) where TEntity : class;
+ ValueTask FindAsync([NotNull] object[] keyValues, CancellationToken cancellationToken) where TEntity : class;
- Task FindAsync([NotNull] params object[] keyValues) where TEntity : class;
+ ValueTask FindAsync([NotNull] params object[] keyValues) where TEntity : class;
- Task FindAsync([NotNull] Type entityType, [NotNull] params object[] keyValues);
+ ValueTask FindAsync([NotNull] Type entityType, [NotNull] params object[] keyValues);
EntityEntry Remove([NotNull] TEntity entity) where TEntity : class;
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs
index b9bcd3ed8b..aae99d0cb7 100644
--- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs
@@ -3,11 +3,11 @@ using System.Collections.Generic;
namespace Volo.Abp.EventBus.Distributed
{
- public class EtoMappingDictionary : Dictionary
+ public class EtoMappingDictionary : Dictionary
{
- public void Add()
+ public void Add(Type objectMappingContextType = null)
{
- this[typeof(TEntity)] = typeof(TEntityEto);
+ this[typeof(TEntity)] = new EtoMappingDictionaryItem(typeof(TEntityEto), objectMappingContextType);
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionaryItem.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionaryItem.cs
new file mode 100644
index 0000000000..d634c44b4d
--- /dev/null
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionaryItem.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Volo.Abp.EventBus.Distributed
+{
+ public class EtoMappingDictionaryItem
+ {
+ public Type EtoType { get; }
+
+ public Type ObjectMappingContextType { get; }
+
+ public EtoMappingDictionaryItem(Type etoType, Type objectMappingContextType = null)
+ {
+ EtoType = etoType;
+ ObjectMappingContextType = objectMappingContextType;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs
index 9641b438b0..d51e4728ca 100644
--- a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs
+++ b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs
@@ -1,14 +1,20 @@
using System;
+using System.Collections.Generic;
using FluentValidation;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.FluentValidation
{
- public class AbpFluentValidationConventionalRegistrar : DefaultConventionalRegistrar
+ public class AbpFluentValidationConventionalRegistrar : ConventionalRegistrarBase
{
public override void AddType(IServiceCollection services, Type type)
{
+ if (IsConventionalRegistrationDisabled(type))
+ {
+ return;
+ }
+
if (!typeof(IValidator).IsAssignableFrom(type))
{
return;
@@ -20,8 +26,12 @@ namespace Volo.Abp.FluentValidation
return;
}
+ var serviceType = typeof(IValidator<>).MakeGenericType(validatingType);
+
+ TriggerServiceExposing(services, type, new List{ serviceType });
+
services.AddTransient(
- typeof(IValidator<>).MakeGenericType(validatingType),
+ serviceType,
type
);
}
diff --git a/framework/src/Volo.Abp.Http.Client.IdentityModel/Properties/launchSettings.json b/framework/src/Volo.Abp.Http.Client.IdentityModel/Properties/launchSettings.json
new file mode 100644
index 0000000000..d56e5c65b7
--- /dev/null
+++ b/framework/src/Volo.Abp.Http.Client.IdentityModel/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:52306/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.Http.Client.IdentityModel": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:52307/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo.Abp.Http.Client.IdentityModel.csproj b/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo.Abp.Http.Client.IdentityModel.csproj
index c515007b30..de2e24e072 100644
--- a/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo.Abp.Http.Client.IdentityModel.csproj
+++ b/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo.Abp.Http.Client.IdentityModel.csproj
@@ -1,15 +1,17 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.Http.Client.IdentityModelVolo.Abp.Http.Client.IdentityModel$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
diff --git a/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo/Abp/Http/Client/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs b/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo/Abp/Http/Client/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs
index eab45ca96b..25763efbd5 100644
--- a/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo/Abp/Http/Client/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs
+++ b/framework/src/Volo.Abp.Http.Client.IdentityModel/Volo/Abp/Http/Client/IdentityModel/IdentityModelRemoteServiceHttpClientAuthenticator.cs
@@ -1,5 +1,5 @@
-using System.Net.Http;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
+using IdentityModel.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
diff --git a/framework/src/Volo.Abp.Http.Client/Properties/launchSettings.json b/framework/src/Volo.Abp.Http.Client/Properties/launchSettings.json
new file mode 100644
index 0000000000..3cef3cf668
--- /dev/null
+++ b/framework/src/Volo.Abp.Http.Client/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:52208/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.Http.Client": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:52209/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj b/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj
index 1c7f727e18..3555a61a8a 100644
--- a/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj
+++ b/framework/src/Volo.Abp.Http.Client/Volo.Abp.Http.Client.csproj
@@ -1,21 +1,22 @@
-
+
- netstandard2.0
+ netcoreapp3.0Volo.Abp.Http.ClientVolo.Abp.Http.Client$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalse
+ true
+ Library
-
-
+
diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs
index 882bf94cb0..9b9c8e804c 100644
--- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs
+++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs
@@ -92,7 +92,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
if (!response.IsSuccessStatusCode)
{
- throw new AbpException("Remote service returns error!");
+ throw new AbpException("Remote service returns error! StatusCode = " + response.StatusCode);
}
var content = await response.Content.ReadAsStringAsync();
diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj
index fa2bddfcc6..0d8ef11967 100644
--- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj
+++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
index c5ce0b854d..681b65bcd9 100644
--- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
+++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
@@ -92,7 +92,7 @@ namespace Volo.Abp.IdentityModel
ClientOptions.IdentityClients.Default;
}
- protected virtual async Task GetDiscoveryResponse(
+ protected virtual async Task GetDiscoveryResponse(
IdentityClientConfiguration configuration)
{
using (var httpClient = new HttpClient())
@@ -109,7 +109,7 @@ namespace Volo.Abp.IdentityModel
}
protected virtual async Task GetTokenResponse(
- DiscoveryResponse discoveryResponse,
+ DiscoveryDocumentResponse discoveryResponse,
IdentityClientConfiguration configuration)
{
using (var httpClient = new HttpClient())
@@ -132,7 +132,7 @@ namespace Volo.Abp.IdentityModel
}
}
- protected virtual Task CreatePasswordTokenRequestAsync(DiscoveryResponse discoveryResponse, IdentityClientConfiguration configuration)
+ protected virtual Task CreatePasswordTokenRequestAsync(DiscoveryDocumentResponse discoveryResponse, IdentityClientConfiguration configuration)
{
var request = new PasswordTokenRequest
{
@@ -150,7 +150,7 @@ namespace Volo.Abp.IdentityModel
}
protected virtual Task CreateClientCredentialsTokenRequestAsync(
- DiscoveryResponse discoveryResponse,
+ DiscoveryDocumentResponse discoveryResponse,
IdentityClientConfiguration configuration)
{
var request = new ClientCredentialsTokenRequest
@@ -166,7 +166,7 @@ namespace Volo.Abp.IdentityModel
return Task.FromResult(request);
}
- protected virtual Task AddParametersToRequestAsync(IdentityClientConfiguration configuration, Request request)
+ protected virtual Task AddParametersToRequestAsync(IdentityClientConfiguration configuration, ProtocolRequest request)
{
foreach (var pair in configuration.Where(p => p.Key.StartsWith("[o]", StringComparison.OrdinalIgnoreCase)))
{
diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json
index 9dfaedb32f..b6ff1bb26c 100644
--- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json
+++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/en.json
@@ -16,7 +16,6 @@
"The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.",
"The {0} field is not a valid fully-qualified http, https, or ftp URL.": "The {0} field is not a valid fully-qualified http, https, or ftp URL.",
"The field {0} is invalid.": "The field {0} is invalid.",
- "'{0}' and '{1}' do not match.": "'{0}' and '{1}' do not match.",
"ThisFieldIsNotAValidCreditCardNumber.": "This field is not a valid credit card number.",
"ThisFieldIsNotValid.": "This field is not valid.",
"ThisFieldIsNotAValidEmailAddress.": "This field is not a valid e-mail address.",
diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pt-BR.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pt-BR.json
index 0cf611f1ea..b0852a3f5f 100644
--- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pt-BR.json
+++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/pt-BR.json
@@ -15,6 +15,20 @@
"The field {0} must be a string with a maximum length of {1}.": "O campo {0} deve ser uma palavra com o tamanho máximo de {1}.",
"The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "O campo {0} deve ser uma palavra com o tamanho mínimo de {2} e tamanho máximo de {1}.",
"The {0} field is not a valid fully-qualified http, https, or ftp URL.": "O campo {0} não é um http, https, ou FTP válido.",
- "The field {0} is invalid.": "O campo {0} é inválido."
+ "The field {0} is invalid.": "O campo {0} é inválido.",
+ "ThisFieldIsNotAValidCreditCardNumber.": "Não é um cartão de crédito válido.",
+ "ThisFieldIsNotValid.": "Campo inválido.",
+ "ThisFieldIsNotAValidEmailAddress.": "E-mail inválido.",
+ "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Este campo só aceita arquivos com asseguintes extensões: {0}",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthoOf{0}": "This field must be a string or array type with a maximum length of '{0}'.",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "This field must be a string or array type with a minimum length of '{0}'.",
+ "ThisFieldIsNotAValidPhoneNumber.": "Número de telefone inválido.",
+ "ThisFieldMustBeBetween{0}And{1}": "Este campo deve estar entre {0} e {1}.",
+ "ThisFieldMustMatchTheRegularExpression{0}": "Este campo deve ser compatível com a expressao regular: '{0}'.",
+ "ThisFieldIsRequired.": "Campo Obrigatório.",
+ "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Campo com no máximo {0} caracteres.",
+ "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Este campo deve possuir entre {1} e {0} caracteres.",
+ "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Este campo não é um http, https, ou ftp complatamente qualificado.",
+ "ThisFieldIsInvalid.": "Campo inválido."
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs
index aa66507cdd..c42036d1cd 100644
--- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs
+++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs
@@ -84,7 +84,7 @@ namespace Volo.Abp.Localization.VirtualFiles
var dictionary = CreateDictionaryFromFile(file);
if (dictionaries.ContainsKey(dictionary.CultureName))
{
- throw new AbpException($"{file.PhysicalPath} dictionary has a culture name '{dictionary.CultureName}' which is already defined!");
+ throw new AbpException($"{file.GetVirtualOrPhysicalPathOrNull()} dictionary has a culture name '{dictionary.CultureName}' which is already defined!");
}
dictionaries[dictionary.CultureName] = dictionary;
diff --git a/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj b/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj
index 8af1220e76..90a5fdafcc 100644
--- a/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj
+++ b/framework/src/Volo.Abp.MailKit/Volo.Abp.MailKit.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs
index 0f82aa798b..68b9beeb6e 100644
--- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs
+++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs
@@ -75,18 +75,20 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
protected virtual void SetIdIfNeeded(TEntity entity)
{
- if (typeof(TKey) == typeof(int) || typeof(TKey) == typeof(long) || typeof(TKey) == typeof(Guid))
+ if (typeof(TKey) == typeof(int) ||
+ typeof(TKey) == typeof(long) ||
+ typeof(TKey) == typeof(Guid))
{
if (EntityHelper.HasDefaultId(entity))
{
- entity.Id = Database.GenerateNextId();
+ EntityHelper.TrySetId(entity, () => Database.GenerateNextId());
}
}
}
public virtual TEntity Find(TKey id, bool includeDetails = true)
{
- return GetQueryable().FirstOrDefault(EntityHelper.CreateEqualityExpressionForId(id));
+ return GetQueryable().FirstOrDefault(e => e.Id.Equals(id));
}
public virtual TEntity Get(TKey id, bool includeDetails = true)
diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs
index 9964e6219b..e68b4b6f37 100644
--- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs
+++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/Utf8JsonMemoryDbSerializer.cs
@@ -1,5 +1,8 @@
using System;
+using System.Reflection;
using System.Text;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
@@ -7,21 +10,43 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb
{
public class Utf8JsonMemoryDbSerializer : IMemoryDbSerializer, ITransientDependency
{
- private readonly IJsonSerializer _jsonSerializer;
+ private static readonly JsonSerializerSettings MemoryDbSerializerSettings;
- public Utf8JsonMemoryDbSerializer(IJsonSerializer jsonSerializer)
+ static Utf8JsonMemoryDbSerializer()
{
- _jsonSerializer = jsonSerializer;
+ MemoryDbSerializerSettings = new JsonSerializerSettings
+ {
+ ContractResolver = new ResolverWithPrivateSetters(),
+ ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
+ };
}
byte[] IMemoryDbSerializer.Serialize(object obj)
{
- return Encoding.UTF8.GetBytes(_jsonSerializer.Serialize(obj));
+ var jsonString = JsonConvert.SerializeObject(obj, MemoryDbSerializerSettings);
+ return Encoding.UTF8.GetBytes(jsonString);
}
public object Deserialize(byte[] value, Type type)
{
- return _jsonSerializer.Deserialize(type, Encoding.UTF8.GetString(value));
+ var jsonString = Encoding.UTF8.GetString(value);
+ return JsonConvert.DeserializeObject(jsonString, type, MemoryDbSerializerSettings);
+ }
+
+ public class ResolverWithPrivateSetters : DefaultContractResolver
+ {
+ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
+ {
+ var prop = base.CreateProperty(member, memberSerialization);
+ if (prop.Writable)
+ {
+ return prop;
+ }
+
+ prop.Writable = member.As()?.GetSetMethod(true) != null;
+
+ return prop;
+ }
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj
index 0610e45bfd..b15ea6378c 100644
--- a/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj
+++ b/framework/src/Volo.Abp.MongoDB/Volo.Abp.MongoDB.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
index cddebd253d..deca912bec 100644
--- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
+++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
@@ -15,6 +15,7 @@ using Volo.Abp.EventBus.Local;
using Volo.Abp.Guids;
using Volo.Abp.MongoDB;
using Volo.Abp.MultiTenancy;
+using Volo.Abp.Reflection;
using Volo.Abp.Threading;
namespace Volo.Abp.Domain.Repositories.MongoDB
@@ -315,12 +316,26 @@ namespace Volo.Abp.Domain.Repositories.MongoDB
protected virtual void CheckAndSetId(TEntity entity)
{
- if (entity is IEntity entityWithGuidId && entityWithGuidId.Id == default)
+ if (entity is IEntity entityWithGuidId)
{
- entityWithGuidId.Id = GuidGenerator.Create();
+ TrySetGuidId(entityWithGuidId);
}
}
+ protected virtual void TrySetGuidId(IEntity entity)
+ {
+ if (entity.Id != default)
+ {
+ return;
+ }
+
+ EntityHelper.TrySetId(
+ entity,
+ () => GuidGenerator.Create(),
+ true
+ );
+ }
+
protected virtual void SetCreationAuditProperties(TEntity entity)
{
AuditPropertySetter.SetCreationProperties(entity);
diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs
index 7fb7b039a7..1d7e026589 100644
--- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs
+++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/AbpObjectMappingModule.cs
@@ -19,5 +19,13 @@ namespace Volo.Abp.ObjectMapping
);
});
}
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddTransient(
+ typeof(IObjectMapper<>),
+ typeof(DefaultObjectMapper<>)
+ );
+ }
}
}
diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs
index b746ab3973..dbc0dc6f3a 100644
--- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs
+++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/DefaultObjectMapper.cs
@@ -4,16 +4,33 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.ObjectMapping
{
- //TODO: It can be slow to always check if service is available. Test it and optimize if necessary.
+ public class DefaultObjectMapper : DefaultObjectMapper, IObjectMapper
+ {
+ public DefaultObjectMapper(
+ IServiceProvider serviceProvider,
+ IAutoObjectMappingProvider autoObjectMappingProvider
+ ) : base(
+ serviceProvider,
+ autoObjectMappingProvider)
+ {
+
+ }
+ }
public class DefaultObjectMapper : IObjectMapper, ITransientDependency
{
- private readonly IServiceProvider _serviceProvider;
+ public IAutoObjectMappingProvider AutoObjectMappingProvider { get; }
+ protected IServiceProvider ServiceProvider { get; }
- public DefaultObjectMapper(IServiceProvider serviceProvider)
+ public DefaultObjectMapper(
+ IServiceProvider serviceProvider,
+ IAutoObjectMappingProvider autoObjectMappingProvider)
{
- _serviceProvider = serviceProvider;
+ AutoObjectMappingProvider = autoObjectMappingProvider;
+ ServiceProvider = serviceProvider;
}
+
+ //TODO: It can be slow to always check if service is available. Test it and optimize if necessary.
public virtual TDestination Map(TSource source)
{
@@ -22,7 +39,7 @@ namespace Volo.Abp.ObjectMapping
return default;
}
- using (var scope = _serviceProvider.CreateScope())
+ using (var scope = ServiceProvider.CreateScope())
{
var specificMapper = scope.ServiceProvider.GetService>();
if (specificMapper != null)
@@ -61,7 +78,7 @@ namespace Volo.Abp.ObjectMapping
return default;
}
- using (var scope = _serviceProvider.CreateScope())
+ using (var scope = ServiceProvider.CreateScope())
{
var specificMapper = scope.ServiceProvider.GetService>();
if (specificMapper != null)
@@ -87,12 +104,12 @@ namespace Volo.Abp.ObjectMapping
protected virtual TDestination AutoMap(object source)
{
- throw new NotImplementedException($"Can not map from given object ({source}) to {typeof(TDestination).AssemblyQualifiedName}.");
+ return AutoObjectMappingProvider.Map(source);
}
protected virtual TDestination AutoMap(TSource source, TDestination destination)
{
- throw new NotImplementedException($"Can no map from {typeof(TSource).AssemblyQualifiedName} to {typeof(TDestination).AssemblyQualifiedName}.");
+ return AutoObjectMappingProvider.Map(source, destination);
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IAutoObjectMappingProvider.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IAutoObjectMappingProvider.cs
new file mode 100644
index 0000000000..b402d223f0
--- /dev/null
+++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IAutoObjectMappingProvider.cs
@@ -0,0 +1,14 @@
+namespace Volo.Abp.ObjectMapping
+{
+ public interface IAutoObjectMappingProvider
+ {
+ TDestination Map(object source);
+
+ TDestination Map(TSource source, TDestination destination);
+ }
+
+ public interface IAutoObjectMappingProvider : IAutoObjectMappingProvider
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs
index 88ee14d707..522ba44e34 100644
--- a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs
+++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/IObjectMapper.cs
@@ -5,6 +5,11 @@
///
public interface IObjectMapper
{
+ ///
+ /// Gets the underlying object that is used for auto object mapping.
+ ///
+ IAutoObjectMappingProvider AutoObjectMappingProvider { get; }
+
///
/// Converts an object to another. Creates a new object of .
///
@@ -24,6 +29,14 @@
TDestination Map(TSource source, TDestination destination);
}
+ ///
+ /// Defines a simple interface to automatically map objects for a specific context.
+ ///
+ public interface IObjectMapper : IObjectMapper
+ {
+
+ }
+
///
/// Maps an object to another.
/// Implement this interface to override object to object mapping for specific types.
diff --git a/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/NotImplementedAutoObjectMappingProvider.cs b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/NotImplementedAutoObjectMappingProvider.cs
new file mode 100644
index 0000000000..56592f77f3
--- /dev/null
+++ b/framework/src/Volo.Abp.ObjectMapping/Volo/Abp/ObjectMapping/NotImplementedAutoObjectMappingProvider.cs
@@ -0,0 +1,18 @@
+using System;
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.ObjectMapping
+{
+ public sealed class NotImplementedAutoObjectMappingProvider : IAutoObjectMappingProvider, ISingletonDependency
+ {
+ public TDestination Map(object source)
+ {
+ throw new NotImplementedException($"Can not map from given object ({source}) to {typeof(TDestination).AssemblyQualifiedName}.");
+ }
+
+ public TDestination Map(TSource source, TDestination destination)
+ {
+ throw new NotImplementedException($"Can no map from {typeof(TSource).AssemblyQualifiedName} to {typeof(TDestination).AssemblyQualifiedName}.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json
index 67d6fa7d3c..c589a46e38 100644
--- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json
+++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json
@@ -46,6 +46,6 @@
"DatatableActionDropdownDefaultText": "Ações",
"ChangePassword": "Alterar Senha",
"PersonalInfo": "Perfil",
- "AreYouSureYouWantToCancelEditingWarningMessage": "Você tem alterações não salvas."
+ "AreYouSureYouWantToCancelEditingWarningMessage": "Há alterações não salvas."
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs b/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs
index 6217e82805..7d3505d616 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Microsoft/Extensions/FileProviders/AbpFileInfoExtensions.cs
@@ -3,6 +3,8 @@ using System.IO;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
+using Volo.Abp.VirtualFileSystem;
+using Volo.Abp.VirtualFileSystem.Embedded;
namespace Microsoft.Extensions.FileProviders
{
@@ -57,5 +59,22 @@ namespace Microsoft.Extensions.FileProviders
return await stream.GetAllBytesAsync();
}
}
+
+ public static string GetVirtualOrPhysicalPathOrNull([NotNull] this IFileInfo fileInfo)
+ {
+ Check.NotNull(fileInfo, nameof(fileInfo));
+
+ if (fileInfo is EmbeddedResourceFileInfo embeddedFileInfo)
+ {
+ return embeddedFileInfo.VirtualPath;
+ }
+
+ if (fileInfo is InMemoryFileInfo inMemoryFileInfo)
+ {
+ return inMemoryFileInfo.DynamicPath;
+ }
+
+ return fileInfo.PhysicalPath;
+ }
}
}
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj
index 626f1eebc8..7d8ae348b7 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj
@@ -14,8 +14,8 @@
-
-
+
+
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs
index 4fc72c07ec..a8ea963f0e 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs
@@ -39,12 +39,13 @@ namespace Volo.Abp.VirtualFileSystem
var directoryPath = subpath.EnsureEndsWith('/');
foreach (var fileInfo in Files.Values)
{
- if (!fileInfo.PhysicalPath.StartsWith(directoryPath))
+ var fullPath = fileInfo.GetVirtualOrPhysicalPathOrNull();
+ if (!fullPath.StartsWith(directoryPath))
{
continue;
}
- var relativePath = fileInfo.PhysicalPath.Substring(directoryPath.Length);
+ var relativePath = fullPath.Substring(directoryPath.Length);
if (relativePath.Contains("/"))
{
continue;
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs
index a270616e3a..0a92f62f0a 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs
@@ -31,8 +31,9 @@ namespace Volo.Abp.VirtualFileSystem
public void AddOrUpdate(IFileInfo fileInfo)
{
- DynamicFiles.AddOrUpdate(fileInfo.PhysicalPath, fileInfo, (key, value) => fileInfo);
- ReportChange(fileInfo.PhysicalPath);
+ var filePath = fileInfo.GetVirtualOrPhysicalPathOrNull();
+ DynamicFiles.AddOrUpdate(filePath, fileInfo, (key, value) => fileInfo);
+ ReportChange(filePath);
}
public bool Delete(string filePath)
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs
index 22df03f2ab..7291f93cf8 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/Embedded/EmbeddedResourceFileInfo.cs
@@ -29,7 +29,9 @@ namespace Volo.Abp.VirtualFileSystem.Embedded
}
private long? _length;
- public string PhysicalPath { get; }
+ public string PhysicalPath => null;
+
+ public string VirtualPath { get; }
public string Name { get; }
@@ -46,14 +48,14 @@ namespace Volo.Abp.VirtualFileSystem.Embedded
public EmbeddedResourceFileInfo(
Assembly assembly,
string resourcePath,
- string physicalPath,
+ string virtualPath,
string name,
DateTimeOffset lastModified)
{
_assembly = assembly;
_resourcePath = resourcePath;
- PhysicalPath = physicalPath;
+ VirtualPath = virtualPath;
Name = name;
LastModified = lastModified;
}
@@ -63,7 +65,7 @@ namespace Volo.Abp.VirtualFileSystem.Embedded
{
var stream = _assembly.GetManifestResourceStream(_resourcePath);
- if (!_length.HasValue)
+ if (!_length.HasValue && stream != null)
{
_length = stream.Length;
}
@@ -73,7 +75,7 @@ namespace Volo.Abp.VirtualFileSystem.Embedded
public override string ToString()
{
- return $"[EmbeddedResourceFileInfo] {Name} ({PhysicalPath})";
+ return $"[EmbeddedResourceFileInfo] {Name} ({this.VirtualPath})";
}
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/IDynamicFileManager.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/IDynamicFileManager.cs
index f7dc42704a..8d9bae8540 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/IDynamicFileManager.cs
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/IDynamicFileManager.cs
@@ -5,6 +5,7 @@ namespace Volo.Abp.VirtualFileSystem
public interface IDynamicFileProvider : IFileProvider
{
void AddOrUpdate(IFileInfo fileInfo);
+
bool Delete(string filePath);
}
}
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs
index d9ab30763a..0f529832a0 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs
@@ -10,7 +10,7 @@ namespace Volo.Abp.VirtualFileSystem
public long Length => _fileContent.Length;
- public string PhysicalPath { get; }
+ public string PhysicalPath => null;
public string Name { get; }
@@ -20,9 +20,11 @@ namespace Volo.Abp.VirtualFileSystem
private readonly byte[] _fileContent;
- public InMemoryFileInfo(byte[] fileContent, string physicalPath, string name)
+ public string DynamicPath { get; }
+
+ public InMemoryFileInfo(string dynamicPath, byte[] fileContent, string name)
{
- PhysicalPath = physicalPath;
+ DynamicPath = dynamicPath;
Name = name;
_fileContent = fileContent;
LastModified = DateTimeOffset.Now;
diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs
index 9bcf76e4be..be08fc2024 100644
--- a/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs
+++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs
@@ -71,7 +71,7 @@ namespace Volo.Abp.VirtualFileSystem
true
);
}
-
+
private Dictionary CreateFiles()
{
var files = new Dictionary(StringComparer.OrdinalIgnoreCase);
diff --git a/framework/test/AbpTestBase/AbpTestBase.csproj b/framework/test/AbpTestBase/AbpTestBase.csproj
index d794eaa279..c6d5b71672 100644
--- a/framework/test/AbpTestBase/AbpTestBase.csproj
+++ b/framework/test/AbpTestBase/AbpTestBase.csproj
@@ -1,12 +1,11 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0AbpTestBaseAbpTestBase
- false
- false
- false
diff --git a/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj b/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj
index 0419ae171d..371e2374f9 100644
--- a/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj
+++ b/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp2.2
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj
index c4933829eb..d1eadf276d 100644
--- a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo.Abp.AspNetCore.Authentication.OAuth.Tests.csproj
@@ -1,7 +1,9 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0latestVolo.Abp.AspNetCore.Authentication.OAuth.TestsVolo.Abp.AspNetCore.Authentication.OAuth.Tests
diff --git a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs
index fac9e33e29..bf869fc809 100644
--- a/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Authentication.OAuth.Tests/Volo/Abp/AspNetCore/Authentication/OAuth/Claims/MultipleClaimAction_Tests.cs
@@ -1,5 +1,6 @@
using System.Linq;
using System.Security.Claims;
+using System.Text.Json;
using Newtonsoft.Json.Linq;
using Shouldly;
using Volo.Abp.Security.Claims;
@@ -12,13 +13,12 @@ namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
[Fact]
public void Should_Set_Single_Value()
{
- var jObject = JObject.Parse(@"{
+ var jObject = JsonDocument.Parse(@"{
""sub"": ""71054539-0e48-af28-5e7a-39e4e42d8ea5"",
""role"": ""admin""
}");
-
var claimsIdentity = new ClaimsIdentity();
- new MultipleClaimAction(AbpClaimTypes.Role, "role").Run(jObject, claimsIdentity, null);
+ new MultipleClaimAction(AbpClaimTypes.Role, "role").Run(jObject.RootElement, claimsIdentity, null);
var claims = claimsIdentity.FindAll(AbpClaimTypes.Role).ToList();
claims.Count.ShouldBe(1);
claims[0].Value.ShouldBe("admin");
@@ -27,7 +27,7 @@ namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
[Fact]
public void Should_Set_Multiple_Values()
{
- var jObject = JObject.Parse(@"{
+ var jObject = JsonDocument.Parse(@"{
""sub"": ""71054539-0e48-af28-5e7a-39e4e42d8ea5"",
""role"": [
""admin"",
@@ -36,7 +36,7 @@ namespace Volo.Abp.AspNetCore.Authentication.OAuth.Claims
}");
var claimsIdentity = new ClaimsIdentity();
- new MultipleClaimAction(AbpClaimTypes.Role, "role").Run(jObject, claimsIdentity, null);
+ new MultipleClaimAction(AbpClaimTypes.Role, "role").Run(jObject.RootElement, claimsIdentity, null);
var claims = claimsIdentity.FindAll(AbpClaimTypes.Role).ToList();
claims.Count.ShouldBe(2);
claims[0].Value.ShouldBe("admin");
diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj
index f08d5b1ac2..61d430d984 100644
--- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo.Abp.AspNetCore.MultiTenancy.Tests.csproj
@@ -1,13 +1,11 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0Volo.Abp.AspNetCore.MultiTenancy.TestsVolo.Abp.AspNetCore.MultiTenancy.Tests
- true
- false
- false
- false
diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/Startup.cs b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/Startup.cs
index 1af71d75e8..05b724b9c3 100644
--- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/Startup.cs
+++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/App/Startup.cs
@@ -12,7 +12,7 @@ namespace Volo.Abp.AspNetCore.App
services.AddApplication();
}
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
diff --git a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancyTestBase.cs b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancyTestBase.cs
index 9dc083b3f1..ecc9d055ca 100644
--- a/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancyTestBase.cs
+++ b/framework/test/Volo.Abp.AspNetCore.MultiTenancy.Tests/Volo/Abp/AspNetCore/MultiTenancy/AspNetCoreMultiTenancyTestBase.cs
@@ -1,8 +1,7 @@
-using Volo.Abp.AspNetCore.App;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
- public abstract class AspNetCoreMultiTenancyTestBase : AbpAspNetCoreTestBase
+ public abstract class AspNetCoreMultiTenancyTestBase : AbpAspNetCoreTestBase
{
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Properties/launchSettings.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Properties/launchSettings.json
new file mode 100644
index 0000000000..fcf34f54da
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:55482/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc.Tests": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:55483/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
index 0f4fabd553..93143bfbe0 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo.Abp.AspNetCore.Mvc.Tests.csproj
@@ -1,17 +1,17 @@
-
+
+
+
- netcoreapp2.2
+ netcoreapp3.0$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;Volo.Abp.AspNetCore.Mvc.TestsVolo.Abp.AspNetCore.Mvc.Teststruetrue
- false
- false
- falsetruetrue
+ true
@@ -20,7 +20,6 @@
-
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
index eb0fc1ef48..28b5ee8b1f 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
@@ -69,6 +69,9 @@ namespace Volo.Abp.AspNetCore.Mvc
typeof(AbpUiResource),
typeof(AbpValidationResource)
).AddVirtualJson("/Volo/Abp/AspNetCore/Mvc/Localization/Resource");
+
+ options.Languages.Add(new LanguageInfo("en", "en", "English"));
+ options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
});
}
@@ -77,10 +80,14 @@ namespace Volo.Abp.AspNetCore.Mvc
var app = context.GetApplicationBuilder();
app.UseCorrelationId();
+ app.UseVirtualFiles();
+ app.UseAbpRequestLocalization();
+ app.UseRouting();
app.UseMiddleware();
+ app.UseAuthorization();
app.UseAuditing();
app.UseUnitOfWork();
- app.UseMvcWithDefaultRoute();
+ app.UseMvcWithDefaultRouteAndArea();
}
}
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpApiDefinitionController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpApiDefinitionController_Tests.cs
new file mode 100644
index 0000000000..44b206e462
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ApiExploring/AbpApiDefinitionController_Tests.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Http.Modeling;
+using Xunit;
+
+namespace Volo.Abp.AspNetCore.Mvc.ApiExploring
+{
+ public class AbpApiDefinitionController_Tests : AspNetCoreMvcTestBase
+ {
+ [Fact]
+ public async Task GetAsync()
+ {
+ var model = await GetResponseAsObjectAsync("/api/abp/api-definition");
+ model.ShouldNotBeNull();
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar_Tests.cs
new file mode 100644
index 0000000000..46f2823b70
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalRegistrar_Tests.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using Volo.Abp.DependencyInjection;
+using Xunit;
+
+namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection
+{
+ public class AbpAspNetCoreMvcConventionalRegistrar_Tests
+ {
+ [Fact]
+ public void Should_Registered_Mvc_Service()
+ {
+ //Arrange
+ var services = new ServiceCollection();
+
+ //Act
+ services.AddConventionalRegistrar(new DefaultConventionalRegistrar());
+ services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar());
+
+ services.AddTypes(typeof(My_Test_PageModel), typeof(My_Test_Controller), typeof(My_Test_ViewComponent));
+
+ //Assert
+ services.ShouldContainTransient(typeof(My_Test_PageModel));
+ services.ShouldContainTransient(typeof(My_Test_Controller));
+ services.ShouldContainTransient(typeof(My_Test_ViewComponent));
+
+ var serviceProvider = services.BuildServiceProvider();
+ serviceProvider.GetServices().Count().ShouldBe(1);
+ serviceProvider.GetServices().Count().ShouldBe(1);
+ serviceProvider.GetServices().Count().ShouldBe(1);
+ }
+ }
+
+ public class My_Test_PageModel : PageModel
+ {
+
+ }
+
+ public class My_Test_Controller : Controller
+ {
+
+ }
+
+ public class My_Test_ViewComponent : ViewComponent
+ {
+
+ }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Startup.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Startup.cs
index 458bbd8827..9ae46be82f 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Startup.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Startup.cs
@@ -18,7 +18,7 @@ namespace Volo.Abp.AspNetCore.Mvc
return services.BuildServiceProviderFromFactory();
}
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj
index 3e92a569bc..7b58c9c738 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj
@@ -1,15 +1,14 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.TestsVolo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Teststruetrue
- false
- false
- falsetruetrue
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/TestStartup.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/TestStartup.cs
index da23c66e9f..3a140e35d4 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/TestStartup.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/TestStartup.cs
@@ -18,7 +18,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
return services.BuildServiceProviderFromFactory();
}
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs
index ce9734914d..e14e2336d9 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/AbpAspNetCoreMvcUiBootstrapDemoModule.cs
@@ -1,5 +1,5 @@
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
@@ -22,9 +22,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
app.UseDeveloperExceptionPage();
}
+ app.UseRouting();
app.UseVirtualFiles();
-
- app.UseMvcWithDefaultRoute();
+ app.UseMvcWithDefaultRouteAndArea();
}
}
}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs
index 4ee4949d50..0941475418 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
@@ -20,7 +21,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
try
{
Log.Information("Starting web host.");
- BuildWebHostInternal(args).Run();
+ BuildWebHostInternal(args).Build().Run();
return 0;
}
catch (Exception ex)
@@ -34,13 +35,20 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
}
}
- internal static IWebHost BuildWebHostInternal(string[] args) =>
- new WebHostBuilder()
- .UseKestrel()
- .UseContentRoot(Directory.GetCurrentDirectory())
- .UseIISIntegration()
- .UseStartup()
- .UseSerilog()
- .Build();
+ //internal static IWebHost BuildWebHostInternal(string[] args) =>
+ // new WebHostBuilder()
+ // .UseKestrel()
+ // .UseContentRoot(Directory.GetCurrentDirectory())
+ // .UseIISIntegration()
+ // .UseStartup()
+ // .UseSerilog()
+ // .Build();
+
+ internal static IHostBuilder BuildWebHostInternal(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
}
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs
index ffd3ca47be..0497fe5216 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs
@@ -7,14 +7,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
{
public class Startup
{
- public IServiceProvider ConfigureServices(IServiceCollection services)
+ public void ConfigureServices(IServiceCollection services)
{
services.AddApplication(options =>
{
options.UseAutofac();
});
- return services.BuildServiceProviderFromFactory();
+ //return services.BuildServiceProviderFromFactory();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj
index c5a4731256..455708a1d2 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj
@@ -1,12 +1,14 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0
+ true
-
-
+
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Properties/launchSettings.json b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Properties/launchSettings.json
new file mode 100644
index 0000000000..9e97dc2b61
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:55480/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc.UI.Tests": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:55481/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj
index cfbe4ad40d..b63efadfda 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj
@@ -1,22 +1,20 @@
-
+
+
+
- netcoreapp2.2
+ netcoreapp3.0$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;Volo.Abp.AspNetCore.Mvc.UI.TestsVolo.Abp.AspNetCore.Mvc.UI.Teststruetrue
- false
- false
- falsetruetrue
-
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo/Abp/AspNetCore/Mvc/UI/Startup.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo/Abp/AspNetCore/Mvc/UI/Startup.cs
index 1f4182110a..124a103da2 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo/Abp/AspNetCore/Mvc/UI/Startup.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Tests/Volo/Abp/AspNetCore/Mvc/UI/Startup.cs
@@ -19,7 +19,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI
return services.BuildServiceProviderFromFactory();
}
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Properties/launchSettings.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Properties/launchSettings.json
new file mode 100644
index 0000000000..836bd1af47
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:55487/",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.Abp.AspNetCore.Mvc.Versioning.Tests": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:55488/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj
index 3c9ce2301f..8d954b0b2a 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo.Abp.AspNetCore.Mvc.Versioning.Tests.csproj
@@ -1,22 +1,20 @@
-
+
+
+
- netcoreapp2.2
+ netcoreapp3.0$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;Volo.Abp.AspNetCore.Mvc.Versioning.TestsVolo.Abp.AspNetCore.Mvc.Versioning.Teststruetrue
- false
- false
- falsetruetrue
-
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs
index 3ea9103e9e..99a155f3b7 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/AbpAspNetCoreMvcVersioningTestModule.cs
@@ -66,7 +66,8 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
- app.UseMvcWithDefaultRoute();
+ app.UseRouting();
+ app.UseMvcWithDefaultRouteAndArea();
}
}
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/Startup.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/Startup.cs
index 4d9f831670..79985de769 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/Startup.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Versioning.Tests/Volo/Abp/AspNetCore/Mvc/Versioning/Startup.cs
@@ -19,7 +19,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Versioning
return services.BuildServiceProviderFromFactory();
}
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj
index e52c426e43..061e1640ce 100644
--- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj
+++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo.Abp.AspNetCore.Tests.csproj
@@ -1,18 +1,29 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0Volo.Abp.AspNetCore.TestsVolo.Abp.AspNetCore.Teststruefalsefalsefalse
+ true
+ false
+ true
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs
index 33beb9d62c..dd5edff807 100644
--- a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestBase.cs
@@ -1,5 +1,7 @@
+using System.Globalization;
using System.Net;
using System.Net.Http;
+using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
@@ -8,6 +10,11 @@ using Volo.Abp.AspNetCore.TestBase;
namespace Volo.Abp.AspNetCore
{
+ public class AbpAspNetCoreTestBase : AbpAspNetCoreTestBase
+ {
+
+ }
+
public abstract class AbpAspNetCoreTestBase : AbpAspNetCoreIntegratedTestBase
where TStartup : class
{
@@ -25,15 +32,21 @@ namespace Volo.Abp.AspNetCore
protected virtual async Task GetResponseAsStringAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
{
- var response = await GetResponseAsync(url, expectedStatusCode);
- return await response.Content.ReadAsStringAsync();
+ using (var response = await GetResponseAsync(url, expectedStatusCode))
+ {
+ return await response.Content.ReadAsStringAsync();
+ }
}
protected virtual async Task GetResponseAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
{
- var response = await Client.GetAsync(url);
- response.StatusCode.ShouldBe(expectedStatusCode);
- return response;
+ using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url))
+ {
+ requestMessage.Headers.Add("Accept-Language", CultureInfo.CurrentUICulture.Name);
+ var response = await Client.SendAsync(requestMessage);
+ response.StatusCode.ShouldBe(expectedStatusCode);
+ return response;
+ }
}
}
}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestModule.cs
new file mode 100644
index 0000000000..fafd5794a6
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/AbpAspNetCoreTestModule.cs
@@ -0,0 +1,53 @@
+using System;
+using System.IO;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.AspNetCore.TestBase;
+using Volo.Abp.Autofac;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.Abp.AspNetCore
+{
+ [DependsOn(
+ typeof(AbpAspNetCoreTestBaseModule),
+ typeof(AbpAspNetCoreModule),
+ typeof(AbpAutofacModule)
+ )]
+ public class AbpAspNetCoreTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var hostingEnvironment = context.Services.GetHostingEnvironment();
+
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ //options.FileSets.ReplaceEmbeddedByPhysical(FindProjectPath(hostingEnvironment));
+ });
+ }
+
+ public override void OnApplicationInitialization(ApplicationInitializationContext context)
+ {
+ var app = context.GetApplicationBuilder();
+
+ app.UseCorrelationId();
+ app.UseVirtualFiles();
+ }
+
+ private string FindProjectPath(IWebHostEnvironment hostEnvironment)
+ {
+ var directory = new DirectoryInfo(hostEnvironment.ContentRootPath);
+
+ while (directory != null && directory.Name != "Volo.Abp.AspNetCore.Tests")
+ {
+ directory = directory.Parent;
+ }
+
+ return directory?.FullName
+ ?? throw new Exception("Could not find the project path by beginning from " + hostEnvironment.ContentRootPath + ", going through to parents and looking for Volo.Abp.AspNetCore.Tests");
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/Startup.cs b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/Startup.cs
new file mode 100644
index 0000000000..7f95713274
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/Startup.cs
@@ -0,0 +1,26 @@
+using System;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace Volo.Abp.AspNetCore
+{
+ public class Startup
+ {
+ public IServiceProvider ConfigureServices(IServiceCollection services)
+ {
+ services.AddApplication(options =>
+ {
+ options.UseAutofac();
+ });
+
+ return services.BuildServiceProviderFromFactory();
+ }
+
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
+ {
+ app.InitializeApplication();
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/VirtualFileSystem/VirtualFileSystem_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/VirtualFileSystem/VirtualFileSystem_Tests.cs
new file mode 100644
index 0000000000..142d44baec
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Tests/Volo/Abp/AspNetCore/VirtualFileSystem/VirtualFileSystem_Tests.cs
@@ -0,0 +1,19 @@
+using System.Threading.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.AspNetCore.VirtualFileSystem
+{
+ public class VirtualFileSystem_Tests : AbpAspNetCoreTestBase
+ {
+ [Fact]
+ public async Task Get_Virtual_File()
+ {
+ var result = await GetResponseAsStringAsync(
+ "/SampleFiles/test1.js"
+ );
+
+ result.ShouldBe("test1.js-content");
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Tests/wwwroot/SampleFiles/test1.js b/framework/test/Volo.Abp.AspNetCore.Tests/wwwroot/SampleFiles/test1.js
new file mode 100644
index 0000000000..20a6856cb7
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Tests/wwwroot/SampleFiles/test1.js
@@ -0,0 +1 @@
+test1.js-content
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj
index aa26dffb44..ee1e2441a6 100644
--- a/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj
+++ b/framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj
@@ -1,14 +1,12 @@
+
+
- netcoreapp2.2
- latest
+ netcoreapp3.0Volo.Abp.Auditing.TestsVolo.Abp.Auditing.Teststrue
- false
- false
- false
diff --git a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj
index a76bcabb37..817533079b 100644
--- a/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj
+++ b/framework/test/Volo.Abp.Authorization.Tests/Volo.Abp.Authorization.Tests.csproj
@@ -1,14 +1,12 @@
+
+
- netcoreapp2.2
- latest
+ netcoreapp3.0Volo.Abp.Authorization.TestsVolo.Abp.Authorization.Teststrue
- false
- false
- false
diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj
index 234c405eda..d8e2e5ec2b 100644
--- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj
+++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo.Abp.AutoMapper.Tests.csproj
@@ -1,13 +1,11 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0Volo.Abp.AutoMapper.TestsVolo.Abp.AutoMapper.Tests
- true
- false
- false
- false
diff --git a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs
index a75db5189b..436c0402d8 100644
--- a/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs
+++ b/framework/test/Volo.Abp.AutoMapper.Tests/Volo/Abp/AutoMapper/AbpAutoMapperModule_Basic_Tests.cs
@@ -17,9 +17,16 @@ namespace Volo.Abp.AutoMapper
}
[Fact]
- public void Should_Replace_ObjectMapper()
+ public void Should_Replace_IAutoObjectMappingProvider()
{
- Assert.True(_objectMapper is AutoMapperObjectMapper);
+ Assert.True(ServiceProvider.GetRequiredService() is AutoMapperAutoObjectMappingProvider);
+ }
+
+ [Fact]
+ public void Should_Get_Internal_Mapper()
+ {
+ _objectMapper.GetMapper().ShouldNotBeNull();
+ _objectMapper.AutoObjectMappingProvider.GetMapper().ShouldNotBeNull();
}
[Fact]
diff --git a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj
index 1a9016ee3a..96088ec3e4 100644
--- a/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj
+++ b/framework/test/Volo.Abp.Autofac.Tests/Volo.Abp.Autofac.Tests.csproj
@@ -1,13 +1,12 @@
+
+
- netcoreapp2.2
+ netcoreapp3.0Volo.Abp.Autofac.TestsVolo.Abp.Autofac.Teststrue
- false
- false
- false
diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj
index 31e9c91779..f8a27d020b 100644
--- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj
+++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo.Abp.BackgroundJobs.Tests.csproj
@@ -1,14 +1,11 @@
+
+
- netcoreapp2.2
- latest
+ netcoreapp3.0Volo.Abp.BackgroundJobs.TestsVolo.Abp.BackgroundJobs.Tests
- true
- false
- false
- false
diff --git a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj
index 8efd87f2b6..1c4818159b 100644
--- a/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj
+++ b/framework/test/Volo.Abp.Caching.Tests/Volo.Abp.Caching.Tests.csproj
@@ -1,14 +1,11 @@
+
+
- netcoreapp2.2
- latest
+ netcoreapp3.0Volo.Abp.Caching.TestsVolo.Abp.Caching.Tests
- true
- false
- false
- false
diff --git a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj
index 34c30b1600..97988f8b3f 100644
--- a/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj
+++ b/framework/test/Volo.Abp.Castle.Core.Tests/Volo.Abp.Castle.Core.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Castle.Core.Tests
- Volo.Abp.Castle.Core.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj b/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj
index d2535076b1..ba75eb73ca 100644
--- a/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj
+++ b/framework/test/Volo.Abp.Cli.Core.Tests/Volo.Abp.Cli.Core.Tests.csproj
@@ -1,8 +1,9 @@
+
+
- netcoreapp2.2
- latest
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj
index 957c255d2b..0812895ae0 100644
--- a/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj
+++ b/framework/test/Volo.Abp.Core.Tests/Volo.Abp.Core.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Core.Tests
- Volo.Abp.Core.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Dapper.Tests/Volo.Abp.Dapper.Tests.csproj b/framework/test/Volo.Abp.Dapper.Tests/Volo.Abp.Dapper.Tests.csproj
index 8e9ff07634..31f56a6144 100644
--- a/framework/test/Volo.Abp.Dapper.Tests/Volo.Abp.Dapper.Tests.csproj
+++ b/framework/test/Volo.Abp.Dapper.Tests/Volo.Abp.Dapper.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Dapper.Tests
- Volo.Abp.Dapper.Tests
- true
- false
- false
- false
+ netcoreapp3.0
@@ -18,7 +14,7 @@
-
+
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj
index b7895d25a0..65b50126bd 100644
--- a/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj
+++ b/framework/test/Volo.Abp.Data.Tests/Volo.Abp.Data.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Data.Tests
- Volo.Abp.Data.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj
index 42de4f22f2..1ed24ead80 100644
--- a/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj
+++ b/framework/test/Volo.Abp.Ddd.Tests/Volo.Abp.Ddd.Tests.csproj
@@ -1,14 +1,9 @@
+
+
- netcoreapp2.2
- latest
- Volo.Abp.Ddd.Tests
- Volo.Abp.Ddd.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs
new file mode 100644
index 0000000000..2ad6a45b05
--- /dev/null
+++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Entities/EntityHelper_Tests.cs
@@ -0,0 +1,57 @@
+using System;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.Domain.Entities
+{
+ public class EntityHelper_Tests
+ {
+ [Fact]
+ public static void SetId_DerivedFromAggregateRoot()
+ {
+ var idValue = Guid.NewGuid();
+ var myEntityDerivedFromAggregateRoot = new MyEntityDerivedFromAggregateRoot();
+ EntityHelper.TrySetId(myEntityDerivedFromAggregateRoot, () => idValue, true);
+ myEntityDerivedFromAggregateRoot.Id.ShouldBe(idValue);
+ }
+
+ [Fact]
+ public static void SetId_ImplementsIEntity()
+ {
+ var idValue = Guid.NewGuid();
+ var myEntityImplementsIEntity = new MyEntityImplementsIEntity();
+ EntityHelper.TrySetId(myEntityImplementsIEntity, () => idValue, true);
+ myEntityImplementsIEntity.Id.ShouldBe(idValue);
+ }
+
+ [Fact]
+ public static void SetId_DisablesIdGeneration()
+ {
+ var idValue = Guid.NewGuid();
+ var myEntityDisablesIdGeneration = new MyEntityDisablesIdGeneration();
+ EntityHelper.TrySetId(myEntityDisablesIdGeneration, () => idValue, true);
+ myEntityDisablesIdGeneration.Id.ShouldBe(default);
+ }
+
+ private class MyEntityDerivedFromAggregateRoot : AggregateRoot
+ {
+
+ }
+
+ private class MyEntityImplementsIEntity : IEntity
+ {
+ public Guid Id { get; protected set; }
+
+ public object[] GetKeys()
+ {
+ return new object[] { Id };
+ }
+ }
+
+ private class MyEntityDisablesIdGeneration : Entity
+ {
+ [DisableIdGeneration]
+ public override Guid Id { get; protected set; }
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj
index ec4d2f8bda..bc1296cbc8 100644
--- a/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj
+++ b/framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj
@@ -1,12 +1,9 @@
+
+
- netcoreapp2.2
- latest
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo.Abp.EntityFrameworkCore.Tests.SecondContext.csproj b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo.Abp.EntityFrameworkCore.Tests.SecondContext.csproj
index 14453442c6..bace3a67e5 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo.Abp.EntityFrameworkCore.Tests.SecondContext.csproj
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo.Abp.EntityFrameworkCore.Tests.SecondContext.csproj
@@ -1,15 +1,12 @@
-
+
+
+
- netcoreapp2.2
+ netcoreapp3.0$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;
- Volo.Abp.EntityFrameworkCore.Tests.SecondContext
- Volo.Abp.EntityFrameworkCore.Tests.SecondContexttruetrue
- false
- false
- falsetruetrue
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/BookInSecondDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/BookInSecondDbContext.cs
index 0e22533c11..59c568ed9d 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/BookInSecondDbContext.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/BookInSecondDbContext.cs
@@ -6,5 +6,16 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext
public class BookInSecondDbContext : AggregateRoot
{
public string Name { get; set; }
+
+ public BookInSecondDbContext()
+ {
+
+ }
+
+ public BookInSecondDbContext(Guid id, string name)
+ : base(id)
+ {
+ Name = name;
+ }
}
}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondContextTestDataBuilder.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondContextTestDataBuilder.cs
index 59ddc2acdf..0b89576f34 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondContextTestDataBuilder.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/SecondContextTestDataBuilder.cs
@@ -18,11 +18,12 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext
public void Build()
{
- _bookRepository.Insert(new BookInSecondDbContext
- {
- Id = _guidGenerator.Create(),
- Name = "TestBook1"
- });
+ _bookRepository.Insert(
+ new BookInSecondDbContext(
+ _guidGenerator.Create(),
+ "TestBook1"
+ )
+ );
}
}
}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj
index e70921b325..b79bfa3b4e 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo.Abp.EntityFrameworkCore.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.EntityFrameworkCore.Tests
- Volo.Abp.EntityFrameworkCore.Tests
- true
- false
- false
- false
+ netcoreapp3.0
@@ -20,7 +16,7 @@
-
+
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests_With_Int_Pk.cs
new file mode 100644
index 0000000000..44cf993be8
--- /dev/null
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests_With_Int_Pk.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.TestApp.Testing;
+
+namespace Volo.Abp.EntityFrameworkCore.Repositories
+{
+ public class Repository_Basic_Tests_With_Int_Pk : Repository_Basic_Tests_With_Int_Pk
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
index cb9726d6b4..0f9def32f0 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
@@ -15,6 +15,8 @@ namespace Volo.Abp.EntityFrameworkCore
public DbSet Books { get; set; }
+ public DbSet EntityWithIntPks { get; set; }
+
public TestMigrationsDbContext(DbContextOptions options)
: base(options)
{
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transactions/Transaction_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transactions/Transaction_Tests.cs
index 030b236637..613c42894c 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transactions/Transaction_Tests.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Transactions/Transaction_Tests.cs
@@ -80,7 +80,7 @@ namespace Volo.Abp.EntityFrameworkCore.Transactions
_unitOfWorkManager.Current.ShouldNotBeNull();
await _personRepository.InsertAsync(new Person(personId, "Adam", 42));
- await _bookRepository.InsertAsync(new BookInSecondDbContext { Id = bookId, Name = bookId.ToString() });
+ await _bookRepository.InsertAsync(new BookInSecondDbContext(bookId, bookId.ToString()));
await _unitOfWorkManager.Current.SaveChangesAsync();
diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
index 00e052d2dd..bfcecdeb65 100644
--- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
+++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
@@ -13,6 +13,8 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore
public DbSet DummyEntities { get; set; }
+ public DbSet EntityWithIntPks { get; set; }
+
public TestAppDbContext(DbContextOptions options)
: base(options)
{
diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj
index eb0f746272..a58e10af2d 100644
--- a/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj
+++ b/framework/test/Volo.Abp.EventBus.Tests/Volo.Abp.EventBus.Tests.csproj
@@ -1,14 +1,9 @@
+
+
- netcoreapp2.2
- latest
- Volo.Abp.EventBus.Tests
- Volo.Abp.EventBus.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/GenericInheritanceTest.cs b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/GenericInheritanceTest.cs
index d770a81325..eeec26b166 100644
--- a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/GenericInheritanceTest.cs
+++ b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/GenericInheritanceTest.cs
@@ -21,7 +21,7 @@ namespace Volo.Abp.EventBus.Local
return Task.CompletedTask;
});
- await LocalEventBus.PublishAsync(new EntityUpdatedEventData(new Person { Id = 42 }));
+ await LocalEventBus.PublishAsync(new EntityUpdatedEventData(new Person(42)));
triggeredEvent.ShouldBe(true);
}
@@ -39,19 +39,37 @@ namespace Volo.Abp.EventBus.Local
return Task.CompletedTask;
});
- await LocalEventBus.PublishAsync(new EntityChangedEventData(new Student { Id = 42 }));
+ await LocalEventBus.PublishAsync(new EntityChangedEventData(new Student(42)));
triggeredEvent.ShouldBe(true);
}
-
+
public class Person : Entity
{
-
+ public Person()
+ {
+
+ }
+
+ public Person(int id)
+ : base(id)
+ {
+
+ }
}
public class Student : Person
{
-
+ public Student()
+ {
+
+ }
+
+ public Student(int id)
+ : base(id)
+ {
+
+ }
}
}
}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj
index dd7436e1d2..d7b28568f3 100644
--- a/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj
+++ b/framework/test/Volo.Abp.Features.Tests/Volo.Abp.Features.Tests.csproj
@@ -1,14 +1,9 @@
+
+
- netcoreapp2.2
- latest
- Volo.Abp.Features.Tests
- Volo.Abp.Features.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj
index 089dbcab38..e3e95e182b 100644
--- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj
+++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo.Abp.FluentValidation.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.FluentValidation.Tests
- Volo.Abp.FluentValidation.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj
index 8800d492ea..a4bcae448b 100644
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo.Abp.Http.Client.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Http.Client.Tests
- Volo.Abp.Http.Client.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestBase.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestBase.cs
new file mode 100644
index 0000000000..7dc930daa1
--- /dev/null
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestBase.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.AspNetCore;
+
+namespace Volo.Abp.Http
+{
+ public abstract class AbpHttpClientTestBase : AbpAspNetCoreTestBase
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs
new file mode 100644
index 0000000000..ecde843177
--- /dev/null
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs
@@ -0,0 +1,33 @@
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.AspNetCore.Mvc;
+using Volo.Abp.Http.Client;
+using Volo.Abp.Http.DynamicProxying;
+using Volo.Abp.Modularity;
+using Volo.Abp.TestApp;
+
+namespace Volo.Abp.Http
+{
+ [DependsOn(
+ typeof(AbpHttpClientModule),
+ typeof(AbpAspNetCoreMvcTestModule)
+ )]
+ public class AbpHttpClientTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddHttpClientProxies(typeof(TestAppModule).Assembly);
+ context.Services.AddHttpClientProxy();
+
+ Configure(options =>
+ {
+ options.RemoteServices.Default = new RemoteServiceConfiguration("/");
+ });
+
+ //This is needed after ASP.NET Core 3.0 upgrade.
+ context.Services.AddMvc()
+ .PartManager.ApplicationParts
+ .Add(new AssemblyPart(typeof(AbpAspNetCoreMvcModule).Assembly));
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpTestBase.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpTestBase.cs
deleted file mode 100644
index d2db4dc3ac..0000000000
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpTestBase.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Volo.Abp.AspNetCore;
-
-namespace Volo.Abp.Http
-{
- public abstract class AbpHttpTestBase : AbpAspNetCoreTestBase
- {
-
- }
-}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpTestModule.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpTestModule.cs
deleted file mode 100644
index 4ee13e7dc7..0000000000
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpTestModule.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Microsoft.Extensions.DependencyInjection;
-using Volo.Abp.AspNetCore.Mvc;
-using Volo.Abp.Http.Client;
-using Volo.Abp.Http.DynamicProxying;
-using Volo.Abp.Modularity;
-using Volo.Abp.TestApp;
-
-namespace Volo.Abp.Http
-{
- [DependsOn(typeof(AbpAspNetCoreMvcTestModule), typeof(AbpHttpClientModule))]
- public class AbpHttpTestModule : AbpModule
- {
- public override void ConfigureServices(ServiceConfigurationContext context)
- {
- context.Services.AddHttpClientProxies(typeof(TestAppModule).Assembly);
- context.Services.AddHttpClientProxy();
-
- Configure(options =>
- {
- options.RemoteServices.Default = new RemoteServiceConfiguration("/");
- });
- }
- }
-}
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs
index 629d979d95..aeae7ef1b4 100644
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs
@@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
+using Volo.Abp.Http.Modeling;
using Volo.Abp.TestApp.Application;
using Volo.Abp.TestApp.Application.Dto;
using Volo.Abp.TestApp.Domain;
@@ -12,7 +13,7 @@ using Xunit;
namespace Volo.Abp.Http.DynamicProxying
{
- public class PersonAppServiceClientProxy_Tests : AbpHttpTestBase
+ public class PersonAppServiceClientProxy_Tests : AbpHttpClientTestBase
{
private readonly IPeopleAppService _peopleAppService;
private readonly IRepository _personRepository;
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
index 1a59b39614..22d9354624 100644
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
@@ -6,7 +6,7 @@ using Xunit;
namespace Volo.Abp.Http.DynamicProxying
{
- public class RegularTestControllerClientProxy_Tests : AbpHttpTestBase
+ public class RegularTestControllerClientProxy_Tests : AbpHttpClientTestBase
{
//TODO: Create a regular MVC Controller and add different parameter bindings, verbs and routes and test client proxy for it!
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Startup.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Startup.cs
index 961454d22a..4704128d9d 100644
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Startup.cs
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/Startup.cs
@@ -1,8 +1,6 @@
using System;
using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
namespace Volo.Abp.Http
{
@@ -10,7 +8,7 @@ namespace Volo.Abp.Http
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
- services.AddApplication(options =>
+ services.AddApplication(options =>
{
options.UseAutofac();
});
@@ -19,7 +17,7 @@ namespace Volo.Abp.Http
return services.BuildServiceProviderFromFactory();
}
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
+ public void Configure(IApplicationBuilder app)
{
app.InitializeApplication();
}
diff --git a/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj
index c7e32be51a..6f16b2499e 100644
--- a/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj
+++ b/framework/test/Volo.Abp.Ldap.Tests/Volo.Abp.Ldap.Tests.csproj
@@ -1,9 +1,9 @@
+
+
- netcoreapp2.2
- latest
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj
index 4cc31224fc..68cc2bdb83 100644
--- a/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo.Abp.Localization.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Localization.Tests
- Volo.Abp.Localization.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json
index 45ccaf0d7b..ddda24d38f 100644
--- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/pt-BR.json
@@ -2,6 +2,6 @@
"culture": "pt-BR",
"texts": {
"ThisFieldIsRequired": "Este campo é obrigatório",
- "MaxLenghtErrorMessage": "Este campo pode ser no máximo de '{0}' caracteres"
+ "MaxLenghtErrorMessage": "Este campo pode ter no máximo '{0}' caracteres"
}
}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json
index 4423681d76..7425a2f176 100644
--- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/pt-BR.json
@@ -4,7 +4,7 @@
"Hello {0}.": "Olá {0}.",
"Car": "Carro",
"CarPlural": "Carros",
- "MaxLenghtErrorMessage": "O comprimento deste campo pode ser no máximo de '{0}' caracteres",
+ "MaxLenghtErrorMessage": "Este campo pode ter no máximo '{0}' caracteres",
"Universe": "Universo",
"FortyTwo": "Quarenta e Dois"
}
diff --git a/framework/test/Volo.Abp.MailKit.Tests/Volo.Abp.MailKit.Tests.csproj b/framework/test/Volo.Abp.MailKit.Tests/Volo.Abp.MailKit.Tests.csproj
index 09ea53af78..11a2ac7673 100644
--- a/framework/test/Volo.Abp.MailKit.Tests/Volo.Abp.MailKit.Tests.csproj
+++ b/framework/test/Volo.Abp.MailKit.Tests/Volo.Abp.MailKit.Tests.csproj
@@ -1,12 +1,9 @@
+
+
- netcoreapp2.2
- latest
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj
index 136dc408c6..e7d0eec2fc 100644
--- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj
+++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo.Abp.MemoryDb.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.MemoryDb.Tests
- Volo.Abp.MemoryDb.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/Repositories/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/Repositories/Repository_Basic_Tests_With_Int_Pk.cs
new file mode 100644
index 0000000000..31cd74043d
--- /dev/null
+++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/Repositories/Repository_Basic_Tests_With_Int_Pk.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.TestApp.Testing;
+
+namespace Volo.Abp.MemoryDb.Repositories
+{
+ public class Repository_Basic_Tests_With_Int_Pk : Repository_Basic_Tests_With_Int_Pk
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/TestAppMemoryDbContext.cs b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/TestAppMemoryDbContext.cs
index 902c013ed8..09b134a078 100644
--- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/TestAppMemoryDbContext.cs
+++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/TestApp/MemoryDb/TestAppMemoryDbContext.cs
@@ -8,7 +8,8 @@ namespace Volo.Abp.TestApp.MemoryDb
public class TestAppMemoryDbContext : MemoryDbContext
{
private static readonly Type[] EntityTypeList = {
- typeof(Person)
+ typeof(Person),
+ typeof(EntityWithIntPk)
};
public override IReadOnlyList GetEntityTypes()
diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj
index 0605a51a7c..bbad58f4fa 100644
--- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj
+++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.MongoDB.Tests
- Volo.Abp.MongoDB.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs
new file mode 100644
index 0000000000..58914e8e50
--- /dev/null
+++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests_With_Int_Pk.cs
@@ -0,0 +1,14 @@
+using Volo.Abp.TestApp.Testing;
+using Xunit;
+
+namespace Volo.Abp.MongoDB.Repositories
+{
+ public class Repository_Basic_Tests_With_Int_Pk : Repository_Basic_Tests_With_Int_Pk
+ {
+ [Fact(Skip = "Int PKs are not working for MongoDb")]
+ public override void Get()
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs
index fd7562f6df..03869ce566 100644
--- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs
+++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs
@@ -8,9 +8,11 @@ namespace Volo.Abp.TestApp.MongoDB
[ConnectionStringName("TestApp")]
public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext
{
- [MongoCollection("Persons")] //Intentially changed the collection name to test it
+ [MongoCollection("Persons")] //Intentionally changed the collection name to test it
public IMongoCollection People => Collection();
+ public IMongoCollection EntityWithIntPks => Collection();
+
public IMongoCollection Cities => Collection();
protected override void CreateModel(IMongoModelBuilder modelBuilder)
diff --git a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj
index 1258956caf..17ce3073c5 100644
--- a/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj
+++ b/framework/test/Volo.Abp.MultiTenancy.Tests/Volo.Abp.MultiTenancy.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.MultiTenancy.Tests
- Volo.Abp.MultiTenancy.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.csproj b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.csproj
new file mode 100644
index 0000000000..7af0ec54b6
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo.Abp.ObjectMapping.Tests.csproj
@@ -0,0 +1,16 @@
+
+
+
+
+
+ netcoreapp3.0
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestBase.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestBase.cs
new file mode 100644
index 0000000000..9ba65b5a10
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestBase.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.ObjectMapping
+{
+ public abstract class AbpObjectMappingTestBase : AbpIntegratedTest
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestModule.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestModule.cs
new file mode 100644
index 0000000000..90b6943412
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/AbpObjectMappingTestModule.cs
@@ -0,0 +1,17 @@
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.ObjectMapping
+{
+ [DependsOn(
+ typeof(AbpObjectMappingModule),
+ typeof(AbpTestBaseModule)
+ )]
+ public class AbpObjectMappingTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddTest1AutoObjectMappingProvider();
+ context.Services.AddTest2AutoObjectMappingProvider();
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ContextSpecificMapper_Tests.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ContextSpecificMapper_Tests.cs
new file mode 100644
index 0000000000..e24dd9a15e
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/ContextSpecificMapper_Tests.cs
@@ -0,0 +1,24 @@
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.ObjectMapping
+{
+ public class ContextSpecificMapper_Tests : AbpObjectMappingTestBase
+ {
+ [Fact]
+ public void Should_Resolve_Correct_ObjectMappper_For_Specific_Context()
+ {
+ GetRequiredService>()
+ .ShouldBeOfType(typeof(DefaultObjectMapper));
+
+ GetRequiredService>()
+ .ShouldBeOfType(typeof(Test1AutoObjectMappingProvider));
+
+ GetRequiredService>()
+ .ShouldBeOfType(typeof(DefaultObjectMapper));
+
+ GetRequiredService>()
+ .ShouldBeOfType(typeof(Test2AutoObjectMappingProvider));
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext1.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext1.cs
new file mode 100644
index 0000000000..96fcb94686
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext1.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.ObjectMapping
+{
+ public class MappingContext1
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext2.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext2.cs
new file mode 100644
index 0000000000..131a9a268b
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/MappingContext2.cs
@@ -0,0 +1,7 @@
+namespace Volo.Abp.ObjectMapping
+{
+ public class MappingContext2
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test1AutoObjectMappingProvider.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test1AutoObjectMappingProvider.cs
new file mode 100644
index 0000000000..b96df71aed
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test1AutoObjectMappingProvider.cs
@@ -0,0 +1,22 @@
+using Volo.Abp.DependencyInjection;
+
+namespace Volo.Abp.ObjectMapping
+{
+ public class Test1AutoObjectMappingProvider : Test1AutoObjectMappingProvider, IAutoObjectMappingProvider
+ {
+
+ }
+
+ public class Test1AutoObjectMappingProvider : IAutoObjectMappingProvider, ITransientDependency
+ {
+ public TDestination Map(object source)
+ {
+ return default;
+ }
+
+ public TDestination Map(TSource source, TDestination destination)
+ {
+ return default;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test2AutoObjectMappingProvider.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test2AutoObjectMappingProvider.cs
new file mode 100644
index 0000000000..3ac0792570
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/Test2AutoObjectMappingProvider.cs
@@ -0,0 +1,15 @@
+namespace Volo.Abp.ObjectMapping
+{
+ public class Test2AutoObjectMappingProvider : IAutoObjectMappingProvider
+ {
+ public TDestination Map(object source)
+ {
+ return default;
+ }
+
+ public TDestination Map(TSource source, TDestination destination)
+ {
+ return default;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/TestContextRegistrar.cs b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/TestContextRegistrar.cs
new file mode 100644
index 0000000000..b7568fc15e
--- /dev/null
+++ b/framework/test/Volo.Abp.ObjectMapping.Tests/Volo/Abp/ObjectMapping/TestContextRegistrar.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Volo.Abp.ObjectMapping
+{
+ public static class TestContextRegistrar
+ {
+ public static IServiceCollection AddTest1AutoObjectMappingProvider(this IServiceCollection services)
+ {
+ return services
+ .AddTransient<
+ IAutoObjectMappingProvider,
+ Test1AutoObjectMappingProvider
+ >();
+ }
+
+ public static IServiceCollection AddTest2AutoObjectMappingProvider(this IServiceCollection services)
+ {
+ return services
+ .AddTransient<
+ IAutoObjectMappingProvider,
+ Test2AutoObjectMappingProvider
+ >();
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj
index 696592c5d3..1534cb28f4 100644
--- a/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj
+++ b/framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Security.Tests
- Volo.Abp.Security.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj
index b800df4fb0..65bb49d57a 100644
--- a/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj
+++ b/framework/test/Volo.Abp.Serialization.Tests/Volo.Abp.Serialization.Tests.csproj
@@ -1,14 +1,9 @@
+
+
- netcoreapp2.2
- latest
- Volo.Abp.Serialization.Tests
- Volo.Abp.Serialization.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj
index 419451777d..ef91443b2a 100644
--- a/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj
+++ b/framework/test/Volo.Abp.Settings.Tests/Volo.Abp.Settings.Tests.csproj
@@ -1,14 +1,9 @@
+
+
- netcoreapp2.2
- latest
- Volo.Abp.Settings.Tests
- Volo.Abp.Settings.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj b/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj
index 3b1f95fabb..0594067fa5 100644
--- a/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj
+++ b/framework/test/Volo.Abp.Specifications.Tests/Volo.Abp.Specifications.Tests.csproj
@@ -1,14 +1,9 @@
+
+
- netcoreapp2.2
- latest
- Volo.Abp.Specifications.Tests
- Volo.Abp.Specifications.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj
index 1d999ea9d5..90dbb56a8e 100644
--- a/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj
+++ b/framework/test/Volo.Abp.TestApp.Tests/Volo.Abp.TestApp.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.TestApp.Tests
- Volo.Abp.TestApp.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj
index be55d0dc90..d72d42e48a 100644
--- a/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj
+++ b/framework/test/Volo.Abp.TestApp/Volo.Abp.TestApp.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.TestApp
- Volo.Abp.TestApp
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/EntityWithIntPk.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/EntityWithIntPk.cs
new file mode 100644
index 0000000000..040af1a4e9
--- /dev/null
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/EntityWithIntPk.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Volo.Abp.Domain.Entities;
+
+namespace Volo.Abp.TestApp.Domain
+{
+ public class EntityWithIntPk : AggregateRoot
+ {
+ public string Name { get; set; }
+
+ public EntityWithIntPk()
+ {
+
+ }
+
+ public EntityWithIntPk(string name)
+ {
+ Name = name;
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
index 16ac62589e..3bbec118a2 100644
--- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Person.cs
@@ -23,8 +23,8 @@ namespace Volo.Abp.TestApp.Domain
}
public Person(Guid id, string name, int age, Guid? tenantId = null, Guid? cityId = null)
+ : base(id)
{
- Id = id;
Name = name;
Age = age;
TenantId = tenantId;
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs
index e53f2bc2e3..20292e3de8 100644
--- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/Phone.cs
@@ -49,8 +49,8 @@ namespace Volo.Abp.TestApp.Domain
}
public Order(Guid id, string referenceNo)
+ : base(id)
{
- Id = id;
ReferenceNo = referenceNo;
OrderLines = new List();
}
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs
index 25886f77a6..1f955b3e82 100644
--- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestDataBuilder.cs
@@ -17,19 +17,23 @@ namespace Volo.Abp.TestApp
private readonly IBasicRepository _personRepository;
private readonly ICityRepository _cityRepository;
+ private readonly IRepository _entityWithIntPksRepository;
public TestDataBuilder(
IBasicRepository personRepository,
- ICityRepository cityRepository)
+ ICityRepository cityRepository,
+ IRepository entityWithIntPksRepository)
{
_personRepository = personRepository;
_cityRepository = cityRepository;
+ _entityWithIntPksRepository = entityWithIntPksRepository;
}
public void Build()
{
AddCities();
AddPeople();
+ AddEntitiesWithPks();
}
private void AddCities()
@@ -63,5 +67,10 @@ namespace Volo.Abp.TestApp
_personRepository.Insert(tenant1Person1);
_personRepository.Insert(tenant1Person2);
}
+
+ private void AddEntitiesWithPks()
+ {
+ _entityWithIntPksRepository.Insert(new EntityWithIntPk("Entity1"));
+ }
}
}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs
new file mode 100644
index 0000000000..f8a2f4e8e9
--- /dev/null
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/Repository_Basic_Tests_With_Int_Pk.cs
@@ -0,0 +1,42 @@
+using System.Linq;
+using Shouldly;
+using Volo.Abp.Domain.Repositories;
+using Volo.Abp.Modularity;
+using Volo.Abp.TestApp.Domain;
+using Xunit;
+
+namespace Volo.Abp.TestApp.Testing
+{
+ public abstract class Repository_Basic_Tests_With_Int_Pk : TestAppTestBase
+ where TStartupModule : IAbpModule
+ {
+ protected readonly IRepository EntityWithIntPkRepository;
+
+ protected Repository_Basic_Tests_With_Int_Pk()
+ {
+ EntityWithIntPkRepository = GetRequiredService>();
+ }
+
+ [Fact]
+ public virtual void FirstOrDefault()
+ {
+ WithUnitOfWork(() =>
+ {
+ var entity = EntityWithIntPkRepository.FirstOrDefault(e => e.Name == "Entity1");
+ entity.ShouldNotBeNull();
+ entity.Name.ShouldBe("Entity1");
+ });
+ }
+
+ [Fact]
+ public virtual void Get()
+ {
+ WithUnitOfWork(() =>
+ {
+ var entity = EntityWithIntPkRepository.Get(1);
+ entity.ShouldNotBeNull();
+ entity.Name.ShouldBe("Entity1");
+ });
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj
index 9a1f142f01..7937d99580 100644
--- a/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj
+++ b/framework/test/Volo.Abp.UI.Navigation.Tests/Volo.Abp.UI.Navigation.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.UI.Navigation.Tests
- Volo.Abp.UI.Navigation.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj
index dd868b860f..6ec5ddac26 100644
--- a/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj
+++ b/framework/test/Volo.Abp.Uow.Tests/Volo.Abp.Uow.Tests.csproj
@@ -1,14 +1,9 @@
+
+
- netcoreapp2.2
- latest
- Volo.Abp.Uow.Tests
- Volo.Abp.Uow.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj
index ea192bb236..b1f30e3ea5 100644
--- a/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj
+++ b/framework/test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.Validation.Tests
- Volo.Abp.Validation.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj
index e74d97c437..440525bc9e 100644
--- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj
+++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj
@@ -1,13 +1,9 @@
+
+
- netcoreapp2.2
- Volo.Abp.VirtualFileSystem.Tests
- Volo.Abp.VirtualFileSystem.Tests
- true
- false
- false
- false
+ netcoreapp3.0
diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/DynamicFileProvider_Tests.cs b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/DynamicFileProvider_Tests.cs
index e3ff516949..45aaa88fd4 100644
--- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/DynamicFileProvider_Tests.cs
+++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/DynamicFileProvider_Tests.cs
@@ -1,5 +1,4 @@
using System;
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using Shouldly;
@@ -24,8 +23,8 @@ namespace Volo.Abp.VirtualFileSystem
_dynamicFileProvider.AddOrUpdate(
new InMemoryFileInfo(
- fileContent.GetBytes(),
"/my-files/test.txt",
+ fileContent.GetBytes(),
"test.txt"
)
);
@@ -42,8 +41,8 @@ namespace Volo.Abp.VirtualFileSystem
_dynamicFileProvider.AddOrUpdate(
new InMemoryFileInfo(
- "Hello World".GetBytes(),
"/my-files/test.txt",
+ "Hello World".GetBytes(),
"test.txt"
)
);
@@ -60,8 +59,8 @@ namespace Volo.Abp.VirtualFileSystem
_dynamicFileProvider.AddOrUpdate(
new InMemoryFileInfo(
- "Hello World UPDATED".GetBytes(),
"/my-files/test.txt",
+ "Hello World UPDATED".GetBytes(),
"test.txt"
)
);
@@ -74,8 +73,8 @@ namespace Volo.Abp.VirtualFileSystem
_dynamicFileProvider.AddOrUpdate(
new InMemoryFileInfo(
- "Hello World UPDATED 2".GetBytes(),
"/my-files/test.txt",
+ "Hello World UPDATED 2".GetBytes(),
"test.txt"
)
);
@@ -88,7 +87,7 @@ namespace Volo.Abp.VirtualFileSystem
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
-
+
}
}
}
diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs
index 2c853e3a19..e376d24aa0 100644
--- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs
+++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo/Abp/VirtualFileSystem/VirtualFileProvider_Tests.cs
@@ -1,4 +1,5 @@
using System.IO;
+using System.Linq;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
@@ -32,6 +33,19 @@ namespace Volo.Abp.VirtualFileSystem
}
}
+ [Fact]
+ public void Should_Define_And_Get_Embedded_Directory_Contents()
+ {
+ //Act
+ var contents = _virtualFileProvider.GetDirectoryContents("/js");
+
+ //Assert
+ contents.Exists.ShouldNotBeNull();
+
+ var contentList = contents.ToList();
+ contentList.ShouldContain(x => x.Name == "jquery-3-1-1-min.js");
+ }
+
[DependsOn(typeof(AbpVirtualFileSystemModule))]
public class TestModule : AbpModule
{
diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json
index 892e60f89e..f5167f51f2 100644
--- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json
+++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json
@@ -16,6 +16,23 @@
"Register": "Register",
"InvalidLoginRequest": "Invalid login request",
"ThereAreNoLoginSchemesConfiguredForThisClient": "There are no login schemes configured for this client.",
- "LogInUsingYourProviderAccount": "Log in using your {0} account"
+ "LogInUsingYourProviderAccount": "Log in using your {0} account",
+ "DisplayName:CurrentPassword": "Current password",
+ "DisplayName:NewPassword": "New password",
+ "DisplayName:NewPasswordConfirm": "Confirm new password",
+ "PasswordChangedMessage": "Your password has been changed successfully.",
+ "DisplayName:UserName": "User name",
+ "DisplayName:Email": "Email",
+ "DisplayName:Name": "Name",
+ "DisplayName:Surname": "Surname",
+ "DisplayName:Password": "Password",
+ "DisplayName:EmailAddress": "Email address",
+ "DisplayName:PhoneNumber": "Phone number",
+ "PersonalSettings": "Personal settings",
+ "PersonalSettingsSaved": "Personal settings saved",
+ "PasswordChanged": "Password changed",
+ "NewPasswordConfirmFailed": "Please confirm the new password.",
+ "Manage": "Manage",
+ "ManageYourProfile": "Manage your profile"
}
}
\ No newline at end of file
diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json
new file mode 100644
index 0000000000..cbb99587cd
--- /dev/null
+++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es-mx.json
@@ -0,0 +1,38 @@
+{
+ "culture": "es-MX",
+ "texts": {
+ "UserName": "Nombre de usuario",
+ "EmailAddress": "Dirección de correo electrónico",
+ "UserNameOrEmailAddress": "Nombre de usuario o dirección de correo electrónico",
+ "Password": "Contraseña",
+ "RememberMe": "Recuérdame",
+ "UseAnotherServiceToLogin": "Usar otro servicio para iniciar sesión",
+ "UserLockedOutMessage": "La cuenta de usuario ha sido bloqueada debido a los intentos de inicio de sesión no válido. Por favor, espere un rato y vuelve a intentarlo.",
+ "InvalidUserNameOrPassword": "No válido nombre de usuario o la contraseña!",
+ "LoginIsNotAllowed": "No está permitido el inicio de sesión! Usted tendrá que confirmar su correo electrónico\/número de teléfono.",
+ "SelfRegistrationDisabledMessage": "El autoregistro de usuario está deshabilitado para esta aplicación. Póngase en contacto con el administrador de la aplicación para registrar un nuevo usuario.",
+ "Login": "Iniciar sesión",
+ "Cancel": "Cancelar",
+ "Register": "Registrar",
+ "InvalidLoginRequest": "Solicitud de inicio de sesión no válido",
+ "ThereAreNoLoginSchemesConfiguredForThisClient": "No hay ningún inicio de sesión esquemas configurado para este cliente.",
+ "LogInUsingYourProviderAccount": "Inicia sesión con tu cuenta de {0} ",
+ "DisplayName:CurrentPassword": "Contraseña actual",
+ "DisplayName:NewPassword": "Nueva contraseña",
+ "DisplayName:NewPasswordConfirm": "Confirmar nueva contraseña",
+ "PasswordChangedMessage": "Su contraseña ha sido cambiada con éxito.",
+ "DisplayName:UserName": "Nombre de usuario",
+ "DisplayName:Email": "Correo electrónico",
+ "DisplayName:Name": "Nombre",
+ "DisplayName:Surname": "Apellido",
+ "DisplayName:Password": "Contraseña",
+ "DisplayName:EmailAddress": "Dirección de correo electrónico",
+ "DisplayName:PhoneNumber": "Número de teléfono",
+ "PersonalSettings": "Configuración Personal",
+ "PersonalSettingsSaved": "Ajustes personales guardados",
+ "PasswordChanged": "Cambia la contraseña",
+ "NewPasswordConfirmFailed": "Por favor, confirme la nueva contraseña.",
+ "Manage": "Administrar",
+ "ManageYourProfile": "Gestionar tu perfil"
+ }
+}
diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json
index 0513d99afd..ea7789357b 100644
--- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json
+++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/pt-BR.json
@@ -7,9 +7,9 @@
"Password": "Senha",
"RememberMe": "Lembrar",
"UseAnotherServiceToLogin": "Usar outro serviço para entrar",
- "UserLockedOutMessage": "Esta conta de usuário está bloqueada devido a muitas tentativas de entrar. Por favor, espero alguns instantes e tente novamente.",
+ "UserLockedOutMessage": "Esta conta de usuário está bloqueada devido a muitas tentativas de acesso. Por favor, espero alguns instantes e tente novamente.",
"InvalidUserNameOrPassword": "Usuário ou senha estão incorretos!",
- "LoginIsNotAllowed": "Você não possui permissão para entrar! Você deveconfirmar seu e-mail ou número de telefone.",
+ "LoginIsNotAllowed": "Você não possui permissão para entrar! Você deve confirmar seu e-mail ou número de telefone.",
"SelfRegistrationDisabledMessage": "Não é permitido que você crie uma nova conta neste site. Contate um administrador para que ele crie uma conta para você.",
"Login": "Entrar",
"Cancel": "Cancelar",
diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj b/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj
index 14f9c8f991..288e7f4e9b 100644
--- a/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj
+++ b/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj
@@ -10,7 +10,7 @@
-
+
diff --git a/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.csproj b/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.csproj
index c5d14ebcc4..9ecb118b9b 100644
--- a/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.csproj
+++ b/modules/account/src/Volo.Abp.Account.HttpApi.Client/Volo.Abp.Account.HttpApi.Client.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netcoreapp3.0Volo.Abp.Account.HttpApi.ClientVolo.Abp.Account.HttpApi.Client
diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj
index 8c028185c7..2af9e29df4 100644
--- a/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj
+++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo.Abp.Account.HttpApi.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netcoreapp3.0Volo.Abp.Account.HttpApiVolo.Abp.Account.HttpApi
@@ -12,6 +12,7 @@
+
diff --git a/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs
index 3a58d11643..0e210dd8de 100644
--- a/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs
+++ b/modules/account/src/Volo.Abp.Account.HttpApi/Volo/Abp/Account/AbpAccountHttpApiModule.cs
@@ -1,6 +1,7 @@
using Localization.Resources.AbpUi;
using Volo.Abp.Account.Localization;
using Volo.Abp.AspNetCore.Mvc;
+using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
@@ -8,6 +9,7 @@ namespace Volo.Abp.Account
{
[DependsOn(
typeof(AbpAccountApplicationContractsModule),
+ typeof(AbpIdentityHttpApiModule),
typeof(AbpAspNetCoreMvcModule))]
public class AbpAccountHttpApiModule : AbpModule
{
diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs
index 666bcfadf0..b6902e86d8 100644
--- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs
+++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/IdentityServerSupportedLoginModel.cs
@@ -52,15 +52,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
//TODO: Reference AspNetCore MultiTenancy module and use options to get the tenant key!
var tenant = context.Parameters[TenantResolverConsts.DefaultTenantKey];
- if (string.IsNullOrEmpty(tenant))
- {
- if (Request.Cookies.ContainsKey(TenantResolverConsts.DefaultTenantKey))
- {
- CurrentTenant.Change(null);
- Response.Cookies.Delete(TenantResolverConsts.DefaultTenantKey);
- }
- }
- else
+ if (!string.IsNullOrEmpty(tenant))
{
CurrentTenant.Change(Guid.Parse(tenant));
Response.Cookies.Append(TenantResolverConsts.DefaultTenantKey, tenant);
diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj
index 724ecc38ef..a03e55b51f 100644
--- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj
+++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netcoreapp3.0Volo.Abp.Account.Web.IdentityServerVolo.Abp.Account.Web.IdentityServertrue
@@ -16,10 +16,9 @@
-
-
-
-
+
+
+
diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs
index 2741aabe82..9bdd8095ed 100644
--- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs
+++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs
@@ -2,17 +2,13 @@
using Localization.Resources.AbpUi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
+using Volo.Abp.Account.Localization;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.Account.Web
{
public class AbpAccountUserMenuContributor : IMenuContributor
{
- public AbpAccountUserMenuContributor()
- {
-
- }
-
public Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name != StandardMenus.User)
@@ -20,13 +16,11 @@ namespace Volo.Abp.Account.Web
return Task.CompletedTask;
}
- var l = context.ServiceProvider.GetRequiredService>();
-
- context.Menu.AddItem(new ApplicationMenuItem("Account.ChangePassword", l["ChangePassword"], icon: "fa fa-key", url: "#", elementId: "abp-account-change-password"));
-
- context.Menu.AddItem(new ApplicationMenuItem("Account.PersonalSettings", l["PersonalInfo"], icon: "fa fa-info", url: "#", elementId: "abp-account-personal-settings"));
+ var uiResource = context.ServiceProvider.GetRequiredService>();
+ var accountResource = context.ServiceProvider.GetRequiredService>();
- context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", l["Logout"], url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000));
+ context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountResource["ManageYourProfile"], url: "/Account/Manage", icon: "fa fa-cog", order: 1000, null));
+ context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", uiResource["Logout"], url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000));
return Task.CompletedTask;
}
diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs
new file mode 100644
index 0000000000..ab7ea41269
--- /dev/null
+++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs
@@ -0,0 +1,14 @@
+using Volo.Abp.Account.Web.Pages.Account;
+using Volo.Abp.Identity;
+using AutoMapper;
+
+namespace Volo.Abp.Account.Web
+{
+ public class AbpAccountWebAutoMapperProfile : Profile
+ {
+ public AbpAccountWebAutoMapperProfile()
+ {
+ CreateMap();
+ }
+ }
+}
diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs
index f7481b3485..5cada69450 100644
--- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs
+++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs
@@ -1,8 +1,10 @@
-using Microsoft.Extensions.DependencyInjection;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Account.Localization;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
+using Volo.Abp.AutoMapper;
using Volo.Abp.Identity.AspNetCore;
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
@@ -13,6 +15,7 @@ namespace Volo.Abp.Account.Web
[DependsOn(
typeof(AbpAccountHttpApiModule),
typeof(AbpIdentityAspNetCoreModule),
+ typeof(AbpAutoMapperModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule)
)]
public class AbpAccountWebModule : AbpModule
@@ -41,6 +44,16 @@ namespace Volo.Abp.Account.Web
{
options.Contributors.Add(new AccountModuleToolbarContributor());
});
+
+ Configure(options =>
+ {
+ options.Conventions.AuthorizePage("/Account/Manage");
+ });
+
+ Configure(options =>
+ {
+ options.AddProfile(validate: true);
+ });
}
}
}
diff --git a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs
index 5bc347d84d..9f10b7aa1d 100644
--- a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs
+++ b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/AccountController.cs
@@ -1,5 +1,4 @@
using System;
-using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
@@ -9,6 +8,7 @@ using Volo.Abp.Identity;
using Volo.Abp.Validation;
using SignInResult = Microsoft.AspNetCore.Identity.SignInResult;
using UserLoginInfo = Volo.Abp.Account.Web.Areas.Account.Controllers.Models.UserLoginInfo;
+using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace Volo.Abp.Account.Web.Areas.Account.Controllers
{
diff --git a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/LogoutController.cs b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/LogoutController.cs
index 5a5f517851..1f1b43b853 100644
--- a/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/LogoutController.cs
+++ b/modules/account/src/Volo.Abp.Account.Web/Areas/Account/Controllers/LogoutController.cs
@@ -2,7 +2,7 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
-using Volo.Abp.Identity;
+using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace Volo.Abp.Account.Web.Areas.Account.Controllers
{
diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs
index 4a2751f21b..c1c1880650 100644
--- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs
+++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/AccountPageModel.cs
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Account.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Identity;
+using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace Volo.Abp.Account.Web.Pages.Account
{
diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
index aa168344a5..cc82de414f 100644
--- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
+++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
@@ -14,6 +14,7 @@ using Volo.Abp.Identity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
+using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace Volo.Abp.Account.Web.Pages.Account
{
diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml
new file mode 100644
index 0000000000..36c94271d1
--- /dev/null
+++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml
@@ -0,0 +1,50 @@
+@page
+@model Volo.Abp.Account.Web.Pages.Account.ManageModel
+@using Volo.Abp.Identity.Settings
+@using Volo.Abp.Settings
+@using Volo.Abp.AspNetCore.Mvc.UI.Theming
+@inject ISettingProvider SettingManager
+@inject IThemeManager ThemeManager
+@inherits Volo.Abp.Account.Web.Pages.Account.AccountPage
+@{
+ Layout = ThemeManager.CurrentTheme.GetApplicationLayout();
+ var isUserNameUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled), "true",
+ StringComparison.OrdinalIgnoreCase);
+
+ var isEmailUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsEmailUpdateEnabled), "true",
+ StringComparison.OrdinalIgnoreCase);
+}
+@section scripts {
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs
new file mode 100644
index 0000000000..9fba470929
--- /dev/null
+++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml.cs
@@ -0,0 +1,72 @@
+using System.ComponentModel.DataAnnotations;
+using System.Threading.Tasks;
+using Volo.Abp.Identity;
+
+namespace Volo.Abp.Account.Web.Pages.Account
+{
+ public class ManageModel : AccountPageModel
+ {
+ public ChangePasswordInfoModel ChangePasswordInfoModel { get; set; }
+
+ public PersonalSettingsInfoModel PersonalSettingsInfoModel { get; set; }
+
+ private readonly IProfileAppService _profileAppService;
+
+ public ManageModel(IProfileAppService profileAppService)
+ {
+ _profileAppService = profileAppService;
+ }
+
+ public async Task OnGetAsync()
+ {
+ var user = await _profileAppService.GetAsync();
+
+ PersonalSettingsInfoModel = ObjectMapper.Map(user);
+ }
+ }
+
+ public class ChangePasswordInfoModel
+ {
+ [Required]
+ [StringLength(IdentityUserConsts.MaxPasswordLength)]
+ [Display(Name = "DisplayName:CurrentPassword")]
+ [DataType(DataType.Password)]
+ public string CurrentPassword { get; set; }
+
+ [Required]
+ [StringLength(IdentityUserConsts.MaxPasswordLength)]
+ [Display(Name = "DisplayName:NewPassword")]
+ [DataType(DataType.Password)]
+ public string NewPassword { get; set; }
+
+ [Required]
+ [StringLength(IdentityUserConsts.MaxPasswordLength)]
+ [Display(Name = "DisplayName:NewPasswordConfirm")]
+ [DataType(DataType.Password)]
+ public string NewPasswordConfirm { get; set; }
+ }
+ public class PersonalSettingsInfoModel
+ {
+ [Required]
+ [StringLength(IdentityUserConsts.MaxUserNameLength)]
+ [Display(Name = "DisplayName:UserName")]
+ public string UserName { get; set; }
+
+ [Required]
+ [StringLength(IdentityUserConsts.MaxEmailLength)]
+ [Display(Name = "DisplayName:Email")]
+ public string Email { get; set; }
+
+ [StringLength(IdentityUserConsts.MaxNameLength)]
+ [Display(Name = "DisplayName:Name")]
+ public string Name { get; set; }
+
+ [StringLength(IdentityUserConsts.MaxSurnameLength)]
+ [Display(Name = "DisplayName:Surname")]
+ public string Surname { get; set; }
+
+ [StringLength(IdentityUserConsts.MaxPhoneNumberLength)]
+ [Display(Name = "DisplayName:PhoneNumber")]
+ public string PhoneNumber { get; set; }
+ }
+}
diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.js b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.js
new file mode 100644
index 0000000000..844151c71b
--- /dev/null
+++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.js
@@ -0,0 +1,50 @@
+(function ($) {
+
+ var l = abp.localization.getResource('AbpAccount');
+
+ var _profileService = volo.abp.identity.profile;
+
+ $("#ChangePasswordForm").submit(function (e) {
+ e.preventDefault();
+
+ if (!$("#ChangePasswordForm").valid()) {
+ return false;
+ }
+
+ var input = $("#ChangePasswordForm").serializeFormToObject().changePasswordInfoModel;
+
+ if (input.newPassword != input.newPasswordConfirm || input.currentPassword == '') {
+ abp.message.error(l("NewPasswordConfirmFailed"));
+ return;
+ }
+
+ if (input.currentPassword == '') {
+ return;
+ }
+
+ _profileService.changePassword(
+ input
+ ).then(function (result) {
+ abp.message.success(l("PasswordChanged"));
+ });
+
+ });
+
+ $("#PersonalSettingsForm").submit(function (e) {
+ e.preventDefault();
+
+ if (!$("#PersonalSettingsForm").valid()) {
+ return false;
+ }
+
+ var input = $("#PersonalSettingsForm").serializeFormToObject().personalSettingsInfoModel;
+
+ _profileService.update(
+ input
+ ).then(function (result) {
+ abp.notify.success(l("PersonalSettingsSaved"));
+ });
+
+ });
+
+})(jQuery);
\ No newline at end of file
diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs
index d5ffdefd88..1a16cecc2a 100644
--- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs
+++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs
@@ -1,14 +1,11 @@
-using System;
-using System.ComponentModel;
-using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Account.Web.Settings;
-using Volo.Abp.Identity;
using Volo.Abp.Settings;
-using Volo.Abp.UI;
using Volo.Abp.Uow;
+using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace Volo.Abp.Account.Web.Pages.Account
{
diff --git a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj
index 86706f28d5..3101861d54 100644
--- a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj
+++ b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj
@@ -3,33 +3,40 @@
- netstandard2.0
+ netcoreapp3.0Volo.Abp.Account.WebVolo.Abp.Account.Web
- true$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;falsefalsefalseVolo.Abp.Account.Web
+ trueLibrary
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.csproj b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.csproj
index 5fa709490c..d7153fa75f 100644
--- a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.csproj
+++ b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo.Abp.Account.Application.Tests.csproj
@@ -1,11 +1,11 @@
- netcoreapp2.2
+ netcoreapp3.0
-
+
diff --git a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs
index a2dec7ddff..634cbfc253 100644
--- a/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs
+++ b/modules/account/test/Volo.Abp.Account.Application.Tests/Volo/Abp/Account/AccountAppService_Tests.cs
@@ -25,7 +25,7 @@ namespace Volo.Abp.Account.Pro.Application.Tests.Volo.Abp.Account
[Fact]
public async Task RegisterAsync()
{
- var registerDto = new RegisterDto()
+ var registerDto = new RegisterDto
{
UserName = "bob.lee",
EmailAddress = "bob.lee@abp.io",
@@ -36,7 +36,7 @@ namespace Volo.Abp.Account.Pro.Application.Tests.Volo.Abp.Account
await _accountAppService.RegisterAsync(registerDto);
var user = await _identityUserRepository.FindByNormalizedUserNameAsync(
- _lookupNormalizer.Normalize("bob.lee"));
+ _lookupNormalizer.NormalizeName("bob.lee"));
user.ShouldNotBeNull();
user.UserName.ShouldBe("bob.lee");
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
index e94eee3d88..1da98f36aa 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
@@ -13,6 +13,8 @@ namespace Volo.Abp.AuditLogging
string sorting = null,
int maxResultCount = 50,
int skipCount = 0,
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
@@ -26,6 +28,8 @@ namespace Volo.Abp.AuditLogging
CancellationToken cancellationToken = default);
Task GetCountAsync(
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.csproj b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.csproj
index ff72eb23da..93422d8f3f 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.csproj
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo.Abp.AuditLogging.EntityFrameworkCore.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netstandard2.1
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
index 043c3d8988..c60dfcc4d7 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
@@ -23,6 +23,8 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
string sorting = null,
int maxResultCount = 50,
int skipCount = 0,
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
@@ -35,16 +37,31 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
- var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxExecutionDuration, minExecutionDuration, hasException, httpStatusCode, includeDetails);
+ var query = GetListQuery(
+ startTime,
+ endTime,
+ httpMethod,
+ url,
+ userName,
+ applicationName,
+ correlationId,
+ maxExecutionDuration,
+ minExecutionDuration,
+ hasException,
+ httpStatusCode,
+ includeDetails
+ );
var auditLogs = await query.OrderBy(sorting ?? "executionTime desc")
.PageBy(skipCount, maxResultCount)
- .ToListAsync();
+ .ToListAsync(GetCancellationToken(cancellationToken));
return auditLogs;
}
public async Task GetCountAsync(
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
@@ -56,14 +73,28 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default)
{
- var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxExecutionDuration, minExecutionDuration, hasException, httpStatusCode);
+ var query = GetListQuery(
+ startTime,
+ endTime,
+ httpMethod,
+ url,
+ userName,
+ applicationName,
+ correlationId,
+ maxExecutionDuration,
+ minExecutionDuration,
+ hasException,
+ httpStatusCode
+ );
- var totalCount = await query.LongCountAsync();
+ var totalCount = await query.LongCountAsync(GetCancellationToken(cancellationToken));
return totalCount;
}
private IQueryable GetListQuery(
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
@@ -77,16 +108,18 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
{
return DbSet.AsNoTracking()
.IncludeDetails(includeDetails)
- .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions.Length > 0)
- .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions.Length == 0)
- .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod != null && auditLog.HttpMethod.ToLowerInvariant() == httpMethod.ToLowerInvariant())
- .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.ToLowerInvariant().Contains(url.ToLowerInvariant()))
- .WhereIf(userName != null, auditLog => auditLog.UserName != null && auditLog.UserName.ToLowerInvariant() == userName.ToLowerInvariant())
- .WhereIf(applicationName != null, auditLog => auditLog.ApplicationName != null && auditLog.ApplicationName.ToLowerInvariant() == applicationName.ToLowerInvariant())
- .WhereIf(correlationId != null, auditLog => auditLog.CorrelationId != null && auditLog.CorrelationId.ToLowerInvariant() == correlationId.ToLowerInvariant())
+ .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
+ .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
+ .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null)
+ .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null)
+ .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod)
+ .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url))
+ .WhereIf(userName != null, auditLog => auditLog.UserName == userName)
+ .WhereIf(applicationName != null, auditLog => auditLog.ApplicationName == applicationName)
+ .WhereIf(correlationId != null, auditLog => auditLog.CorrelationId == correlationId)
.WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == (int?)httpStatusCode)
- .WhereIf(maxExecutionDuration != null && maxExecutionDuration > 0, auditLog => auditLog.ExecutionDuration <= maxExecutionDuration)
- .WhereIf(minExecutionDuration != null && minExecutionDuration > 0, auditLog => auditLog.ExecutionDuration >= minExecutionDuration);
+ .WhereIf(maxExecutionDuration != null && maxExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration <= maxExecutionDuration)
+ .WhereIf(minExecutionDuration != null && minExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration >= minExecutionDuration);
}
public override IQueryable WithDetails()
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
index f70bd1deaf..cead3fa2a9 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
@@ -24,6 +24,8 @@ namespace Volo.Abp.AuditLogging.MongoDB
string sorting = null,
int maxResultCount = 50,
int skipCount = 0,
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
@@ -36,14 +38,29 @@ namespace Volo.Abp.AuditLogging.MongoDB
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
- var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxDuration, minDuration, hasException, httpStatusCode, includeDetails);
+ var query = GetListQuery(
+ startTime,
+ endTime,
+ httpMethod,
+ url,
+ userName,
+ applicationName,
+ correlationId,
+ maxDuration,
+ minDuration,
+ hasException,
+ httpStatusCode,
+ includeDetails
+ );
return await query.OrderBy(sorting ?? "executionTime desc").As>()
.PageBy>(skipCount, maxResultCount)
- .ToListAsync();
+ .ToListAsync(GetCancellationToken(cancellationToken));
}
public async Task GetCountAsync(
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
@@ -55,14 +72,29 @@ namespace Volo.Abp.AuditLogging.MongoDB
HttpStatusCode? httpStatusCode = null,
CancellationToken cancellationToken = default)
{
- var query = GetListQuery(httpMethod, url, userName, applicationName, correlationId, maxDuration, minDuration, hasException, httpStatusCode);
+ var query = GetListQuery(
+ startTime,
+ endTime,
+ httpMethod,
+ url,
+ userName,
+ applicationName,
+ correlationId,
+ maxDuration,
+ minDuration,
+ hasException,
+ httpStatusCode
+ );
- var count = await query.As>().LongCountAsync();
+ var count = await query.As>()
+ .LongCountAsync(GetCancellationToken(cancellationToken));
return count;
}
private IQueryable GetListQuery(
+ DateTime? startTime = null,
+ DateTime? endTime = null,
string httpMethod = null,
string url = null,
string userName = null,
@@ -75,13 +107,15 @@ namespace Volo.Abp.AuditLogging.MongoDB
bool includeDetails = false)
{
return GetMongoQueryable()
- .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions.Length > 0)
- .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions.Length == 0)
- .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod != null && auditLog.HttpMethod.ToLowerInvariant() == httpMethod.ToLowerInvariant())
- .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.ToLowerInvariant().Contains(url.ToLowerInvariant()))
- .WhereIf(userName != null, auditLog => auditLog.UserName != null && auditLog.UserName.ToLowerInvariant() == userName.ToLowerInvariant())
- .WhereIf(applicationName != null, auditLog => auditLog.ApplicationName != null && auditLog.ApplicationName.ToLowerInvariant() == applicationName.ToLowerInvariant())
- .WhereIf(correlationId != null, auditLog => auditLog.CorrelationId != null && auditLog.CorrelationId.ToLowerInvariant() == correlationId.ToLowerInvariant())
+ .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
+ .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
+ .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null)
+ .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null)
+ .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod)
+ .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url))
+ .WhereIf(userName != null, auditLog => auditLog.UserName == userName)
+ .WhereIf(applicationName != null, auditLog => auditLog.ApplicationName == applicationName)
+ .WhereIf(correlationId != null, auditLog => auditLog.CorrelationId == correlationId)
.WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == (int?)httpStatusCode)
.WhereIf(maxDuration != null && maxDuration > 0, auditLog => auditLog.ExecutionDuration <= maxDuration)
.WhereIf(minDuration != null && minDuration > 0, auditLog => auditLog.ExecutionDuration >= minDuration);
diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj
index 32ee40e070..f55f447489 100644
--- a/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj
+++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests/Volo.Abp.AuditLogging.EntityFrameworkCore.Tests.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -13,9 +13,9 @@
-
-
-
+
+
+
diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj
index 9c831556a4..7126bf3cef 100644
--- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj
+++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.csproj
index 7d817c4f6d..e7d0174cc9 100644
--- a/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.csproj
+++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.TestBase/Volo.Abp.AuditLogging.TestBase.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -14,7 +14,7 @@
-
+
diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.csproj
index 31c5d2886c..7dadd76798 100644
--- a/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.csproj
+++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.Tests/Volo.Abp.AuditLogging.Tests.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -12,7 +12,7 @@
-
+
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/DemoAppHangfireModule.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/DemoAppHangfireModule.cs
index 27809f3d5c..1afe3f594c 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/DemoAppHangfireModule.cs
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/DemoAppHangfireModule.cs
@@ -29,10 +29,11 @@ namespace Volo.Abp.BackgroundJobs.DemoApp.HangFire
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
- context
- .ServiceProvider
- .GetRequiredService()
- .AddConsole(LogLevel.Debug);
+ //TODO: Configure console logging
+ //context
+ // .ServiceProvider
+ // .GetRequiredService()
+ // .AddConsole(LogLevel.Debug);
}
}
}
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj
index c629101316..0eba9eeec3 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/Volo.Abp.BackgroundJobs.DemoApp.HangFire.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp2.2
+ netcoreapp3.0
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/DemoAppRabbitMqModule.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/DemoAppRabbitMqModule.cs
index 6b1071716b..416bb29a96 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/DemoAppRabbitMqModule.cs
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/DemoAppRabbitMqModule.cs
@@ -16,10 +16,11 @@ namespace Volo.Abp.BackgroundJobs.DemoApp.RabbitMq
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
- context
- .ServiceProvider
- .GetRequiredService()
- .AddConsole(LogLevel.Debug);
+ //TODO: Configure console logging
+ //context
+ // .ServiceProvider
+ // .GetRequiredService()
+ // .AddConsole(LogLevel.Debug);
}
}
}
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.csproj
index 46b7ff0ce5..00d239bef2 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.csproj
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq/Volo.Abp.BackgroundJobs.DemoApp.RabbitMq.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp2.2
+ netcoreapp3.0
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj
index 1d7fc9fe56..a2a5f008d9 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Volo.Abp.BackgroundJobs.DemoApp.Shared.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/DemoAppModule.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/DemoAppModule.cs
index 69cfb2aa6f..cb9b532525 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/DemoAppModule.cs
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/DemoAppModule.cs
@@ -38,10 +38,11 @@ namespace Volo.Abp.BackgroundJobs.DemoApp
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
- context
- .ServiceProvider
- .GetRequiredService()
- .AddConsole(LogLevel.Debug);
+ //TODO: Configure console logging
+ //context
+ // .ServiceProvider
+ // .GetRequiredService()
+ // .AddConsole(LogLevel.Debug);
}
}
}
diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj
index 3540aa8e9c..72dc208dc2 100644
--- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj
+++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/Volo.Abp.BackgroundJobs.DemoApp.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp2.2
+ netcoreapp3.0
@@ -11,8 +11,8 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs
index c3684d9cfe..76106ea468 100644
--- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs
+++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs
@@ -48,7 +48,13 @@ namespace Volo.Abp.BackgroundJobs
///
public virtual BackgroundJobPriority Priority { get; set; }
- public BackgroundJobRecord()
+ private BackgroundJobRecord()
+ {
+
+ }
+
+ public BackgroundJobRecord(Guid id)
+ : base(id)
{
}
diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs
index a20a01392b..ebf98bbe70 100644
--- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs
+++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobsDomainAutoMapperProfile.cs
@@ -8,9 +8,11 @@ namespace Volo.Abp.BackgroundJobs
public BackgroundJobsDomainAutoMapperProfile()
{
CreateMap()
+ .ConstructUsing(x => new BackgroundJobRecord(x.Id))
.Ignore(record => record.ConcurrencyStamp)
- .Ignore(record => record.ExtraProperties)
- .ReverseMap();
+ .Ignore(record => record.ExtraProperties);
+
+ CreateMap();
}
}
}
diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.csproj b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.csproj
index 1b3ed12524..eb92972675 100644
--- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.csproj
+++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo.Abp.BackgroundJobs.EntityFrameworkCore.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netstandard2.1
diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj
index 66ef602232..7932f919e1 100644
--- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj
+++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo.Abp.BackgroundJobs.Domain.Tests.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -12,7 +12,7 @@
-
+
diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo/Abp/BackgroundJobs/BackgroundJobStore_Tests.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo/Abp/BackgroundJobs/BackgroundJobStore_Tests.cs
new file mode 100644
index 0000000000..caa9a3c445
--- /dev/null
+++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.Domain.Tests/Volo/Abp/BackgroundJobs/BackgroundJobStore_Tests.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Threading.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.BackgroundJobs
+{
+ public class BackgroundJobStore_Tests : BackgroundJobsDomainTestBase
+ {
+ private readonly IBackgroundJobStore _backgroundJobStore;
+
+ public BackgroundJobStore_Tests()
+ {
+ _backgroundJobStore = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task InsertAsync()
+ {
+ var jobInfo = new BackgroundJobInfo
+ {
+ Id = Guid.NewGuid(),
+ JobArgs = "args1",
+ JobName = "name1"
+ };
+
+ await _backgroundJobStore.InsertAsync(
+ jobInfo
+ );
+
+ var jobInfo2 = await _backgroundJobStore.FindAsync(jobInfo.Id);
+ jobInfo2.ShouldNotBeNull();
+ jobInfo2.Id.ShouldBe(jobInfo.Id);
+ jobInfo2.JobArgs.ShouldBe(jobInfo.JobArgs);
+ jobInfo2.JobName.ShouldBe(jobInfo.JobName);
+ }
+ }
+}
diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj
index 7fd7558b02..433301a189 100644
--- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj
+++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests/Volo.Abp.BackgroundJobs.EntityFrameworkCore.Tests.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -13,10 +13,10 @@
-
-
-
-
+
+
+
+
diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj
index e999356678..468c1f0665 100644
--- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj
+++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -13,7 +13,7 @@
-
+
diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj
index ce6e3b7c1b..d6dbe4bb8e 100644
--- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj
+++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo.Abp.BackgroundJobs.TestBase.csproj
@@ -3,7 +3,7 @@
- netcoreapp2.2
+ netcoreapp3.0
@@ -14,7 +14,7 @@
-
+
diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs
index 347db003a2..dd74854a9c 100644
--- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs
+++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs
@@ -23,9 +23,8 @@ namespace Volo.Abp.BackgroundJobs
public void Build()
{
_backgroundJobRepository.Insert(
- new BackgroundJobRecord
+ new BackgroundJobRecord(_testData.JobId1)
{
- Id = _testData.JobId1,
JobName = "TestJobName",
JobArgs = "{ value: 1 }",
NextTryTime = _clock.Now.Subtract(TimeSpan.FromMinutes(1)),
@@ -38,9 +37,8 @@ namespace Volo.Abp.BackgroundJobs
);
_backgroundJobRepository.Insert(
- new BackgroundJobRecord
+ new BackgroundJobRecord(_testData.JobId2)
{
- Id = _testData.JobId2,
JobName = "TestJobName",
JobArgs = "{ value: 2 }",
NextTryTime = _clock.Now.AddMinutes(42),
@@ -53,9 +51,8 @@ namespace Volo.Abp.BackgroundJobs
);
_backgroundJobRepository.Insert(
- new BackgroundJobRecord
+ new BackgroundJobRecord(_testData.JobId3)
{
- Id = _testData.JobId3,
JobName = "TestJobName",
JobArgs = "{ value: 3 }",
NextTryTime = _clock.Now,
diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj
index e658a6a7ec..27fa209d2c 100644
--- a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj
+++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj
@@ -1,13 +1,9 @@
- netstandard2.0
+ netstandard2.1
-
-
-
-
diff --git a/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj b/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj
index 1192eda1c2..0f21d360e4 100644
--- a/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj
+++ b/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.2
+ netstandard2.0
diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs
index c42ec7eedc..7a7ecc9046 100644
--- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs
+++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs
@@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.Swagger;
using Volo.Abp;
@@ -144,26 +145,19 @@ namespace Volo.BloggingTestApp
app.UseVirtualFiles();
- app.UseSwagger();
- app.UseSwaggerUI(options =>
- {
- options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API");
- });
+ app.UseRouting();
+
+ //app.UseSwagger();
+ //app.UseSwaggerUI(options =>
+ //{
+ // options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API");
+ //});
app.UseAuthentication();
app.UseRequestLocalization(app.ApplicationServices.GetRequiredService>().Value);
- app.UseMvc(routes =>
- {
- routes.MapRoute(
- name: "defaultWithArea",
- template: "{area}/{controller=Home}/{action=Index}/{id?}");
-
- routes.MapRoute(
- name: "default",
- template: "{controller=Home}/{action=Index}/{id?}");
- });
+ app.UseMvcWithDefaultRouteAndArea();
using (var scope = context.ServiceProvider.CreateScope())
diff --git a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj
index deffaccf44..a0df8b49dc 100644
--- a/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj
+++ b/modules/blogging/app/Volo.BloggingTestApp/Volo.BloggingTestApp.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.2
+ netcoreapp3.0InProcess
@@ -13,11 +13,6 @@
-
-
-
-
-
diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pt-BR.json b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pt-BR.json
index a3a4b1fa39..364e0303e5 100644
--- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pt-BR.json
+++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Localization/Resources/Blogging/ApplicationContracts/pt-BR.json
@@ -6,7 +6,7 @@
"Permission:Posts": "Postagens",
"Permission:Tags": "Etiquetas",
"Permission:Comments": "Comentários",
- "Permission:Management": "Gerencimento",
+ "Permission:Management": "Gerenciamento",
"Permission:Edit": "Editar",
"Permission:Create": "Criar",
"Permission:Delete": "Excluir"
diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj
index c5a4990831..e466b4dc99 100644
--- a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj
+++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj
@@ -11,9 +11,6 @@
-
-
-
diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.csproj b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.csproj
index 77f25274f0..122385c76f 100644
--- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.csproj
+++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo.Blogging.EntityFrameworkCore.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netstandard2.1Volo.Blogging.EntityFrameworkCoreVolo.Blogging.EntityFrameworkCore
diff --git a/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo.Blogging.HttpApi.Client.csproj b/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo.Blogging.HttpApi.Client.csproj
index a736b41226..550d58bcec 100644
--- a/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo.Blogging.HttpApi.Client.csproj
+++ b/modules/blogging/src/Volo.Blogging.HttpApi.Client/Volo.Blogging.HttpApi.Client.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netcoreapp3.0Volo.Blogging.HttpApi.ClientVolo.Blogging.HttpApi.Client
diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.csproj b/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.csproj
index b9c9f3933b..db90344d09 100644
--- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.csproj
+++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo.Blogging.HttpApi.csproj
@@ -3,7 +3,7 @@
- netstandard2.0
+ netcoreapp3.0Volo.Blogging.HttpApiVolo.Blogging.HttpApi
diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
index e74ff987ea..4c945e8aac 100644
--- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
+++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/Detail.cshtml
@@ -23,302 +23,297 @@
}
-
+
\n \n \n \n \n \n \n \n \n\n"}]}],"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@ngxs/store","name":"Store","line":14,"character":29},{"__symbolic":"reference","module":"@abp/ng.theme.shared","name":"ToasterService","line":14,"character":60},{"__symbolic":"reference","name":"ɵf"}]}],"ngOnInit":[{"__symbolic":"method"}],"onSwitch":[{"__symbolic":"method"}],"save":[{"__symbolic":"method"}]}},"ɵh":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":15,"character":1},"arguments":[{"imports":[{"__symbolic":"call","expression":{"__symbolic":"select","expression":{"__symbolic":"reference","module":"@angular/router","name":"RouterModule","line":16,"character":12},"member":"forChild"},"arguments":[[{"path":"","pathMatch":"full","redirectTo":"login"},{"path":"","component":{"__symbolic":"reference","module":"@abp/ng.core","name":"DynamicLayoutComponent","line":10,"character":15},"children":[{"path":"login","component":{"__symbolic":"reference","name":"ɵc"}},{"path":"register","component":{"__symbolic":"reference","name":"ɵe"}}]}]]}],"exports":[{"__symbolic":"reference","module":"@angular/router","name":"RouterModule","line":17,"character":12}]}]}],"members":{}}},"origins":{"RootAccountModule":"./lib/root-account.module","AccountModule":"./lib/account.module","ACCOUNT_ROUTES":"./lib/constants/routes","ɵa":"./lib/tokens/options.token","ɵb":"./lib/tokens/options.token","ɵc":"./lib/components/login/login.component","ɵd":"./lib/models/options","ɵe":"./lib/components/register/register.component","ɵf":"./lib/services/account.service","ɵg":"./lib/components/tenant-box/tenant-box.component","ɵh":"./lib/account-routing.module"},"importAs":"@abp/ng.account"}
\ No newline at end of file
+{"__symbolic":"module","version":4,"exports":[{"from":"./lib/options"},{"from":"./lib/user"},{"from":"./lib/tenant"}],"metadata":{"AccountModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule","line":13,"character":1},"arguments":[{"declarations":[{"__symbolic":"reference","name":"ɵa"},{"__symbolic":"reference","name":"ɵc"},{"__symbolic":"reference","name":"ɵe"}],"imports":[{"__symbolic":"reference","module":"@abp/ng.core","name":"CoreModule","line":15,"character":12},{"__symbolic":"reference","name":"ɵf"},{"__symbolic":"reference","module":"@abp/ng.theme.shared","name":"ThemeSharedModule","line":15,"character":46},{"__symbolic":"reference","module":"primeng/table","name":"TableModule","line":15,"character":65},{"__symbolic":"reference","module":"@ng-bootstrap/ng-bootstrap","name":"NgbDropdownModule","line":15,"character":78},{"__symbolic":"reference","module":"@ngx-validate/core","name":"NgxValidateCoreModule","line":15,"character":97}],"exports":[]}]}],"members":{}},"AccountProviders":{"__symbolic":"function","parameters":["options"],"defaults":[{}],"value":[{"provide":{"__symbolic":"reference","name":"ɵh"},"useValue":{"__symbolic":"reference","name":"options"}},{"provide":"ACCOUNT_OPTIONS","useFactory":{"__symbolic":"reference","name":"ɵg"},"deps":[{"__symbolic":"reference","name":"ɵh"}]}]},"ACCOUNT_ROUTES":{"routes":[{"name":"Account","path":"account","invisible":true,"layout":{"__symbolic":"select","expression":{"__symbolic":"reference","module":"@abp/ng.core","name":"eLayoutType","line":8,"character":14},"member":"application"},"children":[{"path":"login","name":"Login","order":1},{"path":"register","name":"Register","order":2}]}]},"ɵa":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Component","line":14,"character":1},"arguments":[{"selector":"abp-login","template":"