Browse Source

Merge branch 'dev' of https://github.com/abpframework/abp into 2294-Dynamic-CSharp-Api-Clients-net-standard20

pull/2867/head
Necati Meral 7 years ago
parent
commit
1702ea6156
  1. 1
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  2. 4
      docs/en/Modules/Docs.md
  3. 4
      docs/zh-Hans/Modules/Docs.md
  4. 8
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs
  5. 70
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController.cs
  6. 130
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs
  7. 25
      modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPage.cs
  8. 8
      modules/docs/src/Volo.Docs.Web/DocsWebModule.cs
  9. 436
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml
  10. 17
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs
  11. 53
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/DocumentNotFoundComponent/Default.cshtml
  12. 15
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/DocumentNotFoundComponent/DocumentNotFoundPageModel.cs
  13. 26
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/DocumentNotFoundComponent/DocumentNotFoundViewComponent.cs
  14. 1
      modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj
  15. 18
      npm/packs/jquery/src/abp.jquery.js
  16. 1
      samples/MicroserviceDemo/applications/AuthServer.Host/AuthServer.Host.csproj
  17. 4
      samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerHostModule.cs

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

@ -6,6 +6,7 @@
"Volo.AbpIo.Commercial:010003": "You are not owner of this organization!", "Volo.AbpIo.Commercial:010003": "You are not owner of this organization!",
"OrganizationNotFoundMessage": "No organization found!", "OrganizationNotFoundMessage": "No organization found!",
"DeveloperCount": "Developer count", "DeveloperCount": "Developer count",
"QuestionCount": "Question count",
"Owners": "Owners", "Owners": "Owners",
"AddMember": "Add member", "AddMember": "Add member",
"AddOwner": "Add owner", "AddOwner": "Add owner",

4
docs/en/Modules/Docs.md

@ -328,7 +328,7 @@ You can use [ABP Framework](https://github.com/abpframework/abp/) GitHub documen
For `SQL` databases, you can use the below `T-SQL` command to insert the specified sample into your `DocsProjects` table: For `SQL` databases, you can use the below `T-SQL` command to insert the specified sample into your `DocsProjects` table:
```mssql ```mssql
INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939658', N'ABP framework (GitHub)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'GitHub', N'{"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs","GitHubAccessToken":"***"}', N'/', N'master') INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939658', N'ABP framework (GitHub)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'GitHub', N'{"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs","GitHubAccessToken":"***"}', N'/', N'master', N'')
``` ```
Be aware that `GitHubAccessToken` is masked. It's a private token and you must get your own token and replace the `***` string. Be aware that `GitHubAccessToken` is masked. It's a private token and you must get your own token and replace the `***` string.
@ -366,7 +366,7 @@ You can use [ABP Framework](https://github.com/abpframework/abp/) GitHub documen
For `SQL` databases, you can use the below `T-SQL` command to insert the specified sample into your `DocsProjects` table: For `SQL` databases, you can use the below `T-SQL` command to insert the specified sample into your `DocsProjects` table:
```mssql ```mssql
INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL) INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL, N'')
``` ```
Add one of the sample projects above and run the application. In the menu you will see `Documents` link, click the menu link to open the documents page. Add one of the sample projects above and run the application. In the menu you will see `Documents` link, click the menu link to open the documents page.

4
docs/zh-Hans/Modules/Docs.md

@ -321,7 +321,7 @@ There are no projects yet!
对于 `SQL` 数据库,你可以使用下面的 `T-SQL` 命令将指定的示例插入到 `DocsProjects` 表中: 对于 `SQL` 数据库,你可以使用下面的 `T-SQL` 命令将指定的示例插入到 `DocsProjects` 表中:
```mssql ```mssql
INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939658', N'ABP framework (GitHub)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'GitHub', N'{"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs/zh-Hans/","GitHubAccessToken":"***"}', N'/', N'master') INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939658', N'ABP framework (GitHub)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'GitHub', N'{"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs","GitHubAccessToken":"***"}', N'/', N'master', N'')
``` ```
请注意,`GitHubAccessToken` 被屏蔽了.它是一个私人令牌,你必须获得自己的令牌并替换 `***` 字符串. 请注意,`GitHubAccessToken` 被屏蔽了.它是一个私人令牌,你必须获得自己的令牌并替换 `***` 字符串.
@ -359,7 +359,7 @@ INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocume
对于 `SQL` 数据库,你可以使用下面的 `T-SQL` 命令将指定的示例插入到 `DocsProjects` 表中: 对于 `SQL` 数据库,你可以使用下面的 `T-SQL` 命令将指定的示例插入到 `DocsProjects` 表中:
```mssql ```mssql
INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL) INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL, N'')
``` ```
添加上面的一个示例项目后运行该应用程序. 在菜单中你会看到`文档` 链接,点击菜单链接打开文档页面. 添加上面的一个示例项目后运行该应用程序. 在菜单中你会看到`文档` 链接,点击菜单链接打开文档页面.

8
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs

@ -30,10 +30,10 @@ namespace Volo.Abp.Auditing
/// Default: true. /// Default: true.
/// </summary> /// </summary>
public bool IsEnabledForAnonymousUsers { get; set; } public bool IsEnabledForAnonymousUsers { get; set; }
/// <summary> /// <summary>
/// Audit log on exceptions. /// Audit log on exceptions.
/// Default: true. /// Default: true.
/// </summary> /// </summary>
public bool AlwaysLogOnException { get; set; } public bool AlwaysLogOnException { get; set; }

70
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController.cs

@ -1,35 +1,35 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
namespace Volo.Abp.AspNetCore.Mvc.Auditing namespace Volo.Abp.AspNetCore.Mvc.Auditing
{ {
[Route("api/audit-test")] [Route("api/audit-test")]
[Audited] [Audited]
public class AuditTestController : AbpController public class AuditTestController : AbpController
{ {
private readonly AbpAuditingOptions _options; private readonly AbpAuditingOptions _options;
public AuditTestController(IOptions<AbpAuditingOptions> options) public AuditTestController(IOptions<AbpAuditingOptions> options)
{ {
_options = options.Value; _options = options.Value;
} }
[Route("audit-success")] [Route("audit-success")]
public IActionResult AuditSuccessForGetRequests() public IActionResult AuditSuccessForGetRequests()
{ {
return Ok(); return Ok();
} }
[Route("audit-fail")] [Route("audit-fail")]
public IActionResult AuditFailForGetRequests() public IActionResult AuditFailForGetRequests()
{ {
throw new UserFriendlyException("Exception occurred!"); throw new UserFriendlyException("Exception occurred!");
} }
[Route("audit-fail-object")] [Route("audit-fail-object")]
public object AuditFailForGetRequestsReturningObject() public object AuditFailForGetRequestsReturningObject()
{ {
throw new UserFriendlyException("Exception occurred!"); throw new UserFriendlyException("Exception occurred!");
} }
} }
} }

130
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs

@ -1,65 +1,65 @@
using System; using System;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using NSubstitute; using NSubstitute;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Xunit; using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Auditing namespace Volo.Abp.AspNetCore.Mvc.Auditing
{ {
public class AuditTestController_Tests : AspNetCoreMvcTestBase public class AuditTestController_Tests : AspNetCoreMvcTestBase
{ {
private readonly AbpAuditingOptions _options; private readonly AbpAuditingOptions _options;
private IAuditingStore _auditingStore; private IAuditingStore _auditingStore;
public AuditTestController_Tests() public AuditTestController_Tests()
{ {
_options = ServiceProvider.GetRequiredService<IOptions<AbpAuditingOptions>>().Value; _options = ServiceProvider.GetRequiredService<IOptions<AbpAuditingOptions>>().Value;
_auditingStore = ServiceProvider.GetRequiredService<IAuditingStore>(); _auditingStore = ServiceProvider.GetRequiredService<IAuditingStore>();
} }
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{ {
_auditingStore = Substitute.For<IAuditingStore>(); _auditingStore = Substitute.For<IAuditingStore>();
services.Replace(ServiceDescriptor.Singleton(_auditingStore)); services.Replace(ServiceDescriptor.Singleton(_auditingStore));
base.ConfigureServices(context, services); base.ConfigureServices(context, services);
} }
[Fact] [Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Success_For_GetRequests() public async Task Should_Trigger_Middleware_And_AuditLog_Success_For_GetRequests()
{ {
_options.IsEnabledForGetRequests = true; _options.IsEnabledForGetRequests = true;
_options.AlwaysLogOnException = false; _options.AlwaysLogOnException = false;
await GetResponseAsync("api/audit-test/audit-success"); await GetResponseAsync("api/audit-test/audit-success");
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>()); await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
} }
[Fact] [Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Exception_Always() public async Task Should_Trigger_Middleware_And_AuditLog_Exception_Always()
{ {
_options.IsEnabled = true; _options.IsEnabled = true;
_options.AlwaysLogOnException = true; _options.AlwaysLogOnException = true;
try try
{ {
await GetResponseAsync("api/audit-test/audit-fail", System.Net.HttpStatusCode.Forbidden); await GetResponseAsync("api/audit-test/audit-fail", System.Net.HttpStatusCode.Forbidden);
} }
catch { } catch { }
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>()); await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
} }
[Fact] [Fact]
public async Task Should_Trigger_Middleware_And_AuditLog_Exception_When_Returns_Object() public async Task Should_Trigger_Middleware_And_AuditLog_Exception_When_Returns_Object()
{ {
_options.IsEnabled = true; _options.IsEnabled = true;
_options.AlwaysLogOnException = true; _options.AlwaysLogOnException = true;
await GetResponseAsync("api/audit-test/audit-fail-object", System.Net.HttpStatusCode.Forbidden); await GetResponseAsync("api/audit-test/audit-fail-object", System.Net.HttpStatusCode.Forbidden);
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>()); await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
} }
} }
} }

25
modules/blogging/src/Volo.Blogging.Web/Pages/Blogs/BloggingPage.cs

@ -1,5 +1,7 @@
using System; using System;
using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using CommonMark; using CommonMark;
using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Localization; using Microsoft.AspNetCore.Mvc.Localization;
@ -30,30 +32,27 @@ namespace Volo.Blogging.Pages.Blog
public string GetShortContent(string content) //TODO: This should be moved to its own place! public string GetShortContent(string content) //TODO: This should be moved to its own place!
{ {
var openingTag = "<p>";
var closingTag = "</p>";
var html = RenderMarkdownToString(content); var html = RenderMarkdownToString(content);
if (string.IsNullOrWhiteSpace(html)) var plainText = Regex.Replace(html, "/<[^>]*>/g", "");
if (string.IsNullOrWhiteSpace(plainText))
{ {
return ""; return "";
} }
var splittedHtml = html.Split(closingTag);
if (splittedHtml.Length < 1) var firsParag = plainText.Split(Environment.NewLine).FirstOrDefault(s => !string.IsNullOrWhiteSpace(s));
if (firsParag == null)
{ {
return ""; return plainText;
} }
var firstHtmlPart = splittedHtml[0]; if (firsParag.Length <= MaxShortContentLength)
var paragraphStartIndex = firstHtmlPart.IndexOf(openingTag, StringComparison.Ordinal) + openingTag.Length;
if (firstHtmlPart.Length - paragraphStartIndex <= MaxShortContentLength)
{ {
return firstHtmlPart.Substring(paragraphStartIndex); return firsParag;
} }
return firstHtmlPart.Substring(paragraphStartIndex, MaxShortContentLength) + "..."; return firsParag.Substring(0, MaxShortContentLength) + "...";
} }
public IHtmlContent RenderMarkdownToHtml(string content) public IHtmlContent RenderMarkdownToHtml(string content)

8
modules/docs/src/Volo.Docs.Web/DocsWebModule.cs

@ -5,7 +5,9 @@ using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.Localization;
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.Prismjs; using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
@ -18,7 +20,11 @@ namespace Volo.Docs
{ {
[DependsOn( [DependsOn(
typeof(DocsHttpApiModule), typeof(DocsHttpApiModule),
typeof(AbpAspNetCoreMvcUiBootstrapModule) typeof(AbpAutoMapperModule),
typeof(AbpAspNetCoreMvcUiBootstrapModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule),
typeof(AbpAspNetCoreMvcUiPackagesModule),
typeof(AbpAspNetCoreMvcUiBundlingModule)
)] )]
public class DocsWebModule : AbpModule public class DocsWebModule : AbpModule
{ {

436
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml

@ -5,6 +5,7 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Clipboard @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Clipboard
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar @using Volo.Abp.AspNetCore.Mvc.UI.Packages.MalihuCustomScrollbar
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Popper @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Popper
@using Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs @using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs
@using Volo.Abp.AspNetCore.Mvc.UI.Theming @using Volo.Abp.AspNetCore.Mvc.UI.Theming
@using Volo.Docs @using Volo.Docs
@ -39,269 +40,284 @@
<abp-script src="/Pages/Documents/Project/index.js" /> <abp-script src="/Pages/Documents/Project/index.js" />
</abp-script-bundle> </abp-script-bundle>
} }
<div class="docs-page" data-spy="scroll" data-target="#docs-sticky-index"> @if (Model.DocumentFound)
<div class="row justify-content-end"> {
<div class="col-md-3 docs-sidebar dark-sidebar"> <div class="docs-page" data-spy="scroll" data-target="#docs-sticky-index">
<div class="docs-sidebar-wrapper"> <div class="row justify-content-end">
<div class="col-md-3 docs-sidebar dark-sidebar">
<div class="docs-top"> <div class="docs-sidebar-wrapper">
<nav class="navbar navbar-logo">
@if (!Model.Project.Name.IsNullOrWhiteSpace()) <div class="docs-top">
{ <nav class="navbar navbar-logo">
<a class="navbar-brand w-100" href="@Model.CreateVersionLink(Model.LatestVersionInfo, Model.GetSpecificVersionOrLatest())"> @if (!Model.Project.Name.IsNullOrWhiteSpace())
<span id="ProjectName">@Model.Project.Name</span><br> {
<strong class="display-block"> <a class="navbar-brand w-100" href="@Model.CreateVersionLink(Model.LatestVersionInfo, Model.GetSpecificVersionOrLatest())">
@L["Documents"] <span id="ProjectName">@Model.Project.Name</span><br>
</strong> <strong class="display-block">
</a> @L["Documents"]
} </strong>
</a>
}
@if (!Model.Document.Project.MainWebsiteUrl.IsNullOrWhiteSpace()) @if (!Model.Document.Project.MainWebsiteUrl.IsNullOrWhiteSpace())
{ {
<a href="@Model.Document.Project.MainWebsiteUrl" class="go-back-site" id="GoToMainWebSite"> <a href="@Model.Document.Project.MainWebsiteUrl" class="go-back-site" id="GoToMainWebSite">
<i class="fa fa-chevron-left"></i> <i class="fa fa-chevron-left"></i>
@L["BackToWebsite"] @L["BackToWebsite"]
</a> </a>
} }
<div class="for-mobile"> <div class="for-mobile">
<div class="navbar-light"> <div class="navbar-light">
<button type="button" class="open-dmenu navbar-toggler" aria-label="Close"> <button type="button" class="open-dmenu navbar-toggler" aria-label="Close">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
</div>
</div> </div>
</div> </nav>
</nav> </div>
</div>
<div class="docs-tree-list"> <div class="docs-tree-list">
@if (Model.ShowProjectsCombobox && Model.ProjectSelectItems.Count > 1) @if (Model.ShowProjectsCombobox && Model.ProjectSelectItems.Count > 1)
{ {
<div class="docs-version"> <div class="docs-version">
<div class="version-select"> <div class="version-select">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<label class="input-group-text"> <label class="input-group-text">
<i class="fa fa-folder-open" aria-hidden="true" data-toggle="tooltip" title="@L["Project"]"></i> <i class="fa fa-folder-open" aria-hidden="true" data-toggle="tooltip" title="@L["Project"]"></i>
</label> </label>
</div> </div>
<select asp-items="Model.ProjectSelectItems" class="form-control" onchange="window.location.pathname = this.value"></select> <select asp-items="Model.ProjectSelectItems" class="form-control" onchange="window.location.pathname = this.value"></select>
</div>
</div> </div>
</div> </div>
</div> }
}
<div class="row"> <div class="row">
@if (Model.VersionSelectItems.Any()) @if (Model.VersionSelectItems.Any())
{ {
<div class="col @(Model.LanguageSelectListItems.Count > 1?"pr-0":"")"> <div class="col @(Model.LanguageSelectListItems.Count > 1?"pr-0":"")">
<div class="docs-version @(Model.LanguageSelectListItems.Count > 1?"pr-1":"")"> <div class="docs-version @(Model.LanguageSelectListItems.Count > 1?"pr-1":"")">
<div class="version-select"> <div class="version-select">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<label class="input-group-text"> <label class="input-group-text">
<i class="fa fa-check-square-o" aria-hidden="true" data-toggle="tooltip" title="@L["Version"]"></i> <i class="fa fa-check-square-o" aria-hidden="true" data-toggle="tooltip" title="@L["Version"]"></i>
</label> </label>
</div> </div>
<select asp-items="Model.VersionSelectItems" class="form-control" onchange="if (this.value) { window.location.replace(this.value) }"></select> <select asp-items="Model.VersionSelectItems" class="form-control" onchange="if (this.value) { window.location.replace(this.value) }"></select>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> }
}
@if (Model.LanguageSelectListItems.Count > 1) @if (Model.LanguageSelectListItems.Count > 1)
{ {
<div class="col @(Model.VersionSelectItems.Any()?"pl-0":"")"> <div class="col @(Model.VersionSelectItems.Any()?"pl-0":"")">
<div class="docs-version docs-language @(Model.VersionSelectItems.Any()?"pl-1":"")"> <div class="docs-version docs-language @(Model.VersionSelectItems.Any()?"pl-1":"")">
<div class="version-select"> <div class="version-select">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<label class="input-group-text"> <label class="input-group-text">
<i class="fa fa-globe" aria-hidden="true" data-toggle="tooltip" title="@L["Language"]"></i> <i class="fa fa-globe" aria-hidden="true" data-toggle="tooltip" title="@L["Language"]"></i>
</label> </label>
</div>
<select asp-items="Model.LanguageSelectListItems" class="form-control" onchange="window.location.replace(this.value)"></select>
</div> </div>
<select asp-items="Model.LanguageSelectListItems" class="form-control" onchange="window.location.replace(this.value)"></select>
</div> </div>
</div> </div>
</div> </div>
</div> }
} </div>
</div>
<div class="docs-version mb-4"> <div class="docs-version mb-4">
<div class="version-select"> <div class="version-select">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<label class="input-group-text"><i class="fa fa-filter"></i></label> <label class="input-group-text"><i class="fa fa-filter"></i></label>
</div> </div>
<input class="form-control" type="search" placeholder="@L["FilterTopics"].Value" aria-label="Filter"> <input class="form-control" type="search" placeholder="@L["FilterTopics"].Value" aria-label="Filter">
</div>
</div> </div>
</div> </div>
</div>
@if (Model.Navigation == null || !Model.Navigation.HasChildItems) @if (Model.Navigation == null || !Model.Navigation.HasChildItems)
{
<div class="text-muted p-3">
<i class="fa fa-warning"></i> @L["NavigationDocumentNotFound"]
</div>
}
else
{
<ul root-node="@Model.Navigation"
version="@(Model.LatestVersionInfo == null || Model.LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Model.Version)"
project-name="@Model.ProjectName"
project-format="@Model.Project.Format"
selected-document-name="@Model.DocumentNameWithExtension"
language="@Model.LanguageCode"
id="sidebar-scroll"
class="nav nav-list"></ul>
}
</div>
</div>
</div>
@if (Model.Document != null)
{
<div class="col-md-7 docs-content bg-white">
<div class="docs-link-btns">
<div class="float-left">
@(L["ShareOn"].Value + " :")
<a href="#" target="_blank" class="share-button twitter" id="TwitterShareLink" title="Twitter">
<i class="fa fa-twitter"></i>
</a>
<a href="#" target="_blank" class="share-button linkedin" id="LinkedinShareLink" title="LinkedIn">
<i class="fa fa-linkedin"></i>
</a>
<a href="#" target="_blank" class="share-button email" id="EmailShareLink" title="E-mail">
<i class="fa fa-envelope-square"></i>
</a>
</div>
<div class="float-right">
@if (!string.IsNullOrEmpty(Model.Document.EditLink))
{ {
<a href="@Model.Document.EditLink" target="_blank"> <i class="fa fa-edit"></i> @(L["Edit"]) (@L["LastEditTime"]: @Model.Document.LastUpdatedTime.ToShortDateString())</a> <div class="text-muted p-3">
<i class="fa fa-warning"></i> @L["NavigationDocumentNotFound"]
</div>
} }
</div> else
<div class="float-right mr-3">
@if (Model.Document.Contributors != null && Model.Document.Contributors.Count > 0)
{ {
@(L["Contributors"].Value + " :") <ul root-node="@Model.Navigation"
@foreach (var contributor in Model.Document.Contributors) version="@(Model.LatestVersionInfo == null || Model.LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Model.Version)"
{ project-name="@Model.ProjectName"
<a href="@contributor.UserProfileUrl" target="_blank"> project-format="@Model.Project.Format"
<img src="@contributor.AvatarUrl" selected-document-name="@Model.DocumentNameWithExtension"
class="rounded-circle" height="21" width="21" title="@contributor.Username" /> language="@Model.LanguageCode"
</a> id="sidebar-scroll"
} class="nav nav-list"></ul>
} }
</div> </div>
</div> </div>
</div>
@if (Model.Document != null)
{
<div class="col-md-7 docs-content bg-white">
<div class="docs-link-btns">
<div class="float-left">
@(L["ShareOn"].Value + " :")
<a href="#" target="_blank" class="share-button twitter" id="TwitterShareLink" title="Twitter">
<i class="fa fa-twitter"></i>
</a>
<a href="#" target="_blank" class="share-button linkedin" id="LinkedinShareLink" title="LinkedIn">
<i class="fa fa-linkedin"></i>
</a>
<a href="#" target="_blank" class="share-button email" id="EmailShareLink" title="E-mail">
<i class="fa fa-envelope-square"></i>
</a>
</div>
<div class="docs-content-field"> <div class="float-right">
<div class="docs-text-field"> @if (!string.IsNullOrEmpty(Model.Document.EditLink))
<div class="position-relative">
@if (Model.DocumentPreferences != null && Model.DocumentPreferences.Parameters != null && Model.DocumentPreferences.Parameters.Any())
{ {
<div class="alert alert-primary alert-criteria"> <a href="@Model.Document.EditLink" target="_blank"> <i class="fa fa-edit"></i> @(L["Edit"]) (@L["LastEditTime"]: @Model.Document.LastUpdatedTime.ToShortDateString())</a>
<abp-row>
<abp-column>
<p class="alert-p mb-2">
<i class="fa fa-info-circle"></i>
@L["MultipleVersionDocumentInfo"]
</p>
</abp-column>
</abp-row>
<abp-form-row>
@foreach (var parameter in Model.DocumentPreferences.Parameters)
{
<abp-column size="_4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="@("Section" + parameter.Name + "ComboboxAddonId")">@(parameter.DisplayName)</span>
</div>
<select class="doc-section-combobox form-control"
aria-describedby="@("Section" + parameter.Name + "ComboboxAddonId")"
id="@("Section" + parameter.Name + "ComboboxId")" data-key="@parameter.Name">
@foreach (var value in parameter.Values)
{
@if (value.Key == (Model.UserPreferences.ContainsKey(parameter.Name) ? Model.UserPreferences[parameter.Name] : null))
{
<option value="@value.Key" selected="selected">@value.Value</option>
}
else
{
<option value="@value.Key">@value.Value</option>
}
}
</select>
</div>
</abp-column>
}
</abp-form-row>
</div>
} }
</div> </div>
<div data-spy="scroll" data-target="#docs-sticky-index" data-offset="0"> <div class="float-right mr-3">
<article class="docs-body"> @if (Model.Document.Contributors != null && Model.Document.Contributors.Count > 0)
{
@(L["Contributors"].Value + " :")
@foreach (var contributor in Model.Document.Contributors)
{
<a href="@contributor.UserProfileUrl" target="_blank">
<img src="@contributor.AvatarUrl"
class="rounded-circle" height="21" width="21" title="@contributor.Username" />
</a>
}
}
</div>
@if (Model.DocumentLanguageIsDifferent) </div>
<div class="docs-content-field">
<div class="docs-text-field">
<div class="position-relative">
@if (Model.DocumentPreferences != null && Model.DocumentPreferences.Parameters != null && Model.DocumentPreferences.Parameters.Any())
{ {
<abp-alert alert-type="Warning" dismissible="true" class="mb-0"> <div class="alert alert-primary alert-criteria">
@L["DocumentNotFoundInSelectedLanguage"] <abp-row>
</abp-alert> <abp-column>
<p class="alert-p mb-2">
<i class="fa fa-info-circle"></i>
@L["MultipleVersionDocumentInfo"]
</p>
</abp-column>
</abp-row>
<abp-form-row>
@foreach (var parameter in Model.DocumentPreferences.Parameters)
{
<abp-column size="_4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="@("Section" + parameter.Name + "ComboboxAddonId")">@(parameter.DisplayName)</span>
</div>
<select class="doc-section-combobox form-control"
aria-describedby="@("Section" + parameter.Name + "ComboboxAddonId")"
id="@("Section" + parameter.Name + "ComboboxId")" data-key="@parameter.Name">
@foreach (var value in parameter.Values)
{
@if (value.Key == (Model.UserPreferences.ContainsKey(parameter.Name) ? Model.UserPreferences[parameter.Name] : null))
{
<option value="@value.Key" selected="selected">@value.Value</option>
}
else
{
<option value="@value.Key">@value.Value</option>
}
}
</select>
</div>
</abp-column>
}
</abp-form-row>
</div>
} }
@Html.Raw(Model.Document.Content) </div>
</article>
<div data-spy="scroll" data-target="#docs-sticky-index" data-offset="0">
<article class="docs-body">
<div id="crawler_link" style="display:none;"> @if (Model.DocumentLanguageIsDifferent)
{
<abp-alert alert-type="Warning" dismissible="true" class="mb-0">
@L["DocumentNotFoundInSelectedLanguage"]
</abp-alert>
}
@Html.Raw(Model.Document.Content)
</article>
<div id="crawler_link" style="display:none;">
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="col-md-2 docs-page-index position-relative bg-light"> <div class="col-md-2 docs-page-index position-relative bg-light">
<div id="scroll-index" class="docs-inner-anchors mt-2"> <div id="scroll-index" class="docs-inner-anchors mt-2">
<h5>@L["InThisDocument"]</h5> <h5>@L["InThisDocument"]</h5>
<nav id="docs-sticky-index" class="navbar index-scroll"> <nav id="docs-sticky-index" class="navbar index-scroll">
</nav> </nav>
<div class="row"> <div class="row">
<div class="col p-0 py-3"> <div class="col p-0 py-3">
<a href="javascript:;" class="scroll-top-btn"><i class="fa fa-chevron-up"></i> @L["GoToTop"]</a> <a href="javascript:;" class="scroll-top-btn"><i class="fa fa-chevron-up"></i> @L["GoToTop"]</a>
</div>
</div> </div>
</div>
</div>
</div> </div>
</div>
} }
else else
{ {
<div class="col-md-9 p-5 bg-white"> <div class="col-md-9 p-5 bg-white">
<p>@L["DocumentNotFound"]</p> <p>@L["DocumentNotFound"]</p>
<a href="/"> <a href="/">
<i class="fa fa-chevron-left"></i> <i class="fa fa-chevron-left"></i>
@L["BackToWebsite"] @L["BackToWebsite"]
</a> </a>
</div> </div>
} }
</div>
</div> </div>
</div> }
else
{
@(await Component.InvokeAsync<DocumentNotFoundViewComponent>(new
{
model = new DocumentNotFoundPageModel
{
ProjectName = Model.ProjectName,
DocumentName = Model.DocumentName,
LanguageCode = Model.LanguageCode,
Version = Model.Version,
}
}))
}

17
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs

@ -33,6 +33,8 @@ namespace Volo.Docs.Pages.Documents.Project
[BindProperty(SupportsGet = true)] [BindProperty(SupportsGet = true)]
public string LanguageCode { get; set; } public string LanguageCode { get; set; }
public bool DocumentFound { get; set; } = true;
public string DefaultLanguageCode { get; set; } public string DefaultLanguageCode { get; set; }
public ProjectDto Project { get; set; } public ProjectDto Project { get; set; }
@ -86,6 +88,21 @@ namespace Volo.Docs.Pages.Documents.Project
} }
public async Task<IActionResult> OnGetAsync() public async Task<IActionResult> OnGetAsync()
{
try
{
return await SetPageAsync();
}
catch (DocumentNotFoundException exception)
{
Logger.LogWarning(exception.Message);
DocumentFound = false;
return Page();
}
}
private async Task<IActionResult> SetPageAsync()
{ {
DocumentsUrlPrefix = _uiOptions.RoutePrefix; DocumentsUrlPrefix = _uiOptions.RoutePrefix;
ShowProjectsCombobox = _uiOptions.ShowProjectsCombobox; ShowProjectsCombobox = _uiOptions.ShowProjectsCombobox;

53
modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/DocumentNotFoundComponent/Default.cshtml

@ -0,0 +1,53 @@
@using Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
@model DocumentNotFoundPageModel
@{
}
<div class="row position-relative vh-100" style="background: #e8e8e8;">
<div class="center">
<span class="notfound-404">404</span>
<h1>
<strong>"@Model.DocumentName"</strong> not found in <strong>@Model.ProjectName</strong> documents, with <strong>@Model.Version</strong> version and <strong>@Model.LanguageCode</strong> language.
</h1>
<br />
<a href="@(Model.DocumentsUrlPrefix + Model.LanguageCode + "/" +Model.ProjectName + "/" + Model.Version)" class="btn btn-primary px-4">
Go Back
</a>
</div>
</div>
<style>
h1 {
font-size: 1.75em;
line-height: 1.75;
color: #777;
font-weight: normal;
}
h1 strong {
color: #222;
}
.center {
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;
}
.notfound-404 {
font-size: 300px;
font-weight: 700;
line-height: 1.25;
margin: 0px;
color: #fff;
text-transform: uppercase;
display: block;
margin-bottom: -150px;
z-index: -1;
position: relative;
}
</style>

15
modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/DocumentNotFoundComponent/DocumentNotFoundPageModel.cs

@ -0,0 +1,15 @@
namespace Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
{
public class DocumentNotFoundPageModel
{
public string ProjectName { get; set; }
public string LanguageCode { get; set; }
public string Version { get; set; }
public string DocumentName { get; set; }
public string DocumentsUrlPrefix { get; set; }
}
}

26
modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/DocumentNotFoundComponent/DocumentNotFoundViewComponent.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc;
namespace Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
{
public class DocumentNotFoundViewComponent : AbpViewComponent
{
private readonly DocsUiOptions _options;
public DocumentNotFoundViewComponent(IOptions<DocsUiOptions> options)
{
_options = options.Value;
}
public IViewComponentResult Invoke(DocumentNotFoundPageModel model, string defaultErrorMessageKey)
{
model.DocumentsUrlPrefix = _options.RoutePrefix;
return View("~/Pages/Documents/Shared/DocumentNotFoundComponent/Default.cshtml", model);
}
}
}

1
modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj

@ -18,6 +18,7 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bundling\Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bundling\Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Packages\Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Packages\Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />
<ProjectReference Include="..\Volo.Docs.HttpApi\Volo.Docs.HttpApi.csproj" /> <ProjectReference Include="..\Volo.Docs.HttpApi\Volo.Docs.HttpApi.csproj" />
<PackageReference Include="Markdig.Signed" Version="0.18.0" /> <PackageReference Include="Markdig.Signed" Version="0.18.0" />
<PackageReference Include="Scriban" Version="2.1.1" /> <PackageReference Include="Scriban" Version="2.1.1" />

18
npm/packs/jquery/src/abp.jquery.js

@ -359,13 +359,17 @@
var _loadScript = function (url, loadCallback, failCallback) { var _loadScript = function (url, loadCallback, failCallback) {
_loadFromUrl(url, loadCallback, failCallback, function (urlInfo) { _loadFromUrl(url, loadCallback, failCallback, function (urlInfo) {
$.getScript(url) $.get({
.done(function () { url: url,
urlInfo.succeed(); dataType: 'text'
}) })
.fail(function () { .done(function (script) {
urlInfo.failed(); $.globalEval(script);
}); urlInfo.succeed();
})
.fail(function () {
urlInfo.failed();
});
}); });
}; };

1
samples/MicroserviceDemo/applications/AuthServer.Host/AuthServer.Host.csproj

@ -29,6 +29,7 @@
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj" /> <ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\identityserver\src\Volo.Abp.IdentityServer.EntityFrameworkCore\Volo.Abp.IdentityServer.EntityFrameworkCore.csproj" /> <ProjectReference Include="..\..\..\..\modules\identityserver\src\Volo.Abp.IdentityServer.EntityFrameworkCore\Volo.Abp.IdentityServer.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web.IdentityServer\Volo.Abp.Account.Web.IdentityServer.csproj" /> <ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Web.IdentityServer\Volo.Abp.Account.Web.IdentityServer.csproj" />
<ProjectReference Include="..\..\..\..\modules\account\src\Volo.Abp.Account.Application\Volo.Abp.Account.Application.csproj" />
<ProjectReference Include="..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.EntityFrameworkCore\Volo.Abp.AuditLogging.EntityFrameworkCore.csproj" /> <ProjectReference Include="..\..\..\..\modules\audit-logging\src\Volo.Abp.AuditLogging.EntityFrameworkCore\Volo.Abp.AuditLogging.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.EntityFrameworkCore\Volo.Abp.PermissionManagement.EntityFrameworkCore.csproj" /> <ProjectReference Include="..\..\..\..\modules\permission-management\src\Volo.Abp.PermissionManagement.EntityFrameworkCore\Volo.Abp.PermissionManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.EntityFrameworkCore\Volo.Abp.SettingManagement.EntityFrameworkCore.csproj" /> <ProjectReference Include="..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.EntityFrameworkCore\Volo.Abp.SettingManagement.EntityFrameworkCore.csproj" />

4
samples/MicroserviceDemo/applications/AuthServer.Host/AuthServerHostModule.cs

@ -1,9 +1,10 @@
using AuthServer.Host.EntityFrameworkCore; using AuthServer.Host.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis; using StackExchange.Redis;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web; using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
@ -34,6 +35,7 @@ namespace AuthServer.Host
typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpIdentityEntityFrameworkCoreModule), typeof(AbpIdentityEntityFrameworkCoreModule),
typeof(AbpIdentityApplicationContractsModule), typeof(AbpIdentityApplicationContractsModule),
typeof(AbpAccountApplicationModule),
typeof(AbpIdentityServerEntityFrameworkCoreModule), typeof(AbpIdentityServerEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreSqlServerModule), typeof(AbpEntityFrameworkCoreSqlServerModule),
typeof(AbpAccountWebIdentityServerModule), typeof(AbpAccountWebIdentityServerModule),

Loading…
Cancel
Save