@ -0,0 +1,8 @@ |
|||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; |
||||
|
|
||||
|
public class PersistentAccessToken |
||||
|
{ |
||||
|
public const string Key = "access_token"; |
||||
|
|
||||
|
public string? AccessToken { get; set; } |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Components; |
||||
|
using Volo.Abp.Http.Client.Authentication; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; |
||||
|
|
||||
|
public class PersistentComponentStateAbpAccessTokenProvider : IAbpAccessTokenProvider |
||||
|
{ |
||||
|
private string? AccessToken { get; set; } |
||||
|
|
||||
|
private readonly PersistentComponentState _persistentComponentState; |
||||
|
|
||||
|
public PersistentComponentStateAbpAccessTokenProvider(PersistentComponentState persistentComponentState) |
||||
|
{ |
||||
|
_persistentComponentState = persistentComponentState; |
||||
|
AccessToken = null; |
||||
|
} |
||||
|
|
||||
|
public virtual Task<string?> GetTokenAsync() |
||||
|
{ |
||||
|
if (AccessToken != null) |
||||
|
{ |
||||
|
return Task.FromResult<string?>(AccessToken); |
||||
|
} |
||||
|
|
||||
|
AccessToken = _persistentComponentState.TryTakeFromJson<PersistentAccessToken>(PersistentAccessToken.Key, out var token) |
||||
|
? token?.AccessToken |
||||
|
: null; |
||||
|
|
||||
|
return Task.FromResult(AccessToken); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using MyCompanyName.MyProjectName.MultiTenancy; |
||||
|
using Volo.Abp.Account.Localization; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Identity.Blazor; |
||||
|
using Volo.Abp.SettingManagement.Blazor.Menus; |
||||
|
using Volo.Abp.TenantManagement.Blazor.Navigation; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client.Menus; |
||||
|
|
||||
|
public class MyProjectNameMenuContributor : IMenuContributor |
||||
|
{ |
||||
|
private readonly IConfiguration _configuration; |
||||
|
|
||||
|
public MyProjectNameMenuContributor(IConfiguration configuration) |
||||
|
{ |
||||
|
_configuration = configuration; |
||||
|
} |
||||
|
|
||||
|
public async Task ConfigureMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
if (context.Menu.Name == StandardMenus.Main) |
||||
|
{ |
||||
|
await ConfigureMainMenuAsync(context); |
||||
|
} |
||||
|
else if (context.Menu.Name == StandardMenus.User) |
||||
|
{ |
||||
|
await ConfigureUserMenuAsync(context); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private Task ConfigureMainMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
var l = context.GetLocalizer<MyProjectNameResource>(); |
||||
|
|
||||
|
context.Menu.Items.Insert( |
||||
|
0, |
||||
|
new ApplicationMenuItem( |
||||
|
MyProjectNameMenus.Home, |
||||
|
l["Menu:Home"], |
||||
|
"/", |
||||
|
icon: "fas fa-home" |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
var administration = context.Menu.GetAdministration(); |
||||
|
|
||||
|
if (MultiTenancyConsts.IsEnabled) |
||||
|
{ |
||||
|
administration.SetSubItemOrder(TenantManagementMenuNames.GroupName, 1); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); |
||||
|
} |
||||
|
|
||||
|
administration.SetSubItemOrder(IdentityMenuNames.GroupName, 2); |
||||
|
administration.SetSubItemOrder(SettingManagementMenus.GroupName, 3); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
private Task ConfigureUserMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
var accountStringLocalizer = context.GetLocalizer<AccountResource>(); |
||||
|
|
||||
|
var authServerUrl = _configuration["AuthServer:Authority"] ?? ""; |
||||
|
|
||||
|
context.Menu.AddItem(new ApplicationMenuItem( |
||||
|
"Account.Manage", |
||||
|
accountStringLocalizer["MyAccount"], |
||||
|
$"{authServerUrl.EnsureEndsWith('/')}Account/Manage?returnUrl={_configuration["App:SelfUrl"]}", |
||||
|
icon: "fa fa-cog", |
||||
|
order: 1000, |
||||
|
null).RequireAuthenticated()); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client.Menus; |
||||
|
|
||||
|
public class MyProjectNameMenus |
||||
|
{ |
||||
|
private const string Prefix = "MyProjectName"; |
||||
|
public const string Home = Prefix + ".Home"; |
||||
|
|
||||
|
//Add your menu items here...
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData> |
||||
|
<!-- <TEMPLATE-REMOVE IF-NOT='PWA'> --> |
||||
|
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest> |
||||
|
<!-- </TEMPLATE-REMOVE> --> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Blazorise.Bootstrap5" Version="1.4.1" /> |
||||
|
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.4.1" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.1" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.1" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<!-- <TEMPLATE-REMOVE> --> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Http.Client.IdentityModel.WebAssembly\Volo.Abp.Http.Client.IdentityModel.WebAssembly.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj" /> |
||||
|
<!-- </TEMPLATE-REMOVE> --> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme" Version="3.0.*-*" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac.WebAssembly\Volo.Abp.Autofac.WebAssembly.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.Blazor.WebAssembly\Volo.Abp.Identity.Blazor.WebAssembly.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Blazor.WebAssembly\Volo.Abp.TenantManagement.Blazor.WebAssembly.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Blazor.WebAssembly\Volo.Abp.SettingManagement.Blazor.WebAssembly.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\MyCompanyName.MyProjectName.HttpApi.Client\MyCompanyName.MyProjectName.HttpApi.Client.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<!-- <TEMPLATE-REMOVE IF-NOT='PWA'> --> |
||||
|
<ItemGroup> |
||||
|
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" /> |
||||
|
</ItemGroup> |
||||
|
<!-- </TEMPLATE-REMOVE> --> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,11 @@ |
|||||
|
using AutoMapper; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client; |
||||
|
|
||||
|
public class MyProjectNameBlazorAutoMapperProfile : Profile |
||||
|
{ |
||||
|
public MyProjectNameBlazorAutoMapperProfile() |
||||
|
{ |
||||
|
//Define your AutoMapper configuration here for the Blazor project.
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,92 @@ |
|||||
|
using System; |
||||
|
using System.Net.Http; |
||||
|
using Blazorise.Bootstrap5; |
||||
|
using Blazorise.Icons.FontAwesome; |
||||
|
using Microsoft.AspNetCore.Components.Authorization; |
||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; |
||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client.Menus; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing; |
||||
|
using Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXLiteTheme; |
||||
|
using Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; |
||||
|
using Volo.Abp.Autofac.WebAssembly; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
using Volo.Abp.Http.Client.Authentication; |
||||
|
using Volo.Abp.Identity.Blazor.WebAssembly; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.SettingManagement.Blazor.WebAssembly; |
||||
|
using Volo.Abp.TenantManagement.Blazor.WebAssembly; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAutofacWebAssemblyModule), |
||||
|
typeof(MyProjectNameHttpApiClientModule), |
||||
|
typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXLiteThemeModule), |
||||
|
typeof(AbpIdentityBlazorWebAssemblyModule), |
||||
|
typeof(AbpTenantManagementBlazorWebAssemblyModule), |
||||
|
typeof(AbpSettingManagementBlazorWebAssemblyModule) |
||||
|
)] |
||||
|
public class MyProjectNameBlazorClientModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var environment = context.Services.GetSingletonInstance<IWebAssemblyHostEnvironment>(); |
||||
|
var builder = context.Services.GetSingletonInstance<WebAssemblyHostBuilder>(); |
||||
|
|
||||
|
ConfigureAuthentication(builder); |
||||
|
ConfigureHttpClient(context, environment); |
||||
|
ConfigureBlazorise(context); |
||||
|
ConfigureRouter(context); |
||||
|
ConfigureMenu(context); |
||||
|
ConfigureAutoMapper(context); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureRouter(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpRouterOptions>(options => |
||||
|
{ |
||||
|
options.AppAssembly = typeof(MyProjectNameBlazorClientModule).Assembly; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureMenu(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpNavigationOptions>(options => |
||||
|
{ |
||||
|
options.MenuContributors.Add(new MyProjectNameMenuContributor(context.Services.GetConfiguration())); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureBlazorise(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services |
||||
|
.AddBootstrap5Providers() |
||||
|
.AddFontAwesomeIcons(); |
||||
|
} |
||||
|
|
||||
|
private static void ConfigureAuthentication(WebAssemblyHostBuilder builder) |
||||
|
{ |
||||
|
builder.Services.TryAddScoped<SignOutSessionStateManager>(); |
||||
|
builder.Services.AddBlazorWebAppTieredServices(); |
||||
|
} |
||||
|
|
||||
|
private static void ConfigureHttpClient(ServiceConfigurationContext context, IWebAssemblyHostEnvironment environment) |
||||
|
{ |
||||
|
context.Services.AddTransient(sp => new HttpClient |
||||
|
{ |
||||
|
BaseAddress = new Uri(environment.BaseAddress) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureAutoMapper(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpAutoMapperOptions>(options => |
||||
|
{ |
||||
|
options.AddMaps<MyProjectNameBlazorClientModule>(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Ui.Branding; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client; |
||||
|
|
||||
|
[Dependency(ReplaceServices = true)] |
||||
|
public class MyProjectNameBrandingProvider : DefaultBrandingProvider |
||||
|
{ |
||||
|
public override string AppName => "MyProjectName"; |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using Volo.Abp.Bundling; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client; |
||||
|
|
||||
|
/* Add your global styles/scripts here. |
||||
|
* See https://docs.abp.io/en/abp/latest/UI/Blazor/Global-Scripts-Styles to learn how to use it
|
||||
|
*/ |
||||
|
public class MyProjectNameBundleContributor : IBundleContributor |
||||
|
{ |
||||
|
public void AddScripts(BundleContext context) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public void AddStyles(BundleContext context) |
||||
|
{ |
||||
|
context.Add("main.css", true); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using Volo.Abp.AspNetCore.Components; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client; |
||||
|
|
||||
|
public abstract class MyProjectNameComponentBase : AbpComponentBase |
||||
|
{ |
||||
|
protected MyProjectNameComponentBase() |
||||
|
{ |
||||
|
LocalizationResource = typeof(MyProjectNameResource); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,177 @@ |
|||||
|
@page "/" |
||||
|
@using Volo.Abp.MultiTenancy |
||||
|
@inherits MyProjectNameComponentBase |
||||
|
@inject AuthenticationStateProvider AuthenticationStateProvider |
||||
|
<div class="container"> |
||||
|
<div class="p-5 text-center"> |
||||
|
<Badge Color="Color.Success" class="mb-4"> |
||||
|
<h5 class="m-1"> <i class="fas fa-rocket"></i> Congratulations, <strong>MyProjectName</strong> is successfully running!</h5> |
||||
|
</Badge> |
||||
|
|
||||
|
<h1>Welcome to the Application</h1> |
||||
|
|
||||
|
<p class="lead px-lg-5 mx-lg-5">@L["LongWelcomeMessage"]</p> |
||||
|
|
||||
|
@if (!CurrentUser.IsAuthenticated) |
||||
|
{ |
||||
|
<a class="btn btn-primary" href="/Account/Login"><i class="fa fa-sign-in"></i> @L["Login"]</a> |
||||
|
} |
||||
|
</div> |
||||
|
|
||||
|
<div class="card"> |
||||
|
<div class="card-body"> |
||||
|
<div class="row"> |
||||
|
<div class="col-md-auto text-center"> |
||||
|
<img src="https://abp.io/assets/png/mastering-abp-framework.webp" style="max-width: 400px;" class="w-100 mb-5 my-md-3"> |
||||
|
</div> |
||||
|
<div class="col-md d-flex align-items-center"> |
||||
|
<div class="pe-0 pe-md-4"> |
||||
|
<small class="text-uppercase text-muted">THE OFFICIAL GUIDE</small> |
||||
|
<h2 class="mb-4">Mastering ABP Framework</h2> |
||||
|
<p class="mb-4">Written by the creator of the ABP Framework, this book will help you gain a complete understanding of the framework and modern web application development techniques.</p> |
||||
|
<div class="mb-4"> |
||||
|
<a href="https://www.amazon.com/gp/product/B097Z2DM8Q/ref=dbs_a_def_rwt_hsch_vapi_tkin_p1_i0" class="btn btn-success mb-1"> |
||||
|
Buy on Amazon US |
||||
|
</a> |
||||
|
<a href="https://www.packtpub.com/product/mastering-abp-framework/9781801079242" class="btn btn-primary mb-1"> |
||||
|
Buy on PACKT |
||||
|
</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="my-3 text-center"> |
||||
|
<h3>Let's improve your application!</h3> |
||||
|
<p>Here are some links to help you get started:</p> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card mt-4 mb-5"> |
||||
|
<div class="card-body"> |
||||
|
<div class="row text-center justify-content-md-center"> |
||||
|
<div class="col-lg-4"> |
||||
|
<div class="p-4"> |
||||
|
<h5 class="mb-3"><i class="fas fa-book text-secondary d-block my-3 fa-2x"></i> Learn the ABP Framework</h5> |
||||
|
<p>Explore the compherensive documentation to learn how to build a modern web application.</p> |
||||
|
<a href="https://docs.abp.io/en/abp/latest?ref=tmpl" target="_blank" class="btn btn-link px-1">See Documents <i class="fas fa-chevron-right"></i></a> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-4 border-start"> |
||||
|
<div class="p-4"> |
||||
|
<h5 class="mb-3"><i class="fas fa-cubes text-secondary d-block my-3 fa-2x"></i> Samples</h5> |
||||
|
<p>See the example projects built with the ABP Framework.</p> |
||||
|
<a href="https://docs.abp.io/en/abp/latest/Samples/Index?ref=tmpl" target="_blank" class="btn btn-link px-1">All samples <i class="fas fa-chevron-right"></i></a> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-4 border-start"> |
||||
|
<div class="p-4"> |
||||
|
<h5 class="mb-3"><i class="fas fa-users text-secondary d-block my-3 fa-2x"></i> ABP Community</h5> |
||||
|
<p>Get involved with a vibrant community and become a contributor.</p> |
||||
|
<a href="https://community.abp.io/" target="_blank" class="btn btn-link px-1">Community <i class="fas fa-chevron-right"></i></a> |
||||
|
<a href="https://docs.abp.io/en/abp/latest/Contribution/Index?ref=tmpl" target="_blank" class="btn btn-link px-1">Contribute <i class="fas fa-chevron-right"></i></a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="row text-center mt-lg-3 justify-content-md-center"> |
||||
|
<div class="col-lg-4"> |
||||
|
<div class="p-4"> |
||||
|
<h5 class="mb-3"><i class="fas fa-pen-nib text-secondary d-block my-3 fa-2x"></i> ABP Blog</h5> |
||||
|
<p>Take a look at our recently published articles.</p> |
||||
|
<a href="https://blog.abp.io/abp?ref=tmpl" target="_blank" class="btn btn-link px-1">See Blog <i class="fas fa-chevron-right"></i></a> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-4 border-start"> |
||||
|
<div class="p-4"> |
||||
|
<h5 class="mb-3"><i class="fab fa-github text-secondary d-block my-3 fa-2x"></i> Github</h5> |
||||
|
<p>Do you love the ABP Framework? Please <strong>give a star</strong> to support it!</p> |
||||
|
|
||||
|
<a href="https://github.com/abpframework/abp/" target="_blank" class="btn btn-link px-1">See Open Source Framework <i class="fas fa-chevron-right"></i></a> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-4 border-start"> |
||||
|
<div class="p-4"> |
||||
|
<h5 class="mb-3"><i class="fab fa-stack-overflow text-secondary d-block my-3 fa-2x"></i> Stackoverflow</h5> |
||||
|
<p>See answers to previously asked questions or ask a new one.</p> |
||||
|
<a href="https://stackoverflow.com/questions/tagged/abp" target="_blank" class="btn btn-link px-1">Questions <i class="fas fa-chevron-right"></i></a> |
||||
|
<a href="https://stackoverflow.com/questions/ask" target="_blank" class="btn btn-link px-1">Ask a Question <i class="fas fa-chevron-right"></i></a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="mt-5 my-3 text-center"> |
||||
|
<h3>Meet the ABP Commercial</h3> |
||||
|
<p>A Complete Web Application Platform Built on the ABP Framework</p> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card mt-4 mb-5"> |
||||
|
<div class="card-body"> |
||||
|
<p class="px-lg-5 mx-lg-5 py-3 text-center"> |
||||
|
<a href="https://commercial.abp.io/" target="_blank">ABP Commercial</a> is a platform based on the open source ABP framework. It provides pre-built application modules, |
||||
|
rapid application development tooling, professional UI themes, premium support and more. |
||||
|
</p> |
||||
|
|
||||
|
<div class="row text-center justify-content-md-center"> |
||||
|
<div class="col-lg-2"> |
||||
|
<div class="p-3"> |
||||
|
<h6> |
||||
|
<i class="fas fa-plus d-block mb-3 fa- 2x text-secondary"></i> Startup Templates |
||||
|
<a href="https://commercial.abp.io/startup-templates?ref=tmpl" target="_blank" class="d-block mt-2 btn btn-sm btn-link">Details <i class="fas fa-chevron-right"></i></a> |
||||
|
</h6> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-2 border-start"> |
||||
|
<div class="p-3"> |
||||
|
<h6> |
||||
|
<i class="fas fa-plus d-block mb-3 fa- 2x text-secondary"></i> Application Modules |
||||
|
<a href="https://commercial.abp.io/modules?ref=tmpl" target="_blank" class="d-block mt-2 btn btn-sm btn-link">Details <i class="fas fa-chevron-right"></i></a> |
||||
|
</h6> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-2 border-start"> |
||||
|
<div class="p-3"> |
||||
|
<h6> |
||||
|
<i class="fas fa-plus d-block mb-3 fa- 2x text-secondary"></i> Developer<br />Tools |
||||
|
<a href="https://commercial.abp.io/tools?ref=tmpl" target="_blank" class="d-block mt-2 btn btn-sm btn-link">Details <i class="fas fa-chevron-right"></i></a> |
||||
|
</h6> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-2 border-start"> |
||||
|
<div class="p-3"> |
||||
|
<h6> |
||||
|
<i class="fas fa-plus d-block mb-3 fa- 2x text-secondary"></i> UI<br /> Themes |
||||
|
<a href="https://commercial.abp.io/themes?ref=tmpl" target="_blank" class="d-block mt-2 btn btn-sm btn-link">Details <i class="fas fa-chevron-right"></i></a> |
||||
|
</h6> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-2 border-start"> |
||||
|
<div class="p-3"> |
||||
|
<h6> |
||||
|
<i class="fas fa-plus d-block mb-3 fa- 2x text-secondary"></i> Premium Support |
||||
|
<a href="https://support.abp.io/QA/Questions?ref=tmpl" target="_blank" class="d-block mt-2 btn btn-sm btn-link">Details <i class="fas fa-chevron-right"></i></a> |
||||
|
</h6> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-lg-2 border-start"> |
||||
|
<div class="p-3"> |
||||
|
<h6> |
||||
|
<i class="fas fa-plus d-block mb-3 fa- 2x text-secondary"></i> Additional Services |
||||
|
<a href="https://commercial.abp.io/additional-services?ref=tmpl" target="_blank" class="d-block mt-2 btn btn-sm btn-link">Details <i class="fas fa-chevron-right"></i></a> |
||||
|
</h6> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="mb-5 text-center"> |
||||
|
<p class="align-middle"> |
||||
|
<a href="https://twitter.com/abpframework" target="_blank" class="mx-2"><i class="fab fa-twitter"></i><span class="text-secondary"> Abp Framework</span></a> |
||||
|
<a href="https://twitter.com/abpcommercial" target="_blank" class="mx-2"><i class="fab fa-twitter"></i><span class="text-secondary"> Abp Commercial</span></a> |
||||
|
<a href="https://github.com/abpframework/abp" target="_blank" class="mx-2"><i class="fab fa-github"></i><span class="text-secondary"> abpframework</span></a> |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client.Pages; |
||||
|
|
||||
|
public partial class Index |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
/* Write here your styles for the Index page */ |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client; |
||||
|
|
||||
|
public class Program |
||||
|
{ |
||||
|
public async static Task Main(string[] args) |
||||
|
{ |
||||
|
var builder = WebAssemblyHostBuilder.CreateDefault(args); |
||||
|
var application = await builder.AddApplicationAsync<MyProjectNameBlazorClientModule>(options => |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
}); |
||||
|
|
||||
|
var host = builder.Build(); |
||||
|
|
||||
|
await application.InitializeApplicationAsync(host.Services); |
||||
|
|
||||
|
await host.RunAsync(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
@using Volo.Abp.AspNetCore.Components.Web.LeptonXLiteTheme.Themes.LeptonXLite |
||||
|
@using Volo.Abp.AspNetCore.Components.Web.Theming.Routing |
||||
|
@using Microsoft.Extensions.Options |
||||
|
@inject IOptions<AbpRouterOptions> RouterOptions |
||||
|
<Router AppAssembly="typeof(Program).Assembly" AdditionalAssemblies="RouterOptions.Value.AdditionalAssemblies"> |
||||
|
<Found Context="routeData"> |
||||
|
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)"> |
||||
|
<NotAuthorized> |
||||
|
<RedirectToLogin /> |
||||
|
</NotAuthorized> |
||||
|
</AuthorizeRouteView> |
||||
|
<FocusOnNavigate RouteData="routeData" Selector="h1" /> |
||||
|
</Found> |
||||
|
</Router> |
||||
@ -0,0 +1,15 @@ |
|||||
|
@using System.Net.Http |
||||
|
@using Microsoft.AspNetCore.Authorization |
||||
|
@using Microsoft.AspNetCore.Components.Authorization |
||||
|
@using Microsoft.AspNetCore.Components.Forms |
||||
|
@using Microsoft.AspNetCore.Components.Routing |
||||
|
@using Microsoft.AspNetCore.Components.Web |
||||
|
@using Microsoft.AspNetCore.Components.WebAssembly.Http |
||||
|
@using static Microsoft.AspNetCore.Components.Web.RenderMode |
||||
|
@using Microsoft.JSInterop |
||||
|
@using Volo.Abp.AspNetCore.Components.Web |
||||
|
@using MyCompanyName.MyProjectName.Blazor |
||||
|
@using Blazorise |
||||
|
@using Blazorise.DataGrid |
||||
|
@using Volo.Abp.BlazoriseUI |
||||
|
@using Volo.Abp.BlazoriseUI.Components |
||||
@ -0,0 +1,3 @@ |
|||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
{ |
||||
|
"App": { |
||||
|
"SelfUrl": "https://localhost:44309" |
||||
|
}, |
||||
|
"AuthServer": { |
||||
|
"Authority": "https://localhost:44301" |
||||
|
}, |
||||
|
"RemoteServices": { |
||||
|
"Default": { |
||||
|
"BaseUrl": "https://localhost:44300" |
||||
|
} |
||||
|
}, |
||||
|
"AbpCli": { |
||||
|
"Bundle": { |
||||
|
"Mode": "BundleAndMinify", /* Options: None, Bundle, BundleAndMinify */ |
||||
|
"Name": "global", |
||||
|
"IsBlazorWebApp": true, |
||||
|
"Parameters": { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
@ -0,0 +1,57 @@ |
|||||
|
/* Global styles for the MyProjectName application */ |
||||
|
|
||||
|
/* <TEMPLATE-REMOVE IF-NOT='LEPTONX'> */ |
||||
|
:root .lpx-brand-logo { |
||||
|
--lpx-logo: url('/images/logo/leptonx/logo-light.png'); |
||||
|
--lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); |
||||
|
} |
||||
|
/* </TEMPLATE-REMOVE> */ |
||||
|
|
||||
|
.spinner { |
||||
|
width: 40px; |
||||
|
height: 40px; |
||||
|
display: block; |
||||
|
position: fixed; |
||||
|
top: calc( 50% - ( 40px / 2) ); |
||||
|
right: calc( 50% - ( 40px / 2) ); |
||||
|
} |
||||
|
|
||||
|
.double-bounce1, .double-bounce2 { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
border-radius: 50%; |
||||
|
background-color: #333; |
||||
|
opacity: 0.6; |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
-webkit-animation: sk-bounce 2.0s infinite ease-in-out; |
||||
|
animation: sk-bounce 2.0s infinite ease-in-out; |
||||
|
} |
||||
|
|
||||
|
.double-bounce2 { |
||||
|
-webkit-animation-delay: -1.0s; |
||||
|
animation-delay: -1.0s; |
||||
|
} |
||||
|
|
||||
|
@-webkit-keyframes sk-bounce { |
||||
|
0%, 100% { |
||||
|
-webkit-transform: scale(0.0) |
||||
|
} |
||||
|
|
||||
|
50% { |
||||
|
-webkit-transform: scale(1.0) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes sk-bounce { |
||||
|
0%, 100% { |
||||
|
transform: scale(0.0); |
||||
|
-webkit-transform: scale(0.0); |
||||
|
} |
||||
|
|
||||
|
50% { |
||||
|
transform: scale(1.0); |
||||
|
-webkit-transform: scale(1.0); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
{ |
||||
|
"name": "MyProjectName", |
||||
|
"short_name": "MyCompanyName.MyProjectName", |
||||
|
"start_url": "./", |
||||
|
"display": "standalone", |
||||
|
"background_color": "#ffffff", |
||||
|
"theme_color": "#03173d", |
||||
|
"prefer_related_applications": false, |
||||
|
"icons": [ |
||||
|
{ |
||||
|
"src": "icon-512.png", |
||||
|
"type": "image/png", |
||||
|
"sizes": "512x512" |
||||
|
}, |
||||
|
{ |
||||
|
"src": "icon-192.png", |
||||
|
"type": "image/png", |
||||
|
"sizes": "192x192" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
// In development, always fetch from the network and do not enable offline support.
|
||||
|
// This is because caching would make development more difficult (changes would not
|
||||
|
// be reflected on the first load after each change).
|
||||
|
self.addEventListener('fetch', () => { }); |
||||
@ -0,0 +1,48 @@ |
|||||
|
// Caution! Be sure you understand the caveats before publishing an application with
|
||||
|
// offline support. See https://aka.ms/blazor-offline-considerations
|
||||
|
|
||||
|
self.importScripts('./service-worker-assets.js'); |
||||
|
self.addEventListener('install', event => event.waitUntil(onInstall(event))); |
||||
|
self.addEventListener('activate', event => event.waitUntil(onActivate(event))); |
||||
|
self.addEventListener('fetch', event => event.respondWith(onFetch(event))); |
||||
|
|
||||
|
const cacheNamePrefix = 'offline-cache-'; |
||||
|
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`; |
||||
|
const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ]; |
||||
|
const offlineAssetsExclude = [ /^service-worker\.js$/ ]; |
||||
|
|
||||
|
async function onInstall(event) { |
||||
|
console.info('Service worker: Install'); |
||||
|
|
||||
|
// Fetch and cache all matching items from the assets manifest
|
||||
|
const assetsRequests = self.assetsManifest.assets |
||||
|
.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url))) |
||||
|
.filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url))) |
||||
|
.map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' })); |
||||
|
await caches.open(cacheName).then(cache => cache.addAll(assetsRequests)); |
||||
|
} |
||||
|
|
||||
|
async function onActivate(event) { |
||||
|
console.info('Service worker: Activate'); |
||||
|
|
||||
|
// Delete unused caches
|
||||
|
const cacheKeys = await caches.keys(); |
||||
|
await Promise.all(cacheKeys |
||||
|
.filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName) |
||||
|
.map(key => caches.delete(key))); |
||||
|
} |
||||
|
|
||||
|
async function onFetch(event) { |
||||
|
let cachedResponse = null; |
||||
|
if (event.request.method === 'GET') { |
||||
|
// For all navigation requests, try to serve index.html from cache
|
||||
|
// If you need some URLs to be server-rendered, edit the following check to exclude those URLs
|
||||
|
const shouldServeIndexHtml = event.request.mode === 'navigate'; |
||||
|
|
||||
|
const request = shouldServeIndexHtml ? 'index.html' : event.request; |
||||
|
const cache = await caches.open(cacheName); |
||||
|
cachedResponse = await cache.match(request); |
||||
|
} |
||||
|
|
||||
|
return cachedResponse || fetch(event.request); |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
@using Volo.Abp.Localization |
||||
|
@using System.Globalization |
||||
|
@using Microsoft.AspNetCore.Authentication |
||||
|
@using Microsoft.AspNetCore.Http |
||||
|
@using Microsoft.Extensions.Hosting |
||||
|
@using Volo.Abp.AspNetCore.Components.Server.Theming.Bundling |
||||
|
@using Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme.Bundling |
||||
|
@using Volo.Abp.AspNetCore.Components.WebAssembly.WebApp |
||||
|
@inject IHostEnvironment Env |
||||
|
@{ |
||||
|
var rtl = CultureHelper.IsRtl ? "rtl" : string.Empty; |
||||
|
} |
||||
|
|
||||
|
<!DOCTYPE html> |
||||
|
<html lang="@CultureInfo.CurrentCulture.Name" dir="@rtl"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="utf-8" /> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||
|
<title>MyCompanyName.MyProjectName.Blazor.Server</title> |
||||
|
<base href="/" /> |
||||
|
|
||||
|
<AbpStyles BundleName="@BlazorLeptonXLiteThemeBundles.Styles.Global" /> |
||||
|
|
||||
|
<HeadOutlet @rendermode="InteractiveAuto" /> |
||||
|
|
||||
|
</head> |
||||
|
<body> |
||||
|
|
||||
|
<Routes @rendermode="InteractiveAuto" /> |
||||
|
|
||||
|
<AbpScripts BundleName="@BlazorLeptonXLiteThemeBundles.Scripts.Global" /> |
||||
|
|
||||
|
<div id="blazor-error-ui"> |
||||
|
@if (Env.IsDevelopment()) |
||||
|
{ |
||||
|
<text>An unhandled exception has occurred. See browser dev tools for details.</text> |
||||
|
} |
||||
|
else if (Env.IsStaging() || Env.IsProduction()) |
||||
|
{ |
||||
|
<text>An error has occurred. This application may no longer respond until reloaded.</text> |
||||
|
} |
||||
|
<a href="" class="reload">Reload</a> |
||||
|
<a class="dismiss">🗙</a> |
||||
|
</div> |
||||
|
|
||||
|
</body> |
||||
|
</html> |
||||
|
|
||||
|
@code{ |
||||
|
[CascadingParameter] |
||||
|
private HttpContext HttpContext { get; set; } = default!; |
||||
|
|
||||
|
[Inject] |
||||
|
private PersistentComponentState PersistentComponentState { get; set; } |
||||
|
|
||||
|
private string? Token { get; set; } = default!; |
||||
|
|
||||
|
protected override async Task OnInitializedAsync() |
||||
|
{ |
||||
|
if (HttpContext.User?.Identity?.IsAuthenticated == true) |
||||
|
{ |
||||
|
Token = await HttpContext.GetTokenAsync("access_token"); |
||||
|
} |
||||
|
|
||||
|
PersistentComponentState.RegisterOnPersisting(OnPersistingAsync, RenderMode.InteractiveWebAssembly); |
||||
|
} |
||||
|
|
||||
|
async Task OnPersistingAsync() |
||||
|
{ |
||||
|
if (!Token.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
PersistentComponentState.PersistAsJson(PersistentAccessToken.Key, new PersistentAccessToken |
||||
|
{ |
||||
|
AccessToken = Token |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
await Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
@using Microsoft.AspNetCore.Mvc.Localization |
||||
|
@using MyCompanyName.MyProjectName.Localization |
||||
|
@inject IHtmlLocalizer<MyProjectNameResource> L |
||||
|
<a class="nav-link" role="button" href="~/Account/Login">@L["Login"]</a> |
||||
@ -0,0 +1,12 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Components.Toolbar.LoginLink; |
||||
|
|
||||
|
public class LoginLinkViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
public virtual IViewComponentResult Invoke() |
||||
|
{ |
||||
|
return View("~/Components/Toolbar/LoginLink/Default.cshtml"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.AspNetCore.Mvc.Authentication; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Controllers; |
||||
|
|
||||
|
public class AccountController : ChallengeAccountController |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,79 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using MyCompanyName.MyProjectName.MultiTenancy; |
||||
|
using Volo.Abp.Account.Localization; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Identity.Blazor; |
||||
|
using Volo.Abp.SettingManagement.Blazor.Menus; |
||||
|
using Volo.Abp.TenantManagement.Blazor.Navigation; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Menus; |
||||
|
|
||||
|
public class MyProjectNameMenuContributor : IMenuContributor |
||||
|
{ |
||||
|
private readonly IConfiguration _configuration; |
||||
|
|
||||
|
public MyProjectNameMenuContributor(IConfiguration configuration) |
||||
|
{ |
||||
|
_configuration = configuration; |
||||
|
} |
||||
|
|
||||
|
public async Task ConfigureMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
if (context.Menu.Name == StandardMenus.Main) |
||||
|
{ |
||||
|
await ConfigureMainMenuAsync(context); |
||||
|
} |
||||
|
else if (context.Menu.Name == StandardMenus.User) |
||||
|
{ |
||||
|
await ConfigureUserMenuAsync(context); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private Task ConfigureMainMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
var administration = context.Menu.GetAdministration(); |
||||
|
var l = context.GetLocalizer<MyProjectNameResource>(); |
||||
|
|
||||
|
context.Menu.Items.Insert( |
||||
|
0, |
||||
|
new ApplicationMenuItem( |
||||
|
MyProjectNameMenus.Home, |
||||
|
l["Menu:Home"], |
||||
|
"/", |
||||
|
icon: "fas fa-home", |
||||
|
order: 0 |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
if (MultiTenancyConsts.IsEnabled) |
||||
|
{ |
||||
|
administration.SetSubItemOrder(TenantManagementMenuNames.GroupName, 1); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
administration.TryRemoveMenuItem(TenantManagementMenuNames.GroupName); |
||||
|
} |
||||
|
|
||||
|
administration.SetSubItemOrder(IdentityMenuNames.GroupName, 2); |
||||
|
administration.SetSubItemOrder(SettingManagementMenus.GroupName, 3); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
private Task ConfigureUserMenuAsync(MenuConfigurationContext context) |
||||
|
{ |
||||
|
var l = context.GetLocalizer<MyProjectNameResource>(); |
||||
|
var accountStringLocalizer = context.GetLocalizer<AccountResource>(); |
||||
|
var authServerUrl = _configuration["AuthServer:Authority"] ?? ""; |
||||
|
|
||||
|
context.Menu.AddItem(new ApplicationMenuItem("Account.Manage", accountStringLocalizer["MyAccount"], |
||||
|
$"{authServerUrl.EnsureEndsWith('/')}Account/Manage?returnUrl={_configuration["App:SelfUrl"]}", icon: "fa fa-cog", order: 1000, null, "_blank").RequireAuthenticated()); |
||||
|
context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", l["Logout"], url: "~/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000).RequireAuthenticated()); |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Menus; |
||||
|
|
||||
|
public class MyProjectNameMenus |
||||
|
{ |
||||
|
private const string Prefix = "MyProjectName"; |
||||
|
public const string Home = Prefix + ".Home"; |
||||
|
|
||||
|
//Add your menu items here...
|
||||
|
|
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Components.Toolbar.LoginLink; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Menus; |
||||
|
|
||||
|
public class MyProjectNameToolbarContributor : IToolbarContributor |
||||
|
{ |
||||
|
public virtual Task ConfigureToolbarAsync(IToolbarConfigurationContext context) |
||||
|
{ |
||||
|
if (context.Toolbar.Name != StandardToolbars.Main) |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
if (!context.ServiceProvider.GetRequiredService<ICurrentUser>().IsAuthenticated) |
||||
|
{ |
||||
|
context.Toolbar.Items.Add(new ToolbarItem(typeof(LoginLinkViewComponent))); |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<Import Project="..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> |
||||
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> |
||||
|
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> |
||||
|
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish> |
||||
|
<PreserveCompilationReferences>true</PreserveCompilationReferences> |
||||
|
<UserSecretsId>MyCompanyName.MyProjectName-4681b4fd-151f-4221-84a4-929d86723e4c</UserSecretsId> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.1" /> |
||||
|
<PackageReference Include="Blazorise.Bootstrap5" Version="1.4.1" /> |
||||
|
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.4.1" /> |
||||
|
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" /> |
||||
|
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" /> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.0" /> |
||||
|
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<!-- <TEMPLATE-REMOVE> --> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy\Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.Server.Theming\Volo.Abp.AspNetCore.Components.Server.Theming.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj" /> |
||||
|
<!-- </TEMPLATE-REMOVE> --> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme" Version="3.0.*-*" /> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite" Version="3.0.*-*" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client\MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client.csproj" /> |
||||
|
<ProjectReference Include="..\MyCompanyName.MyProjectName.HttpApi.Client\MyCompanyName.MyProjectName.HttpApi.Client.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Caching.StackExchangeRedis\Volo.Abp.Caching.StackExchangeRedis.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.DistributedLocking\Volo.Abp.DistributedLocking.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.Client\Volo.Abp.AspNetCore.Mvc.Client.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Authentication.OpenIdConnect\Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Http.Client.IdentityModel.Web\Volo.Abp.Http.Client.IdentityModel.Web.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\framework\src\Volo.Abp.AspNetCore.Serilog\Volo.Abp.AspNetCore.Serilog.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\modules\identity\src\Volo.Abp.Identity.Blazor.Server\Volo.Abp.Identity.Blazor.Server.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\modules\tenant-management\src\Volo.Abp.TenantManagement.Blazor.Server\Volo.Abp.TenantManagement.Blazor.Server.csproj" /> |
||||
|
<ProjectReference Include="..\..\..\..\..\modules\setting-management\src\Volo.Abp.SettingManagement.Blazor.Server\Volo.Abp.SettingManagement.Blazor.Server.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Compile Remove="Logs\**" /> |
||||
|
<Content Remove="Logs\**" /> |
||||
|
<EmbeddedResource Remove="Logs\**" /> |
||||
|
<None Remove="Logs\**" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Update="Pages\**\*.js"> |
||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
||||
|
</None> |
||||
|
<None Update="Pages\**\*.css"> |
||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
||||
|
</None> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,394 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using Blazorise.Bootstrap5; |
||||
|
using Blazorise.Icons.FontAwesome; |
||||
|
using Medallion.Threading; |
||||
|
using Medallion.Threading.Redis; |
||||
|
using Microsoft.AspNetCore.Authentication.Cookies; |
||||
|
using Microsoft.AspNetCore.Authentication.OpenIdConnect; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage; |
||||
|
using Microsoft.AspNetCore.DataProtection; |
||||
|
using Microsoft.AspNetCore.Hosting; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Microsoft.Extensions.Hosting; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Microsoft.IdentityModel.Protocols.OpenIdConnect; |
||||
|
using Microsoft.OpenApi.Models; |
||||
|
using MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client; |
||||
|
using MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Components; |
||||
|
using MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Menus; |
||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using MyCompanyName.MyProjectName.MultiTenancy; |
||||
|
using StackExchange.Redis; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Authentication.OpenIdConnect; |
||||
|
using Volo.Abp.AspNetCore.Components.Server; |
||||
|
using Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme; |
||||
|
using Volo.Abp.AspNetCore.Components.Server.LeptonXLiteTheme.Bundling; |
||||
|
using Volo.Abp.AspNetCore.Components.Web.Theming.Routing; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Client; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Localization; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bundling; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Toolbars; |
||||
|
using Volo.Abp.AspNetCore.Serilog; |
||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
using Volo.Abp.Caching; |
||||
|
using Volo.Abp.Caching.StackExchangeRedis; |
||||
|
using Volo.Abp.DistributedLocking; |
||||
|
using Volo.Abp.Http.Client.IdentityModel.Web; |
||||
|
using Volo.Abp.Identity.Blazor.Server; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.Security.Claims; |
||||
|
using Volo.Abp.SettingManagement.Blazor.Server; |
||||
|
using Volo.Abp.Swashbuckle; |
||||
|
using Volo.Abp.TenantManagement.Blazor.Server; |
||||
|
using Volo.Abp.UI; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
using Volo.Abp.UI.Navigation.Urls; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(MyProjectNameHttpApiClientModule), |
||||
|
typeof(AbpCachingStackExchangeRedisModule), |
||||
|
typeof(AbpDistributedLockingModule), |
||||
|
typeof(AbpAspNetCoreMvcClientModule), |
||||
|
typeof(AbpAspNetCoreAuthenticationOpenIdConnectModule), |
||||
|
typeof(AbpHttpClientIdentityModelWebModule), |
||||
|
typeof(AbpAspNetCoreComponentsServerLeptonXLiteThemeModule), |
||||
|
typeof(AbpAspNetCoreMvcUiLeptonXLiteThemeModule), |
||||
|
typeof(AbpAutofacModule), |
||||
|
typeof(AbpSwashbuckleModule), |
||||
|
typeof(AbpAspNetCoreSerilogModule), |
||||
|
typeof(AbpIdentityBlazorServerModule), |
||||
|
typeof(AbpTenantManagementBlazorServerModule), |
||||
|
typeof(AbpSettingManagementBlazorServerModule) |
||||
|
)] |
||||
|
public class MyProjectNameBlazorModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.AddAssemblyResource( |
||||
|
typeof(MyProjectNameResource), |
||||
|
typeof(MyProjectNameDomainSharedModule).Assembly, |
||||
|
typeof(MyProjectNameApplicationContractsModule).Assembly, |
||||
|
typeof(MyProjectNameBlazorModule).Assembly |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
PreConfigure<AbpAspNetCoreComponentsWebOptions>(options => |
||||
|
{ |
||||
|
options.IsBlazorWebApp = true; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
|
||||
|
// Add services to the container.
|
||||
|
context.Services.AddRazorComponents() |
||||
|
.AddInteractiveServerComponents() |
||||
|
.AddInteractiveWebAssemblyComponents(); |
||||
|
|
||||
|
ConfigureUrls(configuration); |
||||
|
ConfigureCache(); |
||||
|
ConfigureBundles(); |
||||
|
ConfigureMultiTenancy(); |
||||
|
ConfigureAuthentication(context, configuration); |
||||
|
ConfigureAutoMapper(); |
||||
|
ConfigureVirtualFileSystem(hostingEnvironment); |
||||
|
ConfigureBlazorise(context); |
||||
|
ConfigureRouter(context); |
||||
|
ConfigureMenu(configuration); |
||||
|
ConfigureDataProtection(context, configuration, hostingEnvironment); |
||||
|
ConfigureDistributedLocking(context, configuration); |
||||
|
ConfigureSwaggerServices(context.Services); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureUrls(IConfiguration configuration) |
||||
|
{ |
||||
|
Configure<AppUrlOptions>(options => |
||||
|
{ |
||||
|
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"]; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureCache() |
||||
|
{ |
||||
|
Configure<AbpDistributedCacheOptions>(options => |
||||
|
{ |
||||
|
options.KeyPrefix = "MyProjectName:"; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureBundles() |
||||
|
{ |
||||
|
Configure<AbpBundlingOptions>(options => |
||||
|
{ |
||||
|
// MVC UI
|
||||
|
options.StyleBundles.Configure( |
||||
|
LeptonXLiteThemeBundles.Styles.Global, |
||||
|
bundle => |
||||
|
{ |
||||
|
bundle.AddFiles("/global-styles.css"); |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
//BLAZOR UI
|
||||
|
options.StyleBundles.Configure( |
||||
|
BlazorLeptonXLiteThemeBundles.Styles.Global, |
||||
|
bundle => |
||||
|
{ |
||||
|
bundle.AddFiles("/blazor-global-styles.css"); |
||||
|
//You can remove the following line if you don't use Blazor CSS isolation for components
|
||||
|
bundle.AddFiles("/MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client.styles.css"); |
||||
|
} |
||||
|
); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureMultiTenancy() |
||||
|
{ |
||||
|
Configure<AbpMultiTenancyOptions>(options => |
||||
|
{ |
||||
|
options.IsEnabled = MultiTenancyConsts.IsEnabled; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) |
||||
|
{ |
||||
|
context.Services.TryAddScoped<ProtectedLocalStorage>(); |
||||
|
context.Services.AddAuthentication(options => |
||||
|
{ |
||||
|
options.DefaultScheme = "Cookies"; |
||||
|
options.DefaultChallengeScheme = "oidc"; |
||||
|
}) |
||||
|
.AddCookie("Cookies", options => |
||||
|
{ |
||||
|
options.ExpireTimeSpan = TimeSpan.FromDays(365); |
||||
|
options.IntrospectAccessToken(); |
||||
|
}) |
||||
|
.AddAbpOpenIdConnect("oidc", options => |
||||
|
{ |
||||
|
options.Authority = configuration["AuthServer:Authority"]; |
||||
|
options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata"); |
||||
|
options.ResponseType = OpenIdConnectResponseType.CodeIdToken; |
||||
|
|
||||
|
options.ClientId = configuration["AuthServer:ClientId"]; |
||||
|
options.ClientSecret = configuration["AuthServer:ClientSecret"]; |
||||
|
|
||||
|
options.SaveTokens = true; |
||||
|
options.GetClaimsFromUserInfoEndpoint = true; |
||||
|
|
||||
|
options.Scope.Add("roles"); |
||||
|
options.Scope.Add("email"); |
||||
|
options.Scope.Add("phone"); |
||||
|
options.Scope.Add("MyProjectName"); |
||||
|
}); |
||||
|
/* |
||||
|
* This configuration is used when the AuthServer is running on the internal network such as docker or k8s. |
||||
|
* Configuring the redirecting URLs for internal network and the web |
||||
|
* The login and the logout URLs are configured to redirect to the AuthServer real DNS for browser. |
||||
|
* The token acquired and validated from the the internal network AuthServer URL. |
||||
|
*/ |
||||
|
if (configuration.GetValue<bool>("AuthServer:IsContainerized")) |
||||
|
{ |
||||
|
context.Services.Configure<OpenIdConnectOptions>("oidc", options => |
||||
|
{ |
||||
|
options.TokenValidationParameters.ValidIssuers = new[] |
||||
|
{ |
||||
|
configuration["AuthServer:MetaAddress"]!.EnsureEndsWith('/'), |
||||
|
configuration["AuthServer:Authority"]!.EnsureEndsWith('/') |
||||
|
}; |
||||
|
|
||||
|
options.MetadataAddress = configuration["AuthServer:MetaAddress"]!.EnsureEndsWith('/') + |
||||
|
".well-known/openid-configuration"; |
||||
|
|
||||
|
var previousOnRedirectToIdentityProvider = options.Events.OnRedirectToIdentityProvider; |
||||
|
options.Events.OnRedirectToIdentityProvider = async ctx => |
||||
|
{ |
||||
|
// Intercept the redirection so the browser navigates to the right URL in your host
|
||||
|
ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') + "connect/authorize"; |
||||
|
|
||||
|
if (previousOnRedirectToIdentityProvider != null) |
||||
|
{ |
||||
|
await previousOnRedirectToIdentityProvider(ctx); |
||||
|
} |
||||
|
}; |
||||
|
var previousOnRedirectToIdentityProviderForSignOut = options.Events.OnRedirectToIdentityProviderForSignOut; |
||||
|
options.Events.OnRedirectToIdentityProviderForSignOut = async ctx => |
||||
|
{ |
||||
|
// Intercept the redirection for signout so the browser navigates to the right URL in your host
|
||||
|
ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') + "connect/logout"; |
||||
|
|
||||
|
if (previousOnRedirectToIdentityProviderForSignOut != null) |
||||
|
{ |
||||
|
await previousOnRedirectToIdentityProviderForSignOut(ctx); |
||||
|
} |
||||
|
}; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options => |
||||
|
{ |
||||
|
options.IsDynamicClaimsEnabled = true; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment) |
||||
|
{ |
||||
|
if (hostingEnvironment.IsDevelopment()) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
//<TEMPLATE-REMOVE>
|
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpUiModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.UI", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI", Path.DirectorySeparatorChar))); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiBootstrapModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Bootstrap", Path.DirectorySeparatorChar))); |
||||
|
//options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiThemeSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared", Path.DirectorySeparatorChar)));
|
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<AbpAspNetCoreMvcUiMultiTenancyModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}framework{0}src{0}Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy", Path.DirectorySeparatorChar))); |
||||
|
//options.FileSets.ReplaceEmbeddedByPhysical<AbpPermissionManagementWebModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}modules{0}permission-management{0}src{0}Volo.Abp.PermissionManagement.Web", Path.DirectorySeparatorChar)));
|
||||
|
//options.FileSets.ReplaceEmbeddedByPhysical<AbpFeatureManagementWebModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}modules{0}feature-management{0}src{0}Volo.Abp.FeatureManagement.Web", Path.DirectorySeparatorChar)));
|
||||
|
//options.FileSets.ReplaceEmbeddedByPhysical<AbpIdentityWebModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}modules{0}identity{0}src{0}Volo.Abp.Identity.Web", Path.DirectorySeparatorChar)));
|
||||
|
//options.FileSets.ReplaceEmbeddedByPhysical<AbpTenantManagementWebModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}..{0}..{0}..{0}modules{0}tenant-management{0}src{0}Volo.Abp.TenantManagement.Web", Path.DirectorySeparatorChar)));
|
||||
|
//</TEMPLATE-REMOVE>
|
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}MyCompanyName.MyProjectName.Domain.Shared")); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}MyCompanyName.MyProjectName.Application.Contracts")); |
||||
|
options.FileSets.ReplaceEmbeddedByPhysical<MyProjectNameBlazorModule>(hostingEnvironment.ContentRootPath); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void ConfigureBlazorise(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services |
||||
|
.AddBootstrap5Providers() |
||||
|
.AddFontAwesomeIcons(); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureMenu(IConfiguration configuration) |
||||
|
{ |
||||
|
Configure<AbpNavigationOptions>(options => |
||||
|
{ |
||||
|
options.MenuContributors.Add(new MyProjectNameMenuContributor(configuration)); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpToolbarOptions>(options => |
||||
|
{ |
||||
|
options.Contributors.Add(new MyProjectNameToolbarContributor()); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureRouter(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpRouterOptions>(options => |
||||
|
{ |
||||
|
options.AppAssembly = typeof(MyProjectNameBlazorModule).Assembly; |
||||
|
options.AdditionalAssemblies.Add(typeof(MyProjectNameBlazorClientModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureAutoMapper() |
||||
|
{ |
||||
|
Configure<AbpAutoMapperOptions>(options => |
||||
|
{ |
||||
|
options.AddMaps<MyProjectNameBlazorModule>(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureSwaggerServices(IServiceCollection services) |
||||
|
{ |
||||
|
services.AddAbpSwaggerGen( |
||||
|
options => |
||||
|
{ |
||||
|
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MyProjectName API", Version = "v1" }); |
||||
|
options.DocInclusionPredicate((docName, description) => true); |
||||
|
options.CustomSchemaIds(type => type.FullName); |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private void ConfigureDataProtection( |
||||
|
ServiceConfigurationContext context, |
||||
|
IConfiguration configuration, |
||||
|
IWebHostEnvironment hostingEnvironment) |
||||
|
{ |
||||
|
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("MyProjectName"); |
||||
|
if (!hostingEnvironment.IsDevelopment()) |
||||
|
{ |
||||
|
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); |
||||
|
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "MyProjectName-Protection-Keys"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void ConfigureDistributedLocking( |
||||
|
ServiceConfigurationContext context, |
||||
|
IConfiguration configuration) |
||||
|
{ |
||||
|
context.Services.AddSingleton<IDistributedLockProvider>(sp => |
||||
|
{ |
||||
|
var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!); |
||||
|
return new RedisDistributedSynchronizationProvider(connection.GetDatabase()); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
||||
|
{ |
||||
|
var env = context.GetEnvironment(); |
||||
|
var app = context.GetApplicationBuilder(); |
||||
|
|
||||
|
if (env.IsDevelopment()) |
||||
|
{ |
||||
|
app.UseDeveloperExceptionPage(); |
||||
|
} |
||||
|
|
||||
|
app.UseAbpRequestLocalization(); |
||||
|
|
||||
|
if (!env.IsDevelopment()) |
||||
|
{ |
||||
|
app.UseErrorPage(); |
||||
|
} |
||||
|
|
||||
|
app.UseCorrelationId(); |
||||
|
app.UseStaticFiles(); |
||||
|
app.UseRouting(); |
||||
|
app.UseAuthentication(); |
||||
|
|
||||
|
if (MultiTenancyConsts.IsEnabled) |
||||
|
{ |
||||
|
app.UseMultiTenancy(); |
||||
|
} |
||||
|
app.UseDynamicClaims(); |
||||
|
app.UseAntiforgery(); |
||||
|
app.UseAuthorization(); |
||||
|
app.UseSwagger(); |
||||
|
app.UseAbpSwaggerUI(options => |
||||
|
{ |
||||
|
options.SwaggerEndpoint("/swagger/v1/swagger.json", "MyProjectName API"); |
||||
|
}); |
||||
|
app.UseAbpSerilogEnrichers(); |
||||
|
app.UseConfiguredEndpoints(builder => |
||||
|
{ |
||||
|
builder.MapRazorComponents<App>() |
||||
|
.AddInteractiveServerRenderMode() |
||||
|
.AddInteractiveWebAssemblyRenderMode() |
||||
|
.AddAdditionalAssemblies(builder.ServiceProvider.GetRequiredService<IOptions<AbpRouterOptions>>().Value.AdditionalAssemblies.ToArray()); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Ui.Branding; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered; |
||||
|
|
||||
|
[Dependency(ReplaceServices = true)] |
||||
|
public class MyProjectNameBrandingProvider : DefaultBrandingProvider |
||||
|
{ |
||||
|
public override string AppName => "MyProjectName"; |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using MyCompanyName.MyProjectName.Localization; |
||||
|
using Volo.Abp.AspNetCore.Components; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered; |
||||
|
|
||||
|
public abstract class MyProjectNameComponentBase : AbpComponentBase |
||||
|
{ |
||||
|
protected MyProjectNameComponentBase() |
||||
|
{ |
||||
|
LocalizationResource = typeof(MyProjectNameResource); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Builder; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Hosting; |
||||
|
using Serilog; |
||||
|
using Serilog.Events; |
||||
|
|
||||
|
namespace MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered; |
||||
|
|
||||
|
public class Program |
||||
|
{ |
||||
|
public async static Task<int> Main(string[] args) |
||||
|
{ |
||||
|
Log.Logger = new LoggerConfiguration() |
||||
|
#if DEBUG
|
||||
|
.MinimumLevel.Debug() |
||||
|
#else
|
||||
|
.MinimumLevel.Information() |
||||
|
#endif
|
||||
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Information) |
||||
|
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) |
||||
|
.Enrich.FromLogContext() |
||||
|
.WriteTo.Async(c => c.File("Logs/logs.txt")) |
||||
|
.WriteTo.Async(c => c.Console()) |
||||
|
.CreateLogger(); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
Log.Information("Starting web host."); |
||||
|
var builder = WebApplication.CreateBuilder(args); |
||||
|
builder.Host.AddAppSettingsSecretsJson() |
||||
|
.UseAutofac() |
||||
|
.UseSerilog(); |
||||
|
await builder.AddApplicationAsync<MyProjectNameBlazorModule>(); |
||||
|
var app = builder.Build(); |
||||
|
await app.InitializeApplicationAsync(); |
||||
|
await app.RunAsync(); |
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
if (ex is HostAbortedException) |
||||
|
{ |
||||
|
throw; |
||||
|
} |
||||
|
|
||||
|
Log.Fatal(ex, "Host terminated unexpectedly!"); |
||||
|
return 1; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
Log.CloseAndFlush(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "https://localhost:44309/", |
||||
|
"sslPort": 44309 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered": { |
||||
|
"commandName": "Project", |
||||
|
"dotnetRunMessages": "true", |
||||
|
"launchBrowser": true, |
||||
|
"applicationUrl": "https://localhost:44309/", |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
@using System.Net.Http |
||||
|
@using Microsoft.AspNetCore.Authorization |
||||
|
@using Microsoft.AspNetCore.Components.Authorization |
||||
|
@using Microsoft.AspNetCore.Components.Forms |
||||
|
@using Microsoft.AspNetCore.Components.Routing |
||||
|
@using Microsoft.AspNetCore.Components.Web |
||||
|
@using Microsoft.AspNetCore.Components.Web.Virtualization |
||||
|
@using static Microsoft.AspNetCore.Components.Web.RenderMode |
||||
|
@using Microsoft.JSInterop |
||||
|
@using Blazorise |
||||
|
@using Blazorise.DataGrid |
||||
|
@using Volo.Abp.BlazoriseUI |
||||
|
@using Volo.Abp.BlazoriseUI.Components |
||||
|
@using MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.Client |
||||
@ -0,0 +1,11 @@ |
|||||
|
module.exports = { |
||||
|
aliases: { |
||||
|
|
||||
|
}, |
||||
|
clean: [ |
||||
|
|
||||
|
], |
||||
|
mappings: { |
||||
|
|
||||
|
} |
||||
|
}; |
||||
@ -0,0 +1,2 @@ |
|||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
{ |
||||
|
"App": { |
||||
|
"SelfUrl": "https://localhost:44309" |
||||
|
}, |
||||
|
"RemoteServices": { |
||||
|
"Default": { |
||||
|
"BaseUrl": "https://localhost:44300/" |
||||
|
} |
||||
|
}, |
||||
|
"Redis": { |
||||
|
"Configuration": "127.0.0.1" |
||||
|
}, |
||||
|
"AuthServer": { |
||||
|
"Authority": "https://localhost:44301", |
||||
|
"RequireHttpsMetadata": true, |
||||
|
"ClientId": "MyProjectName_BlazorServerTiered", |
||||
|
"ClientSecret": "1q2w3e*", |
||||
|
"IsContainerized": false |
||||
|
}, |
||||
|
"StringEncryption": { |
||||
|
"DefaultPassPhrase": "gsKnGZ041HLL4IM8" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
{ |
||||
|
"version": "1.0.0", |
||||
|
"name": "my-app", |
||||
|
"private": true, |
||||
|
"dependencies": { |
||||
|
"@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~3.0.1", |
||||
|
"@abp/aspnetcore.components.server.leptonxlitetheme": "~3.0.1" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<configuration> |
||||
|
<location path="." inheritInChildApplications="false"> |
||||
|
<system.webServer> |
||||
|
<handlers> |
||||
|
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> |
||||
|
</handlers> |
||||
|
<aspNetCore processPath="dotnet" arguments=".\MyCompanyName.MyProjectName.Blazor.Server.WebApp.Tiered.dll" stdoutLogEnabled="false" stdoutLogFile=".\Logs\stdout" hostingModel="inprocess" /> |
||||
|
</system.webServer> |
||||
|
</location> |
||||
|
<system.webServer> |
||||
|
<httpProtocol> |
||||
|
<customHeaders> |
||||
|
<remove name="x-powered-by" /> |
||||
|
</customHeaders> |
||||
|
</httpProtocol> |
||||
|
</system.webServer> |
||||
|
</configuration> |
||||
@ -0,0 +1,18 @@ |
|||||
|
#blazor-error-ui { |
||||
|
background: lightyellow; |
||||
|
bottom: 0; |
||||
|
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); |
||||
|
display: none; |
||||
|
left: 0; |
||||
|
padding: 0.6rem 1.25rem 0.7rem 1.25rem; |
||||
|
position: fixed; |
||||
|
width: 100%; |
||||
|
z-index: 1000; |
||||
|
} |
||||
|
|
||||
|
#blazor-error-ui .dismiss { |
||||
|
cursor: pointer; |
||||
|
position: absolute; |
||||
|
right: 0.75rem; |
||||
|
top: 0.5rem; |
||||
|
} |
||||
|
After Width: | Height: | Size: 31 KiB |
@ -0,0 +1,10 @@ |
|||||
|
body { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/* <TEMPLATE-REMOVE IF-NOT='LEPTONX'> */ |
||||
|
:root .lpx-brand-logo { |
||||
|
--lpx-logo: url('/images/logo/leptonx/logo-light.png'); |
||||
|
--lpx-logo-icon: url('/images/logo/leptonx/logo-light-thumbnail.png'); |
||||
|
} |
||||
|
/* </TEMPLATE-REMOVE> */ |
||||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 38 KiB |