@MultiTenancyStringLocalizer["Tenant"]:
@@ -73,5 +80,6 @@
@await RenderSectionAsync("scripts", false)
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Account)
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml
index b189bf8e40..db8f8e1a6b 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Application.cshtml
@@ -1,9 +1,11 @@
@using Volo.Abp.AspNetCore.Mvc.AntiForgery
+@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@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.PageAlerts
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components
+@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@inject IAbpAntiForgeryManager AbpAntiForgeryManager
@inject IBrandingProvider BrandingProvider
@inject IPageLayout PageLayout
@@ -29,6 +31,8 @@
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Application)
+
@@ -38,8 +42,11 @@
@await RenderSectionAsync("styles", false)
+
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Application)
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Application)
@(await Component.InvokeAsync
())
@@ -58,5 +65,6 @@
@await RenderSectionAsync("scripts", false)
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Application)
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml
index 59fd80ea1d..da7c119de4 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Layouts/Empty.cshtml
@@ -1,8 +1,10 @@
@using Volo.Abp.AspNetCore.Mvc.AntiForgery
+@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling
@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.Theming
@inject IAbpAntiForgeryManager AbpAntiForgeryManager
@inject IBrandingProvider BrandingProvider
@inject IPageLayout PageLayout
@@ -28,6 +30,8 @@
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Empty)
+
@@ -37,8 +41,11 @@
@await RenderSectionAsync("styles", false)
+
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Empty)
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Empty)
@(await Component.InvokeAsync
())
@@ -52,5 +59,6 @@
@await RenderSectionAsync("scripts", false)
+ @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Empty)
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
index 9911b60b5c..34367260f9 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo.Abp.AspNetCore.Mvc.UI.csproj
@@ -10,6 +10,11 @@
+
+
+
+
+
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/AbpAspNetCoreMvcUiModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/AbpAspNetCoreMvcUiModule.cs
index cafc4c87fc..60a142bda5 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/AbpAspNetCoreMvcUiModule.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/AbpAspNetCoreMvcUiModule.cs
@@ -1,5 +1,6 @@
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
+using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.Mvc.UI
{
@@ -7,6 +8,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI
[DependsOn(typeof(AbpUiNavigationModule))]
public class AbpAspNetCoreMvcUiModule : AbpModule
{
-
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+ }
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml
new file mode 100644
index 0000000000..61e9afbf6e
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml
@@ -0,0 +1,9 @@
+@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
+@model LayoutHookViewModel
+@if (Model.Hooks.Any())
+{
+ foreach (var hook in Model.Hooks)
+ {
+ @await Component.InvokeAsync(hook.ComponentType, new { layout = Model.Layout })
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs
new file mode 100644
index 0000000000..7828ba6536
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookInfo.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
+{
+ public class LayoutHookInfo
+ {
+ ///
+ /// ViewComponent type.
+ ///
+ public Type ComponentType { get; }
+
+ ///
+ /// Specifies the layout name to apply this hook.
+ /// null indicates that this hook will be applied to all layouts.
+ ///
+ public string Layout { get; }
+
+ public LayoutHookInfo(Type componentType, string layout = null)
+ {
+ ComponentType = componentType;
+ Layout = layout;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookOptions.cs
new file mode 100644
index 0000000000..e51f491f64
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookOptions.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+
+namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
+{
+ public class LayoutHookOptions
+ {
+ public IDictionary> Hooks { get; }
+
+ public LayoutHookOptions()
+ {
+ Hooks = new Dictionary>();
+ }
+
+ public LayoutHookOptions Add(string name, Type componentType, string layout = null)
+ {
+ Hooks
+ .GetOrAdd(name, () => new List())
+ .Add(new LayoutHookInfo(componentType, layout));
+
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs
new file mode 100644
index 0000000000..85527037a8
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewComponent.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+
+namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
+{
+ public class LayoutHookViewComponent : AbpViewComponent
+ {
+ protected LayoutHookOptions Options { get; }
+
+ public LayoutHookViewComponent(IOptions options)
+ {
+ Options = options.Value;
+ }
+
+ public virtual IViewComponentResult Invoke(string name, string layout)
+ {
+ var hooks = Options.Hooks.GetOrDefault(name)?.ToArray() ?? Array.Empty();
+
+ return View(
+ "~/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/Default.cshtml",
+ new LayoutHookViewModel(hooks, layout)
+ );
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs
new file mode 100644
index 0000000000..3e71c5cd2d
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHookViewModel.cs
@@ -0,0 +1,15 @@
+namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
+{
+ public class LayoutHookViewModel
+ {
+ public LayoutHookInfo[] Hooks { get; }
+
+ public string Layout { get; }
+
+ public LayoutHookViewModel(LayoutHookInfo[] hooks, string layout)
+ {
+ Hooks = hooks;
+ Layout = layout;
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs
new file mode 100644
index 0000000000..ab3ef8e903
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/LayoutHooks.cs
@@ -0,0 +1,17 @@
+namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
+{
+ public static class LayoutHooks
+ {
+ public static class Head
+ {
+ public const string First = "Header.First";
+ public const string Last = "Header.Last";
+ }
+
+ public static class Body
+ {
+ public const string First = "Body.First";
+ public const string Last = "Body.Last";
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/ViewComponentHelperLayoutHookExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/ViewComponentHelperLayoutHookExtensions.cs
new file mode 100644
index 0000000000..99b6596401
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Components/LayoutHook/ViewComponentHelperLayoutHookExtensions.cs
@@ -0,0 +1,24 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Html;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
+{
+ public static class ViewComponentHelperLayoutHookExtensions
+ {
+ public static Task InvokeLayoutHookAsync(
+ this IViewComponentHelper componentHelper,
+ string name,
+ string layout)
+ {
+ return componentHelper.InvokeAsync(
+ typeof(LayoutHookViewComponent),
+ new
+ {
+ name = name,
+ layout = layout
+ }
+ );
+ }
+ }
+}