Browse Source

Merge pull request #13 from abpframework/master

merge
pull/985/head
Marcelo Mohr Maciel 8 years ago
committed by GitHub
parent
commit
fb30dde7a2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      abp_io/src/Volo.AbpWebSite.Web/AbpWebSiteWebModule.cs
  2. 2
      abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Components/Header/Default.cshtml
  3. 4
      abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/HomePageLayout.cshtml
  4. 4
      abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Layout.cshtml
  5. 4
      abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/LayoutEmpty.cshtml
  6. 4
      abp_io/src/Volo.AbpWebSite.Web/Pages/Templates.cshtml
  7. 1
      abp_io/src/Volo.AbpWebSite.Web/Templates/MvcApplicationTemplate.cs
  8. 20
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildContextExtensions.cs
  9. 17
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildPipelineStep.cs
  10. 39
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/NugetReferenceReplaceStep.cs
  11. 2
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/RemoveProjectFromSolutionStep.cs
  12. 8
      abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs
  13. 2
      build-all.ps1
  14. 2
      common.props
  15. 2
      docs/en/Contribution/Index.md
  16. 2
      docs/en/Dependency-Injection.md
  17. 10
      docs/en/Getting-Started-AspNetCore-MVC-Template.md
  18. 14
      docs/en/Multi-Tenancy.md
  19. 26
      docs/en/Nightly-Builds.md
  20. 26
      docs/en/Samples/Microservice-Demo.md
  21. 6
      docs/en/Tutorials/AspNetCore-Mvc/Part-I.md
  22. 2
      docs/en/Tutorials/AspNetCore-Mvc/Part-III.md
  23. BIN
      docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png
  24. BIN
      docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png
  25. 4
      docs/en/docs-nav.json
  26. BIN
      docs/en/images/bookstore-visual-studio-solution-v2.png
  27. BIN
      docs/en/images/microservice-sample-update-database-authserver.png
  28. BIN
      docs/en/images/microservice-sample-update-database-products.png
  29. BIN
      docs/en/images/night-build-add-nuget-package.png
  30. BIN
      docs/en/images/night-build-add-nuget-source.png
  31. BIN
      docs/en/images/pcm-update-database-v2.png
  32. 54
      docs/zh-Hans/Blog-Posts/2019-02-22/Post.md
  33. BIN
      docs/zh-Hans/Blog-Posts/2019-02-22/scott-and-jon.png
  34. 20
      docs/zh-Hans/Getting-Started-AspNetCore-Application.md
  35. 10
      docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md
  36. 14
      docs/zh-Hans/Multi-Tenancy.md
  37. 25
      docs/zh-Hans/Nightly-Builds.md
  38. 1433
      docs/zh-Hans/Samples/Microservice-Demo.md
  39. 6
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md
  40. 1
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md
  41. BIN
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-pmc-add-book-migration-v2.png
  42. BIN
      docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png
  43. 4
      docs/zh-Hans/docs-nav.json
  44. BIN
      docs/zh-Hans/images/bookstore-visual-studio-solution-v2.png
  45. BIN
      docs/zh-Hans/images/microservice-sample-authserver-home.png
  46. BIN
      docs/zh-Hans/images/microservice-sample-authserver-login.png
  47. BIN
      docs/zh-Hans/images/microservice-sample-backend-ui-permissions.png
  48. BIN
      docs/zh-Hans/images/microservice-sample-backend-ui.png
  49. BIN
      docs/zh-Hans/images/microservice-sample-blogservice-permission-in-database.png
  50. BIN
      docs/zh-Hans/images/microservice-sample-diagram-2.png
  51. BIN
      docs/zh-Hans/images/microservice-sample-kibana-1.png
  52. BIN
      docs/zh-Hans/images/microservice-sample-kibana-2.png
  53. BIN
      docs/zh-Hans/images/microservice-sample-product-module-in-solution.png
  54. BIN
      docs/zh-Hans/images/microservice-sample-public-product-list.png
  55. BIN
      docs/zh-Hans/images/microservice-sample-solution.png
  56. BIN
      docs/zh-Hans/images/night-build-add-nuget-package.png
  57. BIN
      docs/zh-Hans/images/night-build-add-nuget-source.png
  58. BIN
      docs/zh-Hans/images/pcm-update-database-v2.png
  59. 28
      framework/Volo.Abp.sln
  60. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj
  61. 2
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs
  62. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs
  63. 16
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs
  64. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs
  65. 39
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs
  66. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributerBase.cs
  67. 51
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
  68. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs
  69. 4
      framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs
  70. 22
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs
  71. 23
      framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs
  72. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs
  73. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs
  74. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs
  75. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs
  76. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/tenant-switch.js
  77. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj
  78. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/AbpAspNetCoreMvcUiMultiTenancyModule.cs
  79. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml
  80. 51
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/TenantSwitchViewComponent.cs
  81. 8
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json
  82. 6
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json
  83. 21
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/MultiTenancyToolbarContributor.cs
  84. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/AbpAspNetCoreMvcUIBasicThemeModule.cs
  85. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/Default.cshtml
  86. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/_MenuItem.cshtml
  87. 34
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml
  88. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml
  89. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml
  90. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj
  91. 3
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs
  92. 17
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
  93. 0
      framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Layout/IPageLayout.cs
  94. 15
      framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Http/AbpFormFileExtensions.cs
  95. 8
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs
  96. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs
  97. 39
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  98. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs
  99. 42
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeatureActionFilter.cs
  100. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs

17
abp_io/src/Volo.AbpWebSite.Web/AbpWebSiteWebModule.cs

@ -1,5 +1,4 @@
using System.IO; using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -14,7 +13,6 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theming; using Volo.Abp.AspNetCore.Mvc.UI.Theming;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
@ -69,7 +67,6 @@ namespace Volo.AbpWebSite
Configure<BlogFileOptions>(options => Configure<BlogFileOptions>(options =>
{ {
options.FileUploadLocalFolder = Path.Combine(hostingEnvironment.WebRootPath, "files"); options.FileUploadLocalFolder = Path.Combine(hostingEnvironment.WebRootPath, "files");
options.FileUploadUrlRoot = "/files/";
}); });
} }
@ -183,18 +180,8 @@ namespace Volo.AbpWebSite
AsyncHelper.RunSync(async () => AsyncHelper.RunSync(async () =>
{ {
await scope.ServiceProvider await scope.ServiceProvider
.GetRequiredService<IIdentityDataSeeder>() .GetRequiredService<IDataSeeder>()
.SeedAsync( .SeedAsync();
"1q2w3E*"
);
await scope.ServiceProvider
.GetRequiredService<IPermissionDataSeeder>()
.SeedAsync(
RolePermissionValueProvider.ProviderName,
"admin",
IdentityPermissions.GetAll().Union(BloggingPermissions.GetAll())
);
}); });
} }
} }

2
abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Components/Header/Default.cshtml

@ -23,7 +23,7 @@
<a class="nav-link" href="/blog/abp/">Blog</a> <a class="nav-link" href="/blog/abp/">Blog</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="https://github.com/abpframework/abp/" target="_blank">Github</a> <a class="nav-link" href="https://github.com/abpframework/abp/" target="_blank">GitHub</a>
</li> </li>
<li class="for-mobile"> <li class="for-mobile">
<button type="button" class="close close-mmenu" aria-label="Close"> <button type="button" class="close close-mmenu" aria-label="Close">

4
abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/HomePageLayout.cshtml

@ -17,7 +17,7 @@
<title>@(ViewBag.Title == null ? "abp.io" : ViewBag.Title)</title> <title>@(ViewBag.Title == null ? "abp.io" : ViewBag.Title)</title>
@await Component.InvokeAsync(typeof(StandardMetaViewComponent)) @await Component.InvokeAsync(typeof(StandardMetaViewComponent))
<abp-style-bundle name="@AbpIoBundles.Styles.Global" /> <abp-style-bundle name="@AbpIoBundles.Styles.Global" />
@RenderSection("styles", false) @await RenderSectionAsync("styles", false)
</head> </head>
<body> <body>
@ -47,7 +47,7 @@
gtag('config', 'UA-49982725-4'); gtag('config', 'UA-49982725-4');
</script> </script>
@RenderSection("scripts", false) @await RenderSectionAsync("scripts", false)
</body> </body>
</html> </html>

4
abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/Layout.cshtml

@ -17,7 +17,7 @@
<title>@(ViewBag.Title == null ? "abp.io" : ViewBag.Title)</title> <title>@(ViewBag.Title == null ? "abp.io" : ViewBag.Title)</title>
@await Component.InvokeAsync(typeof(StandardMetaViewComponent)) @await Component.InvokeAsync(typeof(StandardMetaViewComponent))
<abp-style-bundle name="@AbpIoBundles.Styles.Global" /> <abp-style-bundle name="@AbpIoBundles.Styles.Global" />
@RenderSection("styles", false) @await RenderSectionAsync("styles", false)
</head> </head>
<body> <body>
@ -58,7 +58,7 @@
gtag('config', 'UA-49982725-4'); gtag('config', 'UA-49982725-4');
</script> </script>
@RenderSection("scripts", false) @await RenderSectionAsync("scripts", false)
</body> </body>
</html> </html>

4
abp_io/src/Volo.AbpWebSite.Web/Pages/Shared/LayoutEmpty.cshtml

@ -18,7 +18,7 @@
<title>@(ViewBag.Title == null ? "abp.io" : ViewBag.Title)</title> <title>@(ViewBag.Title == null ? "abp.io" : ViewBag.Title)</title>
@await Component.InvokeAsync(typeof(StandardMetaViewComponent)) @await Component.InvokeAsync(typeof(StandardMetaViewComponent))
<abp-style-bundle name="@StandardBundles.Styles.Global" /> <abp-style-bundle name="@StandardBundles.Styles.Global" />
@RenderSection("styles", false) @await RenderSectionAsync("styles", false)
</head> </head>
<body class="abp-empty-layout"> <body class="abp-empty-layout">
@ -41,7 +41,7 @@
gtag('config', 'UA-49982725-4'); gtag('config', 'UA-49982725-4');
</script> </script>
@RenderSection("scripts", false) @await RenderSectionAsync("scripts", false)
</body> </body>
</html> </html>

4
abp_io/src/Volo.AbpWebSite.Web/Pages/Templates.cshtml

@ -14,7 +14,7 @@
@using (Html.BeginForm(FormMethod.Post)) @using (Html.BeginForm(FormMethod.Post))
{ {
<div class="row border"> <div class="row border">
<div class="col p-5 "> <div class="col-lg-7 p-5 ">
<h2> <h2>
<span class="text-primary">Create</span> <span class="text-primary">Create</span>
<span class="text-success">New Project</span> <span class="text-success">New Project</span>
@ -64,7 +64,7 @@
</div> </div>
</div> </div>
<div class="col-md-5 bg-light p-5"> <div class="col-lg-5 bg-light p-5">
<h4>The Startup Project</h4> <h4>The Startup Project</h4>
<p>See <a href="/documents/abp/latest/Getting-Started-AspNetCore-MVC-Template" target="_blank">the documentation</a> to understand how to run the downloaded project.</p> <p>See <a href="/documents/abp/latest/Getting-Started-AspNetCore-MVC-Template" target="_blank">the documentation</a> to understand how to run the downloaded project.</p>

1
abp_io/src/Volo.AbpWebSite.Web/Templates/MvcApplicationTemplate.cs

@ -37,6 +37,7 @@ namespace Volo.AbpWebSite.Templates
if (context.Request.DatabaseProvider != DatabaseProvider.EntityFrameworkCore) if (context.Request.DatabaseProvider != DatabaseProvider.EntityFrameworkCore)
{ {
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Application.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Application.Tests")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Application.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Application.Tests"));
steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Web.Tests")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Tests", projectFolderPath: "test/MyCompanyName.MyProjectName.Web.Tests"));
} }

20
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildContextExtensions.cs

@ -0,0 +1,20 @@
using System;
using System.Linq;
using Volo.Utils.SolutionTemplating.Files;
namespace Volo.Utils.SolutionTemplating.Building
{
public static class ProjectBuildContextExtensions
{
public static FileEntry GetFile(this ProjectBuildContext context, string filePath)
{
var file = context.Files.FirstOrDefault(f => f.Name == filePath);
if (file == null)
{
throw new ApplicationException("Could not find file: " + filePath);
}
return file;
}
}
}

17
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/ProjectBuildPipelineStep.cs

@ -1,22 +1,7 @@
using System; namespace Volo.Utils.SolutionTemplating.Building
using System.Linq;
using Volo.Utils.SolutionTemplating.Files;
namespace Volo.Utils.SolutionTemplating.Building
{ {
public abstract class ProjectBuildPipelineStep public abstract class ProjectBuildPipelineStep
{ {
public abstract void Execute(ProjectBuildContext context); public abstract void Execute(ProjectBuildContext context);
protected FileEntry GetFile(ProjectBuildContext context, string filePath)
{
var file = context.Files.FirstOrDefault(f => f.Name == filePath);
if (file == null)
{
throw new ApplicationException("Could not find file: " + filePath);
}
return file;
}
} }
} }

39
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/NugetReferenceReplaceStep.cs

@ -16,7 +16,8 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
new NugetReferenceReplacer( new NugetReferenceReplacer(
context.Files, context.Files,
"MyCompanyName", "MyCompanyName",
"MyProjectName" "MyProjectName",
context.Template.Version
).Run(); ).Run();
} }
@ -27,12 +28,12 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
private readonly string _projectNamePlaceHolder; private readonly string _projectNamePlaceHolder;
private readonly string _latestNugetPackageVersion; private readonly string _latestNugetPackageVersion;
public NugetReferenceReplacer(List<FileEntry> entries, string companyNamePlaceHolder, string projectNamePlaceHolder) public NugetReferenceReplacer(List<FileEntry> entries, string companyNamePlaceHolder, string projectNamePlaceHolder, string latestNugetPackageVersion)
{ {
_entries = entries; _entries = entries;
_companyNamePlaceHolder = companyNamePlaceHolder; _companyNamePlaceHolder = companyNamePlaceHolder;
_projectNamePlaceHolder = projectNamePlaceHolder; _projectNamePlaceHolder = projectNamePlaceHolder;
_latestNugetPackageVersion = GetLatestNugetPackageVersion(); _latestNugetPackageVersion = latestNugetPackageVersion;
} }
public void Run() public void Run()
@ -110,38 +111,6 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
stream.Position = 0; stream.Position = 0;
return stream; return stream;
} }
private string GetLatestNugetPackageVersion()
{
//TODO: This should get it from the related release! Not always from the master!
var commonPropsUrl = "https://raw.githubusercontent.com/abpframework/abp/master/common.props";
var content = "";
using (var webClient = new WebClient())
{
try
{
content = webClient.DownloadString(commonPropsUrl);
}
catch (Exception)
{
throw new Exception("The Common.pros doesn't exist on github or removed to anywhere else.");
}
}
var doc = new HtmlDocument();
doc.Load(GenerateStreamFromString(content));
try
{
return doc.DocumentNode.SelectNodes("//version").FirstOrDefault().InnerHtml.Trim();
}
catch (Exception e)
{
return "";
}
}
} }
} }
} }

2
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/RemoveProjectFromSolutionStep.cs

@ -23,7 +23,7 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
public override void Execute(ProjectBuildContext context) public override void Execute(ProjectBuildContext context)
{ {
context.Files.RemoveAll(file => file.Name.StartsWith(_projectFolderPath)); context.Files.RemoveAll(file => file.Name.StartsWith(_projectFolderPath));
var solutionFile = GetFile(context, _solutionFilePath); var solutionFile = context.GetFile(_solutionFilePath);
solutionFile.NormalizeLineEndings(); solutionFile.NormalizeLineEndings();
solutionFile.SetLines(RemoveProject(solutionFile.GetLines().ToList())); solutionFile.SetLines(RemoveProject(solutionFile.GetLines().ToList()));
} }

8
abp_io/src/Volo.Utils.SolutionTemplating/Volo/Utils/SolutionTemplating/Building/Steps/SwitchEntityFrameworkCoreToMongoDbStep.cs

@ -14,7 +14,7 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
private void ChangeProjectReference(ProjectBuildContext context) private void ChangeProjectReference(ProjectBuildContext context)
{ {
var file = GetFile(context, "/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj"); var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj");
file.NormalizeLineEndings(); file.NormalizeLineEndings();
@ -29,12 +29,12 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
} }
} }
throw new ApplicationException("Could not find the 'Default' connection string in appsettings.json file!"); throw new ApplicationException("Could not find the EntityFrameworkCore reference in the MyCompanyName.MyProjectName.Web.csproj!");
} }
private void ChangeWebModuleUsage(ProjectBuildContext context) private void ChangeWebModuleUsage(ProjectBuildContext context)
{ {
var file = GetFile(context, "/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs"); var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs");
file.NormalizeLineEndings(); file.NormalizeLineEndings();
@ -59,7 +59,7 @@ namespace Volo.Utils.SolutionTemplating.Building.Steps
private void ChangeConnectionString(ProjectBuildContext context) private void ChangeConnectionString(ProjectBuildContext context)
{ {
var file = GetFile(context, "/src/MyCompanyName.MyProjectName.Web/appsettings.json"); var file = context.GetFile("/src/MyCompanyName.MyProjectName.Web/appsettings.json");
file.NormalizeLineEndings(); file.NormalizeLineEndings();

2
build-all.ps1

@ -9,6 +9,7 @@ $solutionPaths = (
"modules/users", "modules/users",
"modules/permission-management", "modules/permission-management",
"modules/setting-management", "modules/setting-management",
"modules/feature-management",
"modules/identity", "modules/identity",
"modules/identityserver", "modules/identityserver",
"modules/tenant-management", "modules/tenant-management",
@ -17,6 +18,7 @@ $solutionPaths = (
"modules/blogging", "modules/blogging",
"modules/audit-logging", "modules/audit-logging",
"modules/background-jobs", "modules/background-jobs",
"modules/client-simulation",
"abp_io", "abp_io",
"templates/module", "templates/module",
"templates/service", "templates/service",

2
common.props

@ -1,7 +1,7 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<Version>0.14.0</Version> <Version>0.15.0</Version>
<NoWarn>$(NoWarn);CS1591</NoWarn> <NoWarn>$(NoWarn);CS1591</NoWarn>
<PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl> <PackageIconUrl>https://abp.io/assets/abp_nupkg.png</PackageIconUrl>
<PackageProjectUrl>https://abp.io</PackageProjectUrl> <PackageProjectUrl>https://abp.io</PackageProjectUrl>

2
docs/en/Contribution/Index.md

@ -49,4 +49,4 @@ If you decide to create some tutorials or blog posts on ABP, please inform us (b
### Bug Report ### Bug Report
If you find any bug, please [create an issue on the Github repository](https://github.com/abpframework/abp/issues/new). If you find any bug, please [create an issue on the Github repository](https://github.com/abpframework/abp/issues/new).

2
docs/en/Dependency-Injection.md

@ -170,7 +170,7 @@ public class BlogModule : AbpModule
There are three common ways of using a service that has already been registered. There are three common ways of using a service that has already been registered.
### Contructor Injection ### Constructor Injection
This is the most common way of injecting a service into a class. For example: This is the most common way of injecting a service into a class. For example:

10
docs/en/Getting-Started-AspNetCore-MVC-Template.md

@ -19,9 +19,9 @@ The downloaded project requires;
### The Solution Structure ### The Solution Structure
Extract the zip file downloaded and open in **Visual Studio 2017 (15.7.0+)**: Extract the zip file downloaded and open in **Visual Studio 2017 (15.9.0+)**:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png) ![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
The solution has a layered structure (based on Domain Driven Design) where; The solution has a layered structure (based on Domain Driven Design) where;
@ -30,6 +30,8 @@ The solution has a layered structure (based on Domain Driven Design) where;
* ``.Web`` is the presentation layer. * ``.Web`` is the presentation layer.
* ``.EntityFrameworkCore`` is the EF Core integration package. * ``.EntityFrameworkCore`` is the EF Core integration package.
EF Core database migrations are separated to a project named `.EntityFrameworkCore.DbMigrations`.
The solution also contains unit & integration test projects properly configured to work with **EF Core** & **SQLite in-memory** database. The solution also contains unit & integration test projects properly configured to work with **EF Core** & **SQLite in-memory** database.
### Creating the Database ### Creating the Database
@ -50,9 +52,9 @@ Right click to the `.Web` project and select **Set as StartUp Project**:
![set-as-startup-project](images/set-as-startup-project.png) ![set-as-startup-project](images/set-as-startup-project.png)
Open the **Package Manager Console**, select `.EntityFrameworkCore` project as the **Default Project** and run the `Update-Database` command: Open the **Package Manager Console**, select `.EntityFrameworkCore.DbMigrations` project as the **Default Project** and run the `Update-Database` command:
![pcm-update-database](images/pcm-update-database.png) ![pcm-update-database](images/pcm-update-database-v2.png)
This will create a new database based on the configured connection string. This will create a new database based on the configured connection string.

14
docs/en/Multi-Tenancy.md

@ -6,17 +6,17 @@ Wikipedia [defines](https://en.wikipedia.org/wiki/Multitenancy) multi-tenancy as
> Software **Multi-tenancy** refers to a software **architecture** in which a **single instance** of a software runs on a server and serves **multiple tenants**. A tenant is a group of users who share a common access with specific privileges to the software instance. With a multitenant architecture, a software application is designed to provide every tenant a **dedicated share of the instance including its data**, configuration, user management, tenant individual functionality and non-functional properties. Multi-tenancy contrasts with multi-instance architectures, where separate software instances operate on behalf of different tenants. > Software **Multi-tenancy** refers to a software **architecture** in which a **single instance** of a software runs on a server and serves **multiple tenants**. A tenant is a group of users who share a common access with specific privileges to the software instance. With a multitenant architecture, a software application is designed to provide every tenant a **dedicated share of the instance including its data**, configuration, user management, tenant individual functionality and non-functional properties. Multi-tenancy contrasts with multi-instance architectures, where separate software instances operate on behalf of different tenants.
### Volo.Abp.MultiTenancy.Abstractions Package ### Volo.Abp.MultiTenancy Package
Volo.Abp.MultiTenancy.Abstractions package defines fundamental interfaces to make your code "multi-tenancy ready". So, install it to your project using the package manager console (PMC): Volo.Abp.MultiTenancy package defines fundamental interfaces to make your code "multi-tenancy ready". So, install it to your project using the package manager console (PMC):
```` ````
Install-Package Volo.Abp.MultiTenancy.Abstractions Install-Package Volo.Abp.MultiTenancy
```` ````
> This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually. > This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually.
Then you can add **AbpMultiTenancyAbstractionsModule** dependency to your module: Then you can add **AbpMultiTenancyModule** dependency to your module:
````C# ````C#
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -24,7 +24,7 @@ using Volo.Abp.MultiTenancy;
namespace MyCompany.MyProject namespace MyCompany.MyProject
{ {
[DependsOn(typeof(AbpMultiTenancyAbstractionsModule))] [DependsOn(typeof(AbpMultiTenancyModule))]
public class MyModule : AbpModule public class MyModule : AbpModule
{ {
//... //...
@ -98,7 +98,7 @@ Volo.Abp.MultiTenancy is the actual package that makes your application multi-te
Install-Package Volo.Abp.MultiTenancy Install-Package Volo.Abp.MultiTenancy
```` ````
Then you can add **AbpMultiTenancyAbstractionsModule** dependency to your module: Then you can add **AbpMultiTenancyModule** dependency to your module:
````C# ````C#
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -114,7 +114,7 @@ namespace MyCompany.MyProject
} }
```` ````
> If you add AbpMultiTenancyModule dependency to your module, then you don't need to add AbpMultiTenancyAbstractionsModule dependency separately since AbpMultiTenancyModule already depends on it. > If you add AbpMultiTenancyModule dependency to your module, then you don't need to add AbpMultiTenancyModule dependency separately since AbpMultiTenancyModule already depends on it.
#### Determining Current Tenant #### Determining Current Tenant

26
docs/en/Nightly-Builds.md

@ -0,0 +1,26 @@
# Nightly Builds
All framework & module packages are deployed to MyGet every night in weekdays. So, you can use or test the latest code without waiting the next release.
## Configure Visual Studio
> Requires Visual Studio 2017+
1. Go to `Tools > Options > NuGet Package Manager > Package Source`.
2. Click the green `+` icon.
3. Set `ABP Nightly` as *Name* and `https://www.myget.org/F/abp-nightly/api/v3/index.json` as the *Source* as shown below:
![night-build-add-nuget-source](images/night-build-add-nuget-source.png)
4. Click the `Update` button.
5. Click the `OK` button to save changes.
## Install Package
Now, you can install preview / nightly packages to your project from Nuget Browser or Package Manager Console.
![night-build-add-nuget-package](images/night-build-add-nuget-package.png)
1. In the nuget browser, select "Include prereleases".
2. Change package source to "All".
3. Search a package. You will see prereleases of the package formatted as `(VERSION)-preview(DATE)` (like *v0.16.0-preview20190401* in this sample).
4. You can click to the `Install` button to add package to your project.

26
docs/en/Samples/Microservice-Demo.md

@ -116,11 +116,29 @@ To be able to run the solution from source code, following tools should be insta
* Run `dotnet restore` from the command line inside the `samples\MicroserviceDemo` folder. * Run `dotnet restore` from the command line inside the `samples\MicroserviceDemo` folder.
* Build the solution in Visual Studio. * Build the solution in Visual Studio.
#### Restore Databases #### Create Databases
Open `MsDemo_Identity.zip` and `MsDemo_ProductManagement.zip` inside the `samples\MicroserviceDemo\databases` folder and restore to the SQL Server. MongoDB database is created dynamically, however you need to create database schemas for SQL server databases. The solution is configured to use Entity Core Code First migrations, so you can easily create databases.
> Notice that: These databases have EF Core migrations in the solution, however they don't have seed data, especially required for IdentityServer4 configuration. So, restoring the databases is much more easier. There are two SQL server databases in this solution.
##### MsDemo_Identity Database
* Right click to the `AuthServer.Host` project and click to the `Set as startup project`.
* Open the **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console)
* Select `AuthServer.Host` as the **Default project**.
* Run `Update-Database` command.
![microservice-sample-update-database-authserver](../images/microservice-sample-update-database-authserver.png)
##### MsDemo_ProductManagement
- Right click to the `ProductService.Host` project and click to the `Set as startup project`.
- Open the **Package Manager Console** (Tools -> Nuget Package Manager -> Package Manager Console)
- Select `ProductService.Host` as the **Default project**.
- Run `Update-Database` command.
![microservice-sample-update-database-products](../images/microservice-sample-update-database-products.png)
#### Run Projects #### Run Projects
@ -136,6 +154,8 @@ Run the projects with the following order (right click to each project, set as s
* BackendAdminApp.Host * BackendAdminApp.Host
* PublicWebSite.Host * PublicWebSite.Host
When you run projects, they will add some initial demo data to their databases.
## A Brief Overview of the Solution ## A Brief Overview of the Solution
The Visual Studio solution consists of multiple projects each have different roles in the system: The Visual Studio solution consists of multiple projects each have different roles in the system:

6
docs/en/Tutorials/AspNetCore-Mvc/Part-I.md

@ -20,7 +20,7 @@ Go to the [startup template page](https://abp.io/Templates) and download a new p
This is the how the layered solution structure looks after it's created from the startup template: This is the how the layered solution structure looks after it's created from the startup template:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png) ![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
### Create the Book Entity ### Create the Book Entity
@ -91,9 +91,9 @@ EF Core requires you to relate entities with your DbContext. The easiest way to
#### Add New Migration & Update the Database #### Add New Migration & Update the Database
The Startup template uses [EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to create and maintain the database schema. Open the **Package Manager Console (PMC)** (under the *Tools/Nuget Package Manager* menu), select the `Acme.BookStore.EntityFrameworkCore` as the **default project** and execute the following command: The Startup template uses [EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to create and maintain the database schema. Open the **Package Manager Console (PMC)** (under the *Tools/Nuget Package Manager* menu), select the `Acme.BookStore.EntityFrameworkCore.DbMigrations` as the **default project** and execute the following command:
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration.png) ![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration-v2.png)
This will create a new migration class inside the `Migrations` folder. Then execute the `Update-Database` command to update the database schema: This will create a new migration class inside the `Migrations` folder. Then execute the `Update-Database` command to update the database schema:

2
docs/en/Tutorials/AspNetCore-Mvc/Part-III.md

@ -14,8 +14,6 @@ You can download the **source code** of the application [from here](https://gith
There are two test projects in the solution: There are two test projects in the solution:
![bookstore-test-projects](images/bookstore-test-projects.png)
* `Acme.BookStore.Application.Tests` is for unit & integration tests. You can write tests for application service methods. It uses **EF Core SQLite in-memory** database. * `Acme.BookStore.Application.Tests` is for unit & integration tests. You can write tests for application service methods. It uses **EF Core SQLite in-memory** database.
* `Acme.BookStore.Web.Tests` is for full stack integration tests including the web layer. So, you can write tests for UI pages too. * `Acme.BookStore.Web.Tests` is for full stack integration tests including the web layer. So, you can write tests for UI pages too.

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
docs/en/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

4
docs/en/docs-nav.json

@ -276,6 +276,10 @@
{ {
"text": "Testing" "text": "Testing"
}, },
{
"text": "Nightly Builds",
"path": "Nightly-Builds.md"
},
{ {
"text": "Contribution Guide", "text": "Contribution Guide",
"path": "Contribution/Index.md" "path": "Contribution/Index.md"

BIN
docs/en/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/en/images/microservice-sample-update-database-authserver.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
docs/en/images/microservice-sample-update-database-products.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
docs/en/images/night-build-add-nuget-package.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/en/images/night-build-add-nuget-source.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/en/images/pcm-update-database-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

54
docs/zh-Hans/Blog-Posts/2019-02-22/Post.md

@ -0,0 +1,54 @@
# 微服务演示,项目状态和路线图
在ABP vNext上的[第一个公告](https://cn.abp.io/blog/abp/Abp-vNext-Announcement)之后,我们对代码库进行了很多改进([GitHub存储库](https://github.com/abpframework/abp)上的1100多次提交).我们已经创建了功能,示例,文档等等.在这篇文章中,我想告诉你一些新闻和项目的状态.
## 微服务演示解决方案
ABP框架的主要目标之一是提供[创建微服务解决方案的便利基础设施](https://cn.abp.io/documents/abp/latest/Microservice-Architecture).
我们一直在努力开发微服务解决方案演示.初始版本已完成并[文档化](https://cn.abp.io/documents/abp/latest/Samples/Microservice-Demo).该示例解决方案旨在演示一个简单而完整的微服务解决方案;
- 具有多个独立的,可自我部署的**微服务**.
- 多个**Web应用程序**,每个都使用不同的API网关.
- 使用[Ocelot](https://github.com/ThreeMammals/Ocelot)库开发了多个**网关** / BFF(后端为前端(Backend for Frontends)).
- 使用[IdentityServer](https://identityserver.io/)框架开发**身份验证服务**.它也是一个带有必要UI的SSO(单点登录)应用程序.
- 有**多个数据库**.一些微服务有自己的数据库,而一些服务/应用程序共享一个数据库(以演示不同的用例).
- 具有不同类型的数据库:**SQL Server**(使用**Entity Framework Core** ORM)和**MongoDB**.
- 有一个**控制台应用程序**来显示通过身份验证使用服务的最简单方法.
- 使用[Redis](https://redis.io/)进行**分布式缓存**.
- 使用[RabbitMQ](https://www.rabbitmq.com/)进行服务到服务(service-to-service)的**消息传递**.
- 使用[Docker](https://www.docker.com/)和[Kubernates](https://kubernetes.io/)**部署**并运行所有服务和应用程序.
- 使用[Elasticsearch](https://www.elastic.co/products/elasticsearch)和[Kibana](https://www.elastic.co/products/kibana)存储和可视化日志(使用[Serilog](https://serilog.net/)编写).
有关解决方案的详细说明,请参阅[其文档](https://cn.abp.io/documents/abp/latest/Samples/Microservice-Demo).
## 改进/功能
我们已经开发了许多功能,包括**分布式事件总线**(与RabbitMQ集成),**IdentityServer4集成**以及几乎所有功能的增强.我们不断重构和添加测试,以使框架更稳定和生产就绪.它正在[快速增长](https://github.com/abpframework/abp/graphs/contributors).
## 路线图
在第一个稳定版本(v1.0)之前还有很多工作要做.您可以在GitHub仓库上看到[优先的积压项目](https://github.com/abpframework/abp/issues?q=is%3Aopen+is%3Aissue+milestone%3ABacklog).
根据我们的估计,我们计划在2019年第二季度(可能在五月或六月)发布v1.0.所以,不用等待太长时间了.我们也对第一个稳定版本感到非常兴奋.
我们还将完善[文档](https://cn.abp.io/documents/abp/latest),因为它现在还远未完成.
第一个版本可能不包含SPA模板.但是,如果可能的话,我们想要准备一个简单些的.SPA框架还没有确定下来.备选有:**Angular,React和Blazor**.请将您的想法写为对此帖的评论.
## 中文网
中国有一个大型的ABP社区.他们创建了一个中文版的abp.io网站:https://cn.abp.io/. 他们一直在保持更新.感谢中国的开发人员,特别是[Liming Ma](https://github.com/maliming).
## NDC {London} 2019
很高兴作为合作伙伴参加[NDC {London}](https://ndc-london.com/)2019 .我们已经与许多开发人员讨论过当前的ASP.NET Boilerplate和ABP vNext,我们得到了很好的反馈.
我们还有机会与[Scott Hanselman](https://twitter.com/shanselman)和[Jon Galloway](https://twitter.com/jongalloway)交谈.他们参观了我们的展位,我们谈到了ABP vNext的想法.他们喜欢新的ABP框架的功能,方法和目标.在twitter上查看一些照片和评论:
![scott-and-jon](scott-and-jon.png)
## 跟上步伐
* 您可以标星并关注**GitHub**存储库:https://github.com/abpframework/abp
* 您可以关注官方**Twitter**帐户获取新闻:https://twitter.com/abpframework

BIN
docs/zh-Hans/Blog-Posts/2019-02-22/scott-and-jon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

20
docs/zh-Hans/Getting-Started-AspNetCore-Application.md

@ -156,6 +156,26 @@ services.AddApplication<AppModule>(options =>
}); });
```` ````
4. 更新 `Program.cs`代码, 不再使用`WebHost.CreateDefaultBuilder()`方法(因为它使用默认的DI容器):
````csharp
public class Program
{
public static void Main(string[] args)
{
BuildWebHostInternal(args).Run();
}
public static IWebHost BuildWebHostInternal(string[] args) =>
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
````
### 源码 ### 源码
从[此处](../samples/BasicAspNetCoreApplication)获取本教程中创建的示例项目的源代码. 从[此处](../samples/BasicAspNetCoreApplication)获取本教程中创建的示例项目的源代码.

10
docs/zh-Hans/Getting-Started-AspNetCore-MVC-Template.md

@ -12,14 +12,14 @@
下载的项目需要: 下载的项目需要:
* [Visual Studio 2017 (v15.7.0+)](https://visualstudio.microsoft.com/tr/downloads/) * [Visual Studio 2017 (v15.9.0+)](https://visualstudio.microsoft.com/tr/downloads/)
* [.NET Core 2.1.1+](https://www.microsoft.com/net/download/dotnet-core/) * [.NET Core 2.1.1+](https://www.microsoft.com/net/download/dotnet-core/)
### 解决方案结构 ### 解决方案结构
下载后解压文件并在 **Visual Studio 2017(15.7.0 +)** 中打开: 下载后解压文件并在 **Visual Studio 2017(15.7.0 +)** 中打开:
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png) ![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
该解决方案具有分层结构(基于域驱动设计), 其中: 该解决方案具有分层结构(基于域驱动设计), 其中:
@ -28,6 +28,8 @@
* ``.Web`` 为是表示层. * ``.Web`` 为是表示层.
* ``.EntityFrameworkCore`` 是EF Core集成. * ``.EntityFrameworkCore`` 是EF Core集成.
EF Core 数据库迁移被分离到名为`.EntityFrameworkCore.DbMigrations`项目中.
解决方案还包含配置好的的单元&集成测试项目, 以便与 **EF Core** 和 **SQLite内存中** 数据库配合使用. 解决方案还包含配置好的的单元&集成测试项目, 以便与 **EF Core** 和 **SQLite内存中** 数据库配合使用.
### 创建数据库 ### 创建数据库
@ -48,9 +50,9 @@
![set-as-startup-project](images/set-as-startup-project.png) ![set-as-startup-project](images/set-as-startup-project.png)
打开**包管理器控制台(Package Manager Console)**, 选择`.EntityFrameworkCore`项目作为**默认项目**并运行`Update-Database`命令: 打开**包管理器控制台(Package Manager Console)**, 选择`.EntityFrameworkCore.DbMigrations`项目作为**默认项目**并运行`Update-Database`命令:
![pcm-update-database](images/pcm-update-database.png) ![pcm-update-database](images/pcm-update-database-v2.png)
这将基于配置的连接字符串创建新数据库. 这将基于配置的连接字符串创建新数据库.

14
docs/zh-Hans/Multi-Tenancy.md

@ -6,17 +6,17 @@ ABP的多租户模块提供了创建多租户应用程序的基本功能.
> 软件多租户技术指的是一种软件架构,这种架构可以使用软件的单实例运行并为多个租户提供服务.租户是通过软件实例的特定权限共享通用访问的一组用户.使用多租户架构,软件应用为每个租户提供实例的专用共享,包括实例的数据、配置、用户管理、租户的私有功能和非功能属性.多租户与多实例架构形成对比,将软件实例的行为根据不同的租户分割开来. > 软件多租户技术指的是一种软件架构,这种架构可以使用软件的单实例运行并为多个租户提供服务.租户是通过软件实例的特定权限共享通用访问的一组用户.使用多租户架构,软件应用为每个租户提供实例的专用共享,包括实例的数据、配置、用户管理、租户的私有功能和非功能属性.多租户与多实例架构形成对比,将软件实例的行为根据不同的租户分割开来.
### Volo.Abp.MultiTenancy.Abstractions ### Volo.Abp.MultiTenancy
Volo.Abp.MultiTenancy.Abstractions定义了一些基础接口让你的代码"multi-tenancy ready",使用包管理器控制台(PMC)将它安装到你的项目中: Volo.Abp.MultiTenancy"multi-tenancy ready",使用包管理器控制台(PMC)将它安装到你的项目中:
```` ````
Install-Package Volo.Abp.MultiTenancy.Abstractions Install-Package Volo.Abp.MultiTenancy
```` ````
> 这个包默认安装在了快速启动模板中.所以,大多数情况下,你不需要手动安装它. > 这个包默认安装在了快速启动模板中.所以,大多数情况下,你不需要手动安装它.
然后你可以添加 **AbpMultiTenancyAbstractionsModule** 依赖到你的模块: 然后你可以添加 **AbpMultiTenancyModule** 依赖到你的模块:
````C# ````C#
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -24,7 +24,7 @@ using Volo.Abp.MultiTenancy;
namespace MyCompany.MyProject namespace MyCompany.MyProject
{ {
[DependsOn(typeof(AbpMultiTenancyAbstractionsModule))] [DependsOn(typeof(AbpMultiTenancyModule))]
public class MyModule : AbpModule public class MyModule : AbpModule
{ {
//... //...
@ -98,7 +98,7 @@ Volo.Abp.MultiTenancy 才是让你的程序实现多租户的真正的包.使用
Install-Package Volo.Abp.MultiTenancy Install-Package Volo.Abp.MultiTenancy
```` ````
然后添加 **AbpMultiTenancyAbstractionsModule** 依赖到你的模块中: 然后添加 **AbpMultiTenancyModule** 依赖到你的模块中:
````C# ````C#
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -114,7 +114,7 @@ namespace MyCompany.MyProject
} }
```` ````
> 如果你添加了AbpMultiTenancyModule依赖,就不需要再另外添加AbpMultiTenancyAbstractionsModule依赖了,因为AbpMultiTenancyModule已经依赖它了. > 如果你添加了AbpMultiTenancyModule依赖,就不需要再另外添加AbpMultiTenancyModule依赖了,因为AbpMultiTenancyModule已经依赖它了.
#### 确定当前租户 #### 确定当前租户

25
docs/zh-Hans/Nightly-Builds.md

@ -0,0 +1,25 @@
# 每日构建
所有框架和模块包都每晚都部署到MyGet. 因此你可以使用或测试最新的代码,而无需等待下一个版本.
## 在Visual Studio配置
> 需要Visual Studio 2017以上
1. 在VS中打开: `工具 > 选项 > NuGet 包管理器 > 程序包源`
2. 单击绿色的`+`图标
3. 在底部输入名称(ABP Nightly)和并粘贴URL(`https://www.myget.org/F/abp-nightly/api/v3/index.json`)到源上.
![night-build-add-nuget-source](images/night-build-add-nuget-source.png)
3. 单击`更新`按钮
4. 点击`确定`按钮保存
## 安装包
现在, 你可以从**管理NuGet包** 或 **程序包管理器控制台** 将预览/夜间程序包安装到你的项目中.
![night-build-add-nuget-package](images/night-build-add-nuget-package.png)
1. 在nuget浏览中,选择"包括预发行版".
2. 将包源更改为`全部`.
3. 搜索nuget包. 你将看到包的预发布格式为`(VERSION)-preview(DATE)` (如本示例中的**v0.16.0-preview20190401**).
4. 你可以单击`安装`按钮将包添加到项目中.

1433
docs/zh-Hans/Samples/Microservice-Demo.md

File diff suppressed because it is too large

6
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-I.md

@ -20,7 +20,7 @@
下面的图片展示了从启动模板创建的项目是如何分层的. 下面的图片展示了从启动模板创建的项目是如何分层的.
![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution.png) ![bookstore-visual-studio-solution](images/bookstore-visual-studio-solution-v2.png)
### 创建Book实体 ### 创建Book实体
@ -91,9 +91,9 @@ public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
#### 添加新的Migration并更新数据库 #### 添加新的Migration并更新数据库
这个启动模板使用了[EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/)来创建并维护数据库结构.打开 **Package Manager Console (PMC)** (工具/Nuget包管理器菜单),选择 `Acme.BookStore.EntityFrameworkCore`作为默认的项目然后执行下面的命令: 这个启动模板使用了[EF Core Code First Migrations](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/)来创建并维护数据库结构.打开 **Package Manager Console (PMC)** (工具/Nuget包管理器菜单),选择 `Acme.BookStore.EntityFrameworkCore.DbMigrations`作为默认的项目然后执行下面的命令:
![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration.png) ![bookstore-pmc-add-book-migration](images/bookstore-pmc-add-book-migration-v2.png)
这样就会在`Migrations`文件夹中创建一个新的migration类.然后执行`Update-Database`命令更新数据库结构. 这样就会在`Migrations`文件夹中创建一个新的migration类.然后执行`Update-Database`命令更新数据库结构.

1
docs/zh-Hans/Tutorials/AspNetCore-Mvc/Part-III.md

@ -14,7 +14,6 @@
本解决方案中有两个测试项目: 本解决方案中有两个测试项目:
![bookstore-test-projects](images/bookstore-test-projects.png)
* `Acme.BookStore.Application.Tests` 项目用于单元测试和集成测试.你可以在这个项目中为Application Service方法写测试代码.这个项目使用了 **EF Core SQLite in-memory** 数据库. * `Acme.BookStore.Application.Tests` 项目用于单元测试和集成测试.你可以在这个项目中为Application Service方法写测试代码.这个项目使用了 **EF Core SQLite in-memory** 数据库.
* `Acme.BookStore.Web.Tests` 项目用于包含Web层的完整集成测试.所以,你也可以在这里写关于UI页面的测试. * `Acme.BookStore.Web.Tests` 项目用于包含Web层的完整集成测试.所以,你也可以在这里写关于UI页面的测试.

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
docs/zh-Hans/Tutorials/AspNetCore-Mvc/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

4
docs/zh-Hans/docs-nav.json

@ -278,6 +278,10 @@
{ {
"text": "测试" "text": "测试"
}, },
{
"text": "每日构建",
"path": "Nightly-Builds.md"
},
{ {
"text": "贡献指南", "text": "贡献指南",
"path": "Contribution/Index.md" "path": "Contribution/Index.md"

BIN
docs/zh-Hans/images/bookstore-visual-studio-solution-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
docs/zh-Hans/images/microservice-sample-authserver-home.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/zh-Hans/images/microservice-sample-authserver-login.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/zh-Hans/images/microservice-sample-backend-ui-permissions.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
docs/zh-Hans/images/microservice-sample-backend-ui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/zh-Hans/images/microservice-sample-blogservice-permission-in-database.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
docs/zh-Hans/images/microservice-sample-diagram-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

BIN
docs/zh-Hans/images/microservice-sample-kibana-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
docs/zh-Hans/images/microservice-sample-kibana-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/zh-Hans/images/microservice-sample-product-module-in-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/zh-Hans/images/microservice-sample-public-product-list.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
docs/zh-Hans/images/microservice-sample-solution.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/zh-Hans/images/night-build-add-nuget-package.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
docs/zh-Hans/images/night-build-add-nuget-source.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/zh-Hans/images/pcm-update-database-v2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

28
framework/Volo.Abp.sln

@ -5,23 +5,8 @@ VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CBCC288A-53C3-402F-99F7-E468738560F5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{447C8A77-E5F0-4538-8687-7383196D04EA}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{447C8A77-E5F0-4538-8687-7383196D04EA}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker-files", "docker-files", "{0BEA55D6-E0B8-40DD-A256-B34C4DD990A5}"
ProjectSection(SolutionItems) = preProject
..\docker\docker-compose.yml = ..\docker\docker-compose.yml
..\docker\down.ps1 = ..\docker\down.ps1
..\docker\haproxy.cfg = ..\docker\haproxy.cfg
..\docker\up.ps1 = ..\docker\up.ps1
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6D893E48-0739-401A-9AD1-286BCB6E5517}"
ProjectSection(SolutionItems) = preProject
..\build\build.ps1 = ..\build\build.ps1
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AbpTestBase", "test\AbpTestBase\AbpTestBase.csproj", "{1020F5FD-6A97-40C2-AFCA-EBDF641DF111}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AbpTestBase", "test\AbpTestBase\AbpTestBase.csproj", "{1020F5FD-6A97-40C2-AFCA-EBDF641DF111}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore", "src\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj", "{02BE03BA-3411-448C-AB61-CB36407CC49A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore", "src\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj", "{02BE03BA-3411-448C-AB61-CB36407CC49A}"
@ -102,7 +87,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Data", "src\Volo.A
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Data.Tests", "test\Volo.Abp.Data.Tests\Volo.Abp.Data.Tests.csproj", "{5D2275B7-0745-420A-AF1C-32C563DAB5C8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Data.Tests", "test\Volo.Abp.Data.Tests\Volo.Abp.Data.Tests.csproj", "{5D2275B7-0745-420A-AF1C-32C563DAB5C8}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy.Abstractions", "src\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj", "{10EB789E-C993-4BE8-BA43-C419936C7233}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.MultiTenancy", "src\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj", "{10EB789E-C993-4BE8-BA43-C419936C7233}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping", "src\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj", "{8D22063D-88DE-4F7A-A917-C81AB4ACE601}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectMapping", "src\Volo.Abp.ObjectMapping\Volo.Abp.ObjectMapping.csproj", "{8D22063D-88DE-4F7A-A917-C81AB4ACE601}"
EndProject EndProject
@ -226,7 +211,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Cli
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Contracts", "src\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj", "{88F6D091-CA16-4B71-9499-8D5B8FA2E712}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.Contracts", "src\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj", "{88F6D091-CA16-4B71-9499-8D5B8FA2E712}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Features", "src\Volo.Abp.Features\Volo.Abp.Features.csproj", "{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features", "src\Volo.Abp.Features\Volo.Abp.Features.csproj", "{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Features.Tests", "test\Volo.Abp.Features.Tests\Volo.Abp.Features.Tests.csproj", "{575BEFA1-19C2-49B1-8D31-B5D4472328DE}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -646,13 +633,15 @@ Global
{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}.Debug|Any CPU.Build.0 = Debug|Any CPU {01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}.Release|Any CPU.ActiveCfg = Release|Any CPU {01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}.Release|Any CPU.Build.0 = Release|Any CPU {01E3D389-8872-4EB1-9D3D-13B6ED54DE0E}.Release|Any CPU.Build.0 = Release|Any CPU
{575BEFA1-19C2-49B1-8D31-B5D4472328DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{575BEFA1-19C2-49B1-8D31-B5D4472328DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{575BEFA1-19C2-49B1-8D31-B5D4472328DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{575BEFA1-19C2-49B1-8D31-B5D4472328DE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{0BEA55D6-E0B8-40DD-A256-B34C4DD990A5} = {CBCC288A-53C3-402F-99F7-E468738560F5}
{6D893E48-0739-401A-9AD1-286BCB6E5517} = {CBCC288A-53C3-402F-99F7-E468738560F5}
{1020F5FD-6A97-40C2-AFCA-EBDF641DF111} = {447C8A77-E5F0-4538-8687-7383196D04EA} {1020F5FD-6A97-40C2-AFCA-EBDF641DF111} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{02BE03BA-3411-448C-AB61-CB36407CC49A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {02BE03BA-3411-448C-AB61-CB36407CC49A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{B1D860BB-6EC6-4BAE-ADAA-C2AEC2FFB510} = {447C8A77-E5F0-4538-8687-7383196D04EA} {B1D860BB-6EC6-4BAE-ADAA-C2AEC2FFB510} = {447C8A77-E5F0-4538-8687-7383196D04EA}
@ -756,6 +745,7 @@ Global
{E803DDB8-81EA-454B-9A66-9C2941100B67} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {E803DDB8-81EA-454B-9A66-9C2941100B67} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{88F6D091-CA16-4B71-9499-8D5B8FA2E712} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {88F6D091-CA16-4B71-9499-8D5B8FA2E712} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{01E3D389-8872-4EB1-9D3D-13B6ED54DE0E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {01E3D389-8872-4EB1-9D3D-13B6ED54DE0E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{575BEFA1-19C2-49B1-8D31-B5D4472328DE} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

2
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo.Abp.AspNetCore.MultiTenancy.csproj

@ -15,7 +15,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj" /> <ProjectReference Include="..\Volo.Abp.AspNetCore\Volo.Abp.AspNetCore.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" /> <ProjectReference Include="..\Volo.Abp.MultiTenancy\Volo.Abp.MultiTenancy.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

2
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs

@ -5,7 +5,7 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
[DependsOn( [DependsOn(
typeof(AbpMultiTenancyAbstractionsModule), typeof(AbpMultiTenancyModule),
typeof(AbpAspNetCoreModule) typeof(AbpAspNetCoreModule)
)] )]
public class AbpAspNetCoreMultiTenancyModule : AbpModule public class AbpAspNetCoreMultiTenancyModule : AbpModule

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/CookieTenantResolveContributor.cs

@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
public class CookieTenantResolveContributor : HttpTenantResolveContributorBase public class CookieTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Cookie";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
return httpContext.Request?.Cookies[context.GetAspNetCoreMultiTenancyOptions().TenantKey]; return httpContext.Request?.Cookies[context.GetAspNetCoreMultiTenancyOptions().TenantKey];

16
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/DomainTenantResolveContributor.cs

@ -9,23 +9,33 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
public class DomainTenantResolveContributor : HttpTenantResolveContributorBase public class DomainTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Domain";
public override string Name => ContributorName;
private static readonly string[] ProtocolPrefixes = { "http://", "https://" };
private readonly string _domainFormat; private readonly string _domainFormat;
public DomainTenantResolveContributor(string domainFormat) public DomainTenantResolveContributor(string domainFormat)
{ {
_domainFormat = domainFormat.RemovePreFix("http://", "https://"); _domainFormat = domainFormat.RemovePreFix(ProtocolPrefixes);
} }
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(
ITenantResolveContext context,
HttpContext httpContext)
{ {
if (httpContext.Request?.Host == null) if (httpContext.Request?.Host == null)
{ {
return null; return null;
} }
var hostName = httpContext.Request.Host.Host.RemovePreFix("http://", "https://"); var hostName = httpContext.Request.Host.Host.RemovePreFix(ProtocolPrefixes);
var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true); var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true);
context.Handled = true;
if (!extractResult.IsMatch) if (!extractResult.IsMatch)
{ {
return null; return null;

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HeaderTenantResolveContributor.cs

@ -9,6 +9,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
public class HeaderTenantResolveContributor : HttpTenantResolveContributorBase public class HeaderTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Header";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
if (httpContext.Request == null || httpContext.Request.Headers.IsNullOrEmpty()) if (httpContext.Request == null || httpContext.Request.Headers.IsNullOrEmpty())

39
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpContextTenantResolveResultAccessor.cs

@ -0,0 +1,39 @@
using Microsoft.AspNetCore.Http;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy
{
[Dependency(ReplaceServices = true)]
public class HttpContextTenantResolveResultAccessor : ITenantResolveResultAccessor, ITransientDependency
{
public TenantResolveResult Result
{
get
{
if (_httpContextAccessor.HttpContext == null)
{
return null;
}
return _httpContextAccessor.HttpContext.Items[""] as TenantResolveResult;
}
set
{
if (_httpContextAccessor.HttpContext == null)
{
return;
}
_httpContextAccessor.HttpContext.Items[""] = value;
}
}
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextTenantResolveResultAccessor(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
}
}

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/HttpTenantResolveContributerBase.cs

@ -7,9 +7,9 @@ using Volo.Abp.MultiTenancy;
namespace Volo.Abp.AspNetCore.MultiTenancy namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
public abstract class HttpTenantResolveContributorBase : ITenantResolveContributor public abstract class HttpTenantResolveContributorBase : TenantResolveContributorBase
{ {
public virtual void Resolve(ITenantResolveContext context) public override void Resolve(ITenantResolveContext context)
{ {
var httpContext = context.GetHttpContext(); var httpContext = context.GetHttpContext();
if (httpContext == null) if (httpContext == null)

51
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs

@ -1,6 +1,5 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
@ -12,46 +11,48 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
private readonly ITenantResolver _tenantResolver; private readonly ITenantResolver _tenantResolver;
private readonly ITenantStore _tenantStore; private readonly ITenantStore _tenantStore;
private readonly ICurrentTenantIdAccessor _currentTenantIdAccessor; private readonly ICurrentTenant _currentTenant;
private readonly ITenantResolveResultAccessor _tenantResolveResultAccessor;
public MultiTenancyMiddleware( public MultiTenancyMiddleware(
RequestDelegate next, RequestDelegate next,
ITenantResolver tenantResolver, ITenantResolver tenantResolver,
ITenantStore tenantStore, ITenantStore tenantStore,
ICurrentTenantIdAccessor currentTenantIdAccessor) ICurrentTenant currentTenant,
ITenantResolveResultAccessor tenantResolveResultAccessor)
{ {
_next = next; _next = next;
_tenantResolver = tenantResolver; _tenantResolver = tenantResolver;
_tenantStore = tenantStore; _tenantStore = tenantStore;
_currentTenantIdAccessor = currentTenantIdAccessor; _currentTenant = currentTenant;
_tenantResolveResultAccessor = tenantResolveResultAccessor;
} }
public async Task Invoke(HttpContext httpContext) public async Task Invoke(HttpContext httpContext)
{ {
using (SetCurrentTenant(await ResolveCurrentTenantAsync())) var resolveResult = _tenantResolver.ResolveTenantIdOrName();
{ _tenantResolveResultAccessor.Result = resolveResult;
await _next(httpContext);
}
}
private async Task<TenantInfo> ResolveCurrentTenantAsync() TenantConfiguration tenant = null;
{ if (resolveResult.TenantIdOrName != null)
var tenantIdOrName = _tenantResolver.ResolveTenantIdOrName();
if (tenantIdOrName == null)
{ {
return null; tenant = await FindTenantAsync(resolveResult.TenantIdOrName);
if (tenant == null)
{
//TODO: A better exception?
throw new AbpException(
"There is no tenant with given tenant id or name: " + resolveResult.TenantIdOrName
);
}
} }
var tenant = await FindTenantAsync(tenantIdOrName); using (_currentTenant.Change(tenant?.Id, tenant?.Name))
if (tenant == null)
{ {
throw new AbpException("There is no tenant with given tenant id or name: " + tenantIdOrName); await _next(httpContext);
} }
return tenant;
} }
private async Task<TenantInfo> FindTenantAsync(string tenantIdOrName) private async Task<TenantConfiguration> FindTenantAsync(string tenantIdOrName)
{ {
if (Guid.TryParse(tenantIdOrName, out var parsedTenantId)) if (Guid.TryParse(tenantIdOrName, out var parsedTenantId))
{ {
@ -62,15 +63,5 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
return await _tenantStore.FindAsync(tenantIdOrName); return await _tenantStore.FindAsync(tenantIdOrName);
} }
} }
private IDisposable SetCurrentTenant([CanBeNull] TenantInfo tenant)
{
var parentScope = _currentTenantIdAccessor.Current;
_currentTenantIdAccessor.Current = new TenantIdWrapper(tenant?.Id);
return new DisposeAction(() =>
{
_currentTenantIdAccessor.Current = parentScope;
});
}
} }
} }

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/QueryStringTenantResolveContributor.cs

@ -5,6 +5,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
public class QueryStringTenantResolveContributor : HttpTenantResolveContributorBase public class QueryStringTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "QueryString";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
if (httpContext.Request == null || !httpContext.Request.QueryString.HasValue) if (httpContext.Request == null || !httpContext.Request.QueryString.HasValue)

4
framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/RouteTenantResolveContributor.cs

@ -7,6 +7,10 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
{ {
public class RouteTenantResolveContributor : HttpTenantResolveContributorBase public class RouteTenantResolveContributor : HttpTenantResolveContributorBase
{ {
public const string ContributorName = "Route";
public override string Name => ContributorName;
protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext) protected override string GetTenantIdOrNameFromHttpContextOrNull(ITenantResolveContext context, HttpContext httpContext)
{ {
var tenantId = httpContext.GetRouteValue(context.GetAspNetCoreMultiTenancyOptions().TenantKey); var tenantId = httpContext.GetRouteValue(context.GetAspNetCoreMultiTenancyOptions().TenantKey);

22
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteFeatureChecker.cs

@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Features;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class RemoteFeatureChecker : FeatureCheckerBase
{
protected ICachedApplicationConfigurationClient ConfigurationClient { get; }
public RemoteFeatureChecker(ICachedApplicationConfigurationClient configurationClient)
{
ConfigurationClient = configurationClient;
}
public override async Task<string> GetOrNullAsync(string name)
{
var configuration = await ConfigurationClient.GetAsync();
return configuration.Features.Values.GetOrDefault(name);
}
}
}

23
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/RemoteLanguageProvider.cs

@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.Client
{
public class RemoteLanguageProvider : ILanguageProvider, ITransientDependency
{
protected ICachedApplicationConfigurationClient ConfigurationClient { get; }
public RemoteLanguageProvider(ICachedApplicationConfigurationClient configurationClient)
{
ConfigurationClient = configurationClient;
}
public async Task<IReadOnlyList<LanguageInfo>> GetLanguagesAsync()
{
var configuration = await ConfigurationClient.GetAsync();
return configuration.Localization.Languages;
}
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationConfigurationDto.cs

@ -12,5 +12,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
public ApplicationSettingConfigurationDto Setting { get; set; } public ApplicationSettingConfigurationDto Setting { get; set; }
public CurrentUserDto CurrentUser { get; set; } public CurrentUserDto CurrentUser { get; set; }
public ApplicationFeatureConfigurationDto Features { get; set; }
} }
} }

16
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationFeatureConfigurationDto.cs

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{
[Serializable]
public class ApplicationFeatureConfigurationDto
{
public Dictionary<string, string> Values { get; set; }
public ApplicationFeatureConfigurationDto()
{
Values = new Dictionary<string, string>();
}
}
}

5
framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationConfigurationDto.cs

@ -1,16 +1,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.Localization;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
{ {
[Serializable] [Serializable]
public class ApplicationLocalizationConfigurationDto public class ApplicationLocalizationConfigurationDto
{ {
//TODO: Rename to Texts?
public Dictionary<string, Dictionary<string, string>> Values { get; set; } public Dictionary<string, Dictionary<string, string>> Values { get; set; }
public List<LanguageInfo> Languages { get; set; }
public ApplicationLocalizationConfigurationDto() public ApplicationLocalizationConfigurationDto()
{ {
Values = new Dictionary<string, Dictionary<string, string>>(); Values = new Dictionary<string, Dictionary<string, string>>();
Languages = new List<LanguageInfo>();
} }
} }
} }

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/AbpAspNetCoreMvcUiBootstrapModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Pages/Abp/MultiTenancy/tenant-switch.js

@ -3,7 +3,7 @@
var tenantSwitchModal = new abp.ModalManager(abp.appPath + 'Abp/MultiTenancy/TenantSwitchModal'); var tenantSwitchModal = new abp.ModalManager(abp.appPath + 'Abp/MultiTenancy/TenantSwitchModal');
$(function() { $(function() {
$('#TenantSwitchToolbarLink').click(function(e) { $('#AbpTenantSwitchLink').click(function(e) {
e.preventDefault(); e.preventDefault();
tenantSwitchModal.open(); tenantSwitchModal.open();
}); });

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj

@ -18,11 +18,9 @@
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Pages\**\*.cshtml" /> <EmbeddedResource Include="Pages\**\*.cshtml" />
<EmbeddedResource Include="Pages\**\*.js" /> <EmbeddedResource Include="Pages\**\*.js" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" /> <EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
<Content Remove="Pages\**\*.cshtml" /> <Content Remove="Pages\**\*.cshtml" />
<Content Remove="Pages\**\*.js" /> <Content Remove="Pages\**\*.js" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Components\**\*.cshtml" />
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" /> <Content Remove="Volo\Abp\AspNetCore\Mvc\UI\MultiTenancy\Localization\*.json" />
</ItemGroup> </ItemGroup>

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/AbpAspNetCoreMvcUiMultiTenancyModule.cs

@ -1,11 +1,9 @@
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization; using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
@ -36,11 +34,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiMultiTenancyModule>(); options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiMultiTenancyModule>();
}); });
Configure<ToolbarOptions>(options =>
{
options.Contributors.Add(new MultiTenancyToolbarContributor());
});
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {
options.Resources options.Resources

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml

@ -1,17 +0,0 @@
@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch
@model TenantSwitchViewComponent.TenantSwitchViewModel
@if (!Model.CurrentUser.IsAuthenticated)
{
<li class="nav-item">
<a abp-button="Link" id="TenantSwitchToolbarLink" href="#">
@if (Model.Tenant == null)
{
<text>@@host</text>
}
else
{
<text>@@@Model.Tenant.Name</text>
}
</a>
</li>
}

51
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/TenantSwitchViewComponent.cs

@ -1,51 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch
{
public class TenantSwitchViewComponent : AbpViewComponent
{
/// <summary>
/// -1,000,000
/// </summary>
public const int Order = -1_000_000;
protected ITenantStore TenantStore { get; }
protected ICurrentTenant CurrentTenant { get; }
protected ICurrentUser CurrentUser { get; }
public TenantSwitchViewComponent(
ITenantStore tenantStore,
ICurrentTenant currentTenant,
ICurrentUser currentUser)
{
TenantStore = tenantStore;
CurrentTenant = currentTenant;
CurrentUser = currentUser;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var model = new TenantSwitchViewModel
{
CurrentUser = CurrentUser
};
if (CurrentTenant.Id.HasValue)
{
model.Tenant = await TenantStore.FindAsync(CurrentTenant.GetId());
}
return View("~/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Components/TenantSwitch/Default.cshtml", model);
}
public class TenantSwitchViewModel
{
public TenantInfo Tenant { get; set; }
public ICurrentUser CurrentUser { get; set; }
}
}
}

8
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/en.json

@ -1,9 +1,11 @@
{ {
"culture": "en", "culture": "en",
"texts": { "texts": {
"GivenTenantIsNotAvailable": "Given tenant is not available: {0}", "GivenTenantIsNotAvailable": "Given tenant is not available: {0}",
"SwitchTenant": "Switch tenant", "Tenant": "Tenant",
"Switch": "switch",
"Name": "Name", "Name": "Name",
"SwitchTenantHint": "Leave the name field blank to switch to the host side." "SwitchTenantHint": "Leave the name field blank to switch to the host side.",
"NotSelected": "Not selected"
} }
} }

6
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/tr.json

@ -2,8 +2,10 @@
"culture": "tr", "culture": "tr",
"texts": { "texts": {
"GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}", "GivenTenantIsNotAvailable": "İstenilen müşteri bulunamadı: {0}",
"SwitchTenant": "Müşteri değiştir", "Tenant": "Müşteri",
"Switch": "değiştir",
"Name": "İsim", "Name": "İsim",
"SwitchTenantHint": "Host tarafına geçmek için isim alanını boş bırakın." "SwitchTenantHint": "Host tarafına geçmek için isim alanını boş bırakın.",
"NotSelected": "Seçili değil"
} }
} }

21
framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/MultiTenancyToolbarContributor.cs

@ -1,21 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Components.TenantSwitch;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars;
namespace Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy
{
public class MultiTenancyToolbarContributor : IToolbarContributor
{
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
{
if (context.Toolbar.Name != StandardToolbars.Main)
{
return Task.CompletedTask;
}
context.Toolbar.Items.Add(new ToolbarItem(typeof(TenantSwitchViewComponent), TenantSwitchViewComponent.Order));
return Task.CompletedTask;
}
}
}

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/AbpAspNetCoreMvcUIBasicThemeModule.cs

@ -1,4 +1,5 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Toolbars; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Toolbars;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
@ -11,7 +12,8 @@ using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic
{ {
[DependsOn( [DependsOn(
typeof(AbpAspNetCoreMvcUiThemeSharedModule) typeof(AbpAspNetCoreMvcUiThemeSharedModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule)
)] )]
public class AbpAspNetCoreMvcUiBasicThemeModule : AbpModule public class AbpAspNetCoreMvcUiBasicThemeModule : AbpModule
{ {

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/Default.cshtml

@ -7,7 +7,7 @@
var disabled = menuItem.IsDisabled ? "disabled" : string.Empty; var disabled = menuItem.IsDisabled ? "disabled" : string.Empty;
if (menuItem.IsLeaf) if (menuItem.IsLeaf)
{ {
@if (menuItem.Url != null) if (menuItem.Url != null)
{ {
<li class="nav-item @cssClass @disabled" @elementId> <li class="nav-item @cssClass @disabled" @elementId>
<a class="nav-link" href="@(menuItem.Url ?? "#")"> <a class="nav-link" href="@(menuItem.Url ?? "#")">

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/_MenuItem.cshtml

@ -7,7 +7,7 @@
} }
@if (Model.IsLeaf) @if (Model.IsLeaf)
{ {
@if (Model.Url != null) if (Model.Url != null)
{ {
<a class="dropdown-item @cssClass @disabled" href="@(Model.Url ?? "#")" @Html.Raw(elementId)> <a class="dropdown-item @cssClass @disabled" href="@(Model.Url ?? "#")" @Html.Raw(elementId)>
@Model.DisplayName @Model.DisplayName

34
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Account.cshtml

@ -1,10 +1,20 @@
@using Volo.Abp.AspNetCore.Mvc.AntiForgery @using Microsoft.Extensions.Localization
@using Microsoft.Extensions.Options
@using Volo.Abp.AspNetCore.MultiTenancy
@using Volo.Abp.AspNetCore.Mvc.AntiForgery
@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling @using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.MainNavbar @using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.MainNavbar
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.PageAlerts @using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Themes.Basic.Components.PageAlerts
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components @using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components
@using Volo.Abp.MultiTenancy
@inject IAbpAntiForgeryManager AbpAntiForgeryManager @inject IAbpAntiForgeryManager AbpAntiForgeryManager
@inject IBrandingProvider BrandingProvider @inject IBrandingProvider BrandingProvider
@inject IOptions<MultiTenancyOptions> MultiTenancyOptions
@inject ICurrentTenant CurrentTenant
@inject IStringLocalizer<AbpUiMultiTenancyResource> MultiTenancyStringLocalizer
@inject ITenantResolveResultAccessor TenantResolveResultAccessor
@{ @{
Layout = null; Layout = null;
AbpAntiForgeryManager.SetCookie(); AbpAntiForgeryManager.SetCookie();
@ -23,7 +33,7 @@
<abp-style-bundle name="@BasicThemeBundles.Styles.Global" /> <abp-style-bundle name="@BasicThemeBundles.Styles.Global" />
@RenderSection("styles", false) @await RenderSectionAsync("styles", false)
</head> </head>
<body class="abp-account-layout"> <body class="abp-account-layout">
@ -32,6 +42,24 @@
<div class="@containerClass"> <div class="@containerClass">
<abp-row> <abp-row>
<abp-column size-md="_4" offset-md="_4"> <abp-column size-md="_4" offset-md="_4">
@if (MultiTenancyOptions.Value.IsEnabled &&
(TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true))
{
<div class="tenant-switch-box" style="background-color: #eee; margin-bottom: 20px; color: #000; padding: 10px; text-align: center;">
<span style="color: #666;">@MultiTenancyStringLocalizer["Tenant"]: </span>
<strong>
@if (CurrentTenant.Id == null)
{
<i>@MultiTenancyStringLocalizer["NotSelected"]</i>
}
else
{
@(CurrentTenant.Name ?? CurrentTenant.Id.Value.ToString())
}
</strong>
(<a id="AbpTenantSwitchLink" style="color: #333; cursor: pointer">@MultiTenancyStringLocalizer["Switch"]</a>)
</div>
}
@(await Component.InvokeAsync<PageAlertsViewComponent>()) @(await Component.InvokeAsync<PageAlertsViewComponent>())
@RenderBody() @RenderBody()
</abp-column> </abp-column>
@ -43,7 +71,7 @@
<script type="text/javascript" src="~/Abp/ApplicationConfigurationScript"></script> <script type="text/javascript" src="~/Abp/ApplicationConfigurationScript"></script>
<script type="text/javascript" src="~/Abp/ServiceProxyScript"></script> <script type="text/javascript" src="~/Abp/ServiceProxyScript"></script>
@RenderSection("scripts", false) @await RenderSectionAsync("scripts", false)
</body> </body>
</html> </html>

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml

@ -23,7 +23,7 @@
<abp-style-bundle name="@BasicThemeBundles.Styles.Global" /> <abp-style-bundle name="@BasicThemeBundles.Styles.Global" />
@RenderSection("styles", false) @await RenderSectionAsync("styles", false)
</head> </head>
<body class="abp-application-layout"> <body class="abp-application-layout">
@ -39,7 +39,7 @@
<script type="text/javascript" src="~/Abp/ApplicationConfigurationScript"></script> <script type="text/javascript" src="~/Abp/ApplicationConfigurationScript"></script>
<script type="text/javascript" src="~/Abp/ServiceProxyScript"></script> <script type="text/javascript" src="~/Abp/ServiceProxyScript"></script>
@RenderSection("scripts", false) @await RenderSectionAsync("scripts", false)
</body> </body>
</html> </html>

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml

@ -22,7 +22,7 @@
<abp-style-bundle name="@BasicThemeBundles.Styles.Global" /> <abp-style-bundle name="@BasicThemeBundles.Styles.Global" />
@RenderSection("styles", false) @await RenderSectionAsync("styles", false)
</head> </head>
<body class="abp-empty-layout"> <body class="abp-empty-layout">
@ -36,7 +36,7 @@
<script type="text/javascript" src="~/Abp/ApplicationConfigurationScript"></script> <script type="text/javascript" src="~/Abp/ApplicationConfigurationScript"></script>
<script type="text/javascript" src="~/Abp/ServiceProxyScript"></script> <script type="text/javascript" src="~/Abp/ServiceProxyScript"></script>
@RenderSection("scripts", false) @await RenderSectionAsync("scripts", false)
</body> </body>
</html> </html>

1
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj

@ -31,6 +31,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj" />
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" /> <ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />
</ItemGroup> </ItemGroup>

3
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/AbpAspNetCoreMvcUiThemeSharedModule.cs

@ -1,5 +1,4 @@
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages; using Volo.Abp.AspNetCore.Mvc.UI.Packages;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling;

17
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js

@ -338,6 +338,23 @@
} }
} }
configuration.language = {
info: localize("PagerInfo"),
infoFiltered: localize("PagerInfoFiltered"),
infoEmpty: localize("PagerInfoEmpty"),
search: localize("PagerSearch"),
processing: localize("ProcessingWithThreeDot"),
loadingRecords: localize("LoadingWithThreeDot"),
lengthMenu: localize("PagerShowMenuEntries"),
emptyTable: localize("NoDataAvailableInDatatable"),
paginate: {
first: localize("PagerFirst"),
last: localize("PagerLast"),
previous: localize("PagerPrevious"),
next: localize("PagerNext")
}
};
configuration.dom = '<"dataTable_filters"f>rt<"row dataTable_footer"<"col-auto"l><"col-auto"i><"col"p>>'; configuration.dom = '<"dataTable_filters"f>rt<"row dataTable_footer"<"col-auto"l><"col-auto"i><"col"p>>';
return configuration; return configuration;

0
framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Layout/ILayoutManager.cs → framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Layout/IPageLayout.cs

15
framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Http/AbpFormFileExtensions.cs

@ -0,0 +1,15 @@
using System.IO;
namespace Microsoft.AspNetCore.Http
{
public static class AbpFormFileExtensions
{
public static byte[] GetAllBytes(this IFormFile file)
{
using (var stream = file.OpenReadStream())
{
return stream.GetAllBytes();
}
}
}
}

8
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs

@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Aspects; using Volo.Abp.Aspects;
using Volo.Abp.AspNetCore.Mvc.Validation; using Volo.Abp.AspNetCore.Mvc.Validation;
using Volo.Abp.Features;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
@ -28,12 +30,16 @@ namespace Volo.Abp.AspNetCore.Mvc
public ICurrentTenant CurrentTenant { get; set; } public ICurrentTenant CurrentTenant { get; set; }
public IAuthorizationService AuthorizationService { get; set; }
protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current; protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current;
public IClock Clock { get; set; } public IClock Clock { get; set; }
public IModelStateValidator ModelValidator { get; set; } public IModelStateValidator ModelValidator { get; set; }
public IFeatureChecker FeatureChecker { get; set; }
public List<string> AppliedCrossCuttingConcerns { get; } = new List<string>(); public List<string> AppliedCrossCuttingConcerns { get; } = new List<string>();
protected virtual void ValidateModel() protected virtual void ValidateModel()

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs

@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Auditing; using Volo.Abp.AspNetCore.Mvc.Auditing;
using Volo.Abp.AspNetCore.Mvc.Conventions; using Volo.Abp.AspNetCore.Mvc.Conventions;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling; using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc.Features;
using Volo.Abp.AspNetCore.Mvc.Uow; using Volo.Abp.AspNetCore.Mvc.Uow;
using Volo.Abp.AspNetCore.Mvc.Validation; using Volo.Abp.AspNetCore.Mvc.Validation;
@ -26,6 +27,7 @@ namespace Volo.Abp.AspNetCore.Mvc
private static void AddFilters(MvcOptions options) private static void AddFilters(MvcOptions options)
{ {
options.Filters.AddService(typeof(AbpAuditActionFilter)); options.Filters.AddService(typeof(AbpAuditActionFilter));
options.Filters.AddService(typeof(AbpFeatureActionFilter));
options.Filters.AddService(typeof(AbpValidationActionFilter)); options.Filters.AddService(typeof(AbpValidationActionFilter));
options.Filters.AddService(typeof(AbpUowActionFilter)); options.Filters.AddService(typeof(AbpUowActionFilter));
options.Filters.AddService(typeof(AbpExceptionFilter)); options.Filters.AddService(typeof(AbpExceptionFilter));

39
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -4,10 +4,10 @@ using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.Authorization; using Volo.Abp.Authorization;
using Volo.Abp.Features;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Settings; using Volo.Abp.Settings;
using Volo.Abp.Users; using Volo.Abp.Users;
@ -23,6 +23,8 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
private readonly ICurrentUser _currentUser; private readonly ICurrentUser _currentUser;
private readonly ISettingProvider _settingProvider; private readonly ISettingProvider _settingProvider;
private readonly ISettingDefinitionManager _settingDefinitionManager; private readonly ISettingDefinitionManager _settingDefinitionManager;
private readonly IFeatureDefinitionManager _featureDefinitionManager;
private readonly ILanguageProvider _languageProvider;
public AbpApplicationConfigurationAppService( public AbpApplicationConfigurationAppService(
IOptions<AbpLocalizationOptions> localizationOptions, IOptions<AbpLocalizationOptions> localizationOptions,
@ -31,7 +33,9 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
IAuthorizationService authorizationService, IAuthorizationService authorizationService,
ICurrentUser currentUser, ICurrentUser currentUser,
ISettingProvider settingProvider, ISettingProvider settingProvider,
SettingDefinitionManager settingDefinitionManager) SettingDefinitionManager settingDefinitionManager,
IFeatureDefinitionManager featureDefinitionManager,
ILanguageProvider languageProvider)
{ {
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider; _abpAuthorizationPolicyProvider = abpAuthorizationPolicyProvider;
@ -39,17 +43,20 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
_currentUser = currentUser; _currentUser = currentUser;
_settingProvider = settingProvider; _settingProvider = settingProvider;
_settingDefinitionManager = settingDefinitionManager; _settingDefinitionManager = settingDefinitionManager;
_featureDefinitionManager = featureDefinitionManager;
_languageProvider = languageProvider;
_localizationOptions = localizationOptions.Value; _localizationOptions = localizationOptions.Value;
} }
public async Task<ApplicationConfigurationDto> GetAsync() public virtual async Task<ApplicationConfigurationDto> GetAsync()
{ {
//TODO: Optimize & cache..? //TODO: Optimize & cache..?
return new ApplicationConfigurationDto return new ApplicationConfigurationDto
{ {
Auth = await GetAuthConfigAsync(), Auth = await GetAuthConfigAsync(),
Localization = GetLocalizationConfig(), Features = await GetFeaturesConfigAsync(),
Localization = await GetLocalizationConfigAsync(),
CurrentUser = GetCurrentUser(), CurrentUser = GetCurrentUser(),
Setting = await GetSettingConfigAsync() Setting = await GetSettingConfigAsync()
}; };
@ -83,10 +90,12 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return authConfig; return authConfig;
} }
protected virtual ApplicationLocalizationConfigurationDto GetLocalizationConfig() protected virtual async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync()
{ {
var localizationConfig = new ApplicationLocalizationConfigurationDto(); var localizationConfig = new ApplicationLocalizationConfigurationDto();
localizationConfig.Languages.AddRange(await _languageProvider.GetLanguagesAsync());
foreach (var resource in _localizationOptions.Resources.Values) foreach (var resource in _localizationOptions.Resources.Values)
{ {
var dictionary = new Dictionary<string, string>(); var dictionary = new Dictionary<string, string>();
@ -100,8 +109,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
dictionary[localizedString.Name] = localizedString.Value; dictionary[localizedString.Name] = localizedString.Value;
} }
var resourceName = LocalizationResourceNameAttribute.GetName(resource.ResourceType); localizationConfig.Values[resource.ResourceName] = dictionary;
localizationConfig.Values[resourceName] = dictionary;
} }
return localizationConfig; return localizationConfig;
@ -126,5 +134,22 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
return result; return result;
} }
protected virtual async Task<ApplicationFeatureConfigurationDto> GetFeaturesConfigAsync()
{
var result = new ApplicationFeatureConfigurationDto();
foreach (var featureDefinition in _featureDefinitionManager.GetAll())
{
if (!featureDefinition.IsVisibleToClients)
{
continue;
}
result.Values[featureDefinition.Name] = await FeatureChecker.GetOrNullAsync(featureDefinition.Name);
}
return result;
}
} }
} }

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs

@ -92,6 +92,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Auditing
auditLog = auditLogScope.Log; auditLog = auditLogScope.Log;
auditLogAction = _auditingHelper.CreateAuditLogAction( auditLogAction = _auditingHelper.CreateAuditLogAction(
auditLog,
context.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType(), context.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType(),
context.ActionDescriptor.AsControllerActionDescriptor().MethodInfo, context.ActionDescriptor.AsControllerActionDescriptor().MethodInfo,
context.ActionArguments context.ActionArguments

42
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Features/AbpFeatureActionFilter.cs

@ -0,0 +1,42 @@
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Volo.Abp.Aspects;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
namespace Volo.Abp.AspNetCore.Mvc.Features
{
public class AbpFeatureActionFilter : IAsyncActionFilter, ITransientDependency
{
private readonly IMethodInvocationFeatureCheckerService _methodInvocationAuthorizationService;
public AbpFeatureActionFilter(IMethodInvocationFeatureCheckerService methodInvocationAuthorizationService)
{
_methodInvocationAuthorizationService = methodInvocationAuthorizationService;
}
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
if (!context.ActionDescriptor.IsControllerAction())
{
await next();
return;
}
var methodInfo = context.ActionDescriptor.GetMethodInfo();
using (AbpCrossCuttingConcerns.Applying(context.Controller, AbpCrossCuttingConcerns.FeatureChecking))
{
await _methodInvocationAuthorizationService.CheckAsync(
new MethodInvocationFeatureCheckerContext(methodInfo)
);
await next();
}
}
}
}

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs

@ -12,7 +12,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Uow
{ {
public class AbpUowActionFilter : IAsyncActionFilter, ITransientDependency public class AbpUowActionFilter : IAsyncActionFilter, ITransientDependency
{ {
private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly UnitOfWorkDefaultOptions _defaultOptions; private readonly UnitOfWorkDefaultOptions _defaultOptions;

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

Loading…
Cancel
Save