From ad9da5735b66970946ce0720aa7b76e4bf5d402f Mon Sep 17 00:00:00 2001
From: Jon P Smith
Date: Thu, 15 Dec 2022 14:24:52 +0000
Subject: [PATCH] Got .NET localization working in Example1
---
AuthPermissions.AspNetCore/SetupExtensions.cs | 5 +-
.../Model/AppSummary.cs | 2 +-
.../Pages/Index.cshtml | 5 +-
.../Pages/Localization/SetCulture.cshtml | 16 +++
.../Pages/Localization/SetCulture.cshtml.cs | 43 +++++++
.../Pages/Shared/_Layout.cshtml | 10 +-
.../PermissionsCode/AppAuthSetupData.cs | 2 +-
.../Program.cs | 113 ++++++++++++++++--
.../Startup.cs | 91 --------------
.../appsettings.json | 4 +-
10 files changed, 178 insertions(+), 113 deletions(-)
create mode 100644 Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml
create mode 100644 Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml.cs
delete mode 100644 Example1.RazorPages.IndividualAccounts/Startup.cs
diff --git a/AuthPermissions.AspNetCore/SetupExtensions.cs b/AuthPermissions.AspNetCore/SetupExtensions.cs
index d2f17386..ed1c65a6 100644
--- a/AuthPermissions.AspNetCore/SetupExtensions.cs
+++ b/AuthPermissions.AspNetCore/SetupExtensions.cs
@@ -1,9 +1,6 @@
// Copyright (c) 2021 Jon P Smith, GitHub: JonPSmith, web: http://www.thereformedprogrammer.net/
// Licensed under MIT license. See License.txt in the project root for license information.
-using System;
-using System.Linq;
-using System.Threading.Tasks;
using AuthPermissions.AdminCode;
using AuthPermissions.AdminCode.Services;
using AuthPermissions.AspNetCore.AccessTenantData;
@@ -266,7 +263,7 @@ private static void RegisterCommonServices(this AuthSetupData setupData)
setupData.Services.AddTransient();
//Localization services
- //NOTE: The developer must register the .NET localization service and add
+ //NOTE: If you want to use the localization services you need to setup / register the .NET IStringLocalizer service
setupData.Services.AddSingleton(typeof(ILocalizeWithDefault<>), typeof(LocalizeWithDefault<>));
//Other services
diff --git a/Example1.RazorPages.IndividualAccounts/Model/AppSummary.cs b/Example1.RazorPages.IndividualAccounts/Model/AppSummary.cs
index 9ec62efd..6e125e2c 100644
--- a/Example1.RazorPages.IndividualAccounts/Model/AppSummary.cs
+++ b/Example1.RazorPages.IndividualAccounts/Model/AppSummary.cs
@@ -14,6 +14,6 @@ public class AppSummary
"Individual accounts: InMemoryDatabase",
"AuthPermissions: In-memory database (uses SQLite in-memory)"
};
- public string Note { get; } = "This is a basic example of AuthPermissions Roles and permissions.";
+ public string Note { get; } = "Shows basics of Roles and permissions, plus multi-language support.";
}
}
\ No newline at end of file
diff --git a/Example1.RazorPages.IndividualAccounts/Pages/Index.cshtml b/Example1.RazorPages.IndividualAccounts/Pages/Index.cshtml
index 762ea768..7eca1d0b 100644
--- a/Example1.RazorPages.IndividualAccounts/Pages/Index.cshtml
+++ b/Example1.RazorPages.IndividualAccounts/Pages/Index.cshtml
@@ -1,12 +1,13 @@
@page
@using Example1.RazorPages.IndividualAccounts.Model
+@using Microsoft.AspNetCore.Identity
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
-
Example1 - looking at Roles and Permissions
+ Example1 - looking at Roles/Permissions, plus localization
Application summary
@@ -34,7 +35,7 @@
NOTE: The Email address is also the password in these cases.
- @foreach (var user in @Model.Users)
+ @foreach (var user in @Model.Users ?? new List() )
{
- @user.UserName
}
diff --git a/Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml b/Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml
new file mode 100644
index 00000000..438c18d7
--- /dev/null
+++ b/Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml
@@ -0,0 +1,16 @@
+@page
+@model SetCultureModel
+@{
+}
+
+Select the culture you want
+
+
\ No newline at end of file
diff --git a/Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml.cs b/Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml.cs
new file mode 100644
index 00000000..b354c909
--- /dev/null
+++ b/Example1.RazorPages.IndividualAccounts/Pages/Localization/SetCulture.cshtml.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Localization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.AspNetCore.Mvc.Rendering;
+using Microsoft.Extensions.Options;
+
+namespace Example1.RazorPages.IndividualAccounts.Pages.Localization;
+
+public class SetCultureModel : PageModel
+{
+ private readonly IOptions _locOptions;
+
+ public SetCultureModel(IOptions locOptions)
+ {
+ _locOptions = locOptions;
+ }
+
+ [BindProperty] public List CultureList { get; set; }
+ [BindProperty] public string SetLanguage { get; set; }
+
+ public void OnGet()
+ {
+ CultureList = _locOptions.Value.SupportedUICultures
+ .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
+ .ToList();
+ }
+
+ public IActionResult OnPost()
+ {
+ Response.Cookies.Append(
+ CookieRequestCultureProvider.DefaultCookieName,
+ CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(SetLanguage))
+ );
+
+ return RedirectToPage("/Index");
+ }
+}
\ No newline at end of file
diff --git a/Example1.RazorPages.IndividualAccounts/Pages/Shared/_Layout.cshtml b/Example1.RazorPages.IndividualAccounts/Pages/Shared/_Layout.cshtml
index 6930753e..459efb2e 100644
--- a/Example1.RazorPages.IndividualAccounts/Pages/Shared/_Layout.cshtml
+++ b/Example1.RazorPages.IndividualAccounts/Pages/Shared/_Layout.cshtml
@@ -1,4 +1,6 @@
-
+@using System.Threading
+@using Microsoft.Net.Http.Headers
+
@@ -32,6 +34,12 @@
User's claims
+ -
+ Current culture = @Thread.CurrentThread.CurrentUICulture.DisplayName
+
+ -
+ Change
+
diff --git a/Example1.RazorPages.IndividualAccounts/PermissionsCode/AppAuthSetupData.cs b/Example1.RazorPages.IndividualAccounts/PermissionsCode/AppAuthSetupData.cs
index c6fac6a8..3009a2c3 100644
--- a/Example1.RazorPages.IndividualAccounts/PermissionsCode/AppAuthSetupData.cs
+++ b/Example1.RazorPages.IndividualAccounts/PermissionsCode/AppAuthSetupData.cs
@@ -19,7 +19,7 @@ public static class AppAuthSetupData
public static readonly List UsersWithRolesDefinition = new()
{
new ("Staff@g1.com", null, "Role1"),
- new ("Mananger@g1.com", null, "Role2"),
+ new ("Manager@g1.com", null, "Role2"),
new ( "Super@g1.com", null, "SuperAdmin"),
};
}
diff --git a/Example1.RazorPages.IndividualAccounts/Program.cs b/Example1.RazorPages.IndividualAccounts/Program.cs
index df4c98a5..0900935b 100644
--- a/Example1.RazorPages.IndividualAccounts/Program.cs
+++ b/Example1.RazorPages.IndividualAccounts/Program.cs
@@ -1,20 +1,111 @@
+using Example1.RazorPages.IndividualAccounts.PermissionsCode;
+using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Localization;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+using System.Collections.Generic;
+using System.Globalization;
+using AuthPermissions;
+using AuthPermissions.AspNetCore;
+using AuthPermissions.AspNetCore.Services;
+using AuthPermissions.AspNetCore.StartupServices;
+using Example1.RazorPages.IndividualAccounts.Data;
+using Microsoft.EntityFrameworkCore;
+using RunMethodsSequentially;
+using Microsoft.Extensions.Options;
-namespace Example1.RazorPages.IndividualAccounts
+namespace Example1.RazorPages.IndividualAccounts;
+
+public class Program
{
- public class Program
+ public static void Main(string[] args)
{
- public static void Main(string[] args)
+ var builder = WebApplication.CreateBuilder(args);
+
+ builder.Services.AddDatabaseDeveloperPageExceptionFilter();
+
+ builder.Services.AddDbContext(opt =>
+ opt.UseInMemoryDatabase(nameof(ApplicationDbContext)));
+
+ builder.Services.AddDefaultIdentity(
+ options => options.SignIn.RequireConfirmedAccount = false)
+ .AddEntityFrameworkStores();
+
+ //Example of configure a page as only shown if you log in
+ builder.Services.AddRazorPages(options =>
{
- CreateHostBuilder(args).Build().Run();
- }
+ options.Conventions.AuthorizePage("/AuthBuiltIn/LoggedInConfigure");
+ })
+ #region localization
+ .AddViewLocalization(options => options.ResourcesPath = "Resources");
+ #endregion
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>
+ #region localization
+ builder.Services.Configure(options => {
+ List supportedCultures = new List
{
- webBuilder.UseStartup();
- });
+ new ("en"),
+ new ("fr"),
+ };
+ options.DefaultRequestCulture = new RequestCulture("en");
+ options.SupportedCultures = supportedCultures;
+ options.SupportedUICultures = supportedCultures;
+
+ options.RequestCultureProviders = new List()
+ {
+ new CookieRequestCultureProvider(),
+ //new AcceptLanguageHeaderRequestCultureProvider(),
+ //new QueryStringRequestCultureProvider()
+ };
+ });
+ #endregion
+
+ builder.Services.RegisterAuthPermissions()
+ .UsingInMemoryDatabase()
+ .IndividualAccountsAuthentication()
+ .AddRolesPermissionsIfEmpty(AppAuthSetupData.RolesDefinition)
+ .AddAuthUsersIfEmpty(AppAuthSetupData.UsersWithRolesDefinition)
+ .RegisterAuthenticationProviderReader()
+ .RegisterFindUserInfoService()
+ .AddSuperUserToIndividualAccounts()
+ .SetupAspNetCoreAndDatabase(options =>
+ {
+ //Migrate individual account database
+ options.RegisterServiceToRunInJob>();
+ //Add demo users to the database
+ options.RegisterServiceToRunInJob();
+ });
+
+
+ var app = builder.Build();
+
+ #region localization
+
+ var options = app.Services.GetRequiredService>().Value;
+ app.UseRequestLocalization(options);
+
+ #endregion
+
+ // Configure the HTTP request pipeline.
+ if (!app.Environment.IsDevelopment())
+ {
+ app.UseExceptionHandler("/Error");
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+ }
+
+ app.UseHttpsRedirection();
+ app.UseStaticFiles();
+
+ app.UseRouting();
+
+ app.UseAuthorization();
+
+ app.MapRazorPages();
+
+ app.Run();
}
-}
+
+}
\ No newline at end of file
diff --git a/Example1.RazorPages.IndividualAccounts/Startup.cs b/Example1.RazorPages.IndividualAccounts/Startup.cs
deleted file mode 100644
index 55f72782..00000000
--- a/Example1.RazorPages.IndividualAccounts/Startup.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using AuthPermissions;
-using AuthPermissions.AspNetCore;
-using AuthPermissions.AspNetCore.Services;
-using AuthPermissions.AspNetCore.StartupServices;
-using Example1.RazorPages.IndividualAccounts.Data;
-using Example1.RazorPages.IndividualAccounts.PermissionsCode;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Identity;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using RunMethodsSequentially;
-
-namespace Example1.RazorPages.IndividualAccounts
-{
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- public IConfiguration Configuration { get; }
-
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddDatabaseDeveloperPageExceptionFilter();
-
- services.AddDbContext(opt =>
- opt.UseInMemoryDatabase(nameof(ApplicationDbContext)));
-
- services.AddDefaultIdentity(
- options => options.SignIn.RequireConfirmedAccount = false)
- .AddEntityFrameworkStores();
-
- //Example of configure a page as only shown if you log in
- services.AddRazorPages(options =>
- {
- options.Conventions.AuthorizePage("/AuthBuiltIn/LoggedInConfigure");
- });
-
- services.RegisterAuthPermissions()
- .UsingInMemoryDatabase()
- .IndividualAccountsAuthentication()
- .AddRolesPermissionsIfEmpty(AppAuthSetupData.RolesDefinition)
- .AddAuthUsersIfEmpty(AppAuthSetupData.UsersWithRolesDefinition)
- .RegisterAuthenticationProviderReader()
- .RegisterFindUserInfoService()
- .AddSuperUserToIndividualAccounts()
- .SetupAspNetCoreAndDatabase(options =>
- {
- //Migrate individual account database
- options.RegisterServiceToRunInJob>();
- //Add demo users to the database
- options.RegisterServiceToRunInJob();
- });
- }
-
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- app.UseMigrationsEndPoint();
- }
- else
- {
- app.UseExceptionHandler("/Error");
- // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
- app.UseHsts();
- }
-
- app.UseHttpsRedirection();
- app.UseStaticFiles();
-
- app.UseRouting();
-
- app.UseAuthentication();
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapRazorPages();
- });
- }
- }
-}
diff --git a/Example1.RazorPages.IndividualAccounts/appsettings.json b/Example1.RazorPages.IndividualAccounts/appsettings.json
index d0f520ea..11f69d3b 100644
--- a/Example1.RazorPages.IndividualAccounts/appsettings.json
+++ b/Example1.RazorPages.IndividualAccounts/appsettings.json
@@ -1,6 +1,6 @@
{
"ConnectionStrings": {
- "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-Example1.RazorPages.IndividualAccounts;Trusted_Connection=True;MultipleActiveResultSets=true"
+ //Example1 uses Sqlite in-memory database
},
"Logging": {
"LogLevel": {
@@ -15,5 +15,5 @@
"Email": "Super@g1.com",
"Password": "Super@g1.com"
},
- "DemoUsers": "Trainee@g1.com,Staff@g1.com,Mananger@g1.com"
+ "DemoUsers": "Trainee@g1.com,Staff@g1.com,Manager@g1.com"
}