From 0ab198c20b2017f93d8fd7de52faf38fca3da506 Mon Sep 17 00:00:00 2001 From: Sumit Ghosh Date: Mon, 25 Oct 2021 18:35:51 +0530 Subject: [PATCH] Updates webspa project to Net 6.0 (#1778) * Included globalusing in webspa project * Included file scoped namespace for webspa project * Updated packages in WebSPA project --- src/Web/WebSPA/AppSettings.cs | 24 +- src/Web/WebSPA/GlobalUsings.cs | 27 ++ src/Web/WebSPA/Program.cs | 10 +- .../Server/Controllers/HomeController.cs | 31 +- .../Server/Infrastructure/WebContextSeed.cs | 102 +++---- src/Web/WebSPA/Startup.cs | 273 ++++++++---------- src/Web/WebSPA/WebSPA.csproj | 6 +- 7 files changed, 224 insertions(+), 249 deletions(-) create mode 100644 src/Web/WebSPA/GlobalUsings.cs diff --git a/src/Web/WebSPA/AppSettings.cs b/src/Web/WebSPA/AppSettings.cs index 037ed858f..941a5fdcd 100644 --- a/src/Web/WebSPA/AppSettings.cs +++ b/src/Web/WebSPA/AppSettings.cs @@ -1,20 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +namespace eShopOnContainers.WebSPA; -namespace eShopOnContainers.WebSPA +public class AppSettings { - public class AppSettings - { - public string IdentityUrl { get; set; } - public string BasketUrl { get; set; } - public string MarketingUrl { get; set; } + public string IdentityUrl { get; set; } + public string BasketUrl { get; set; } + public string MarketingUrl { get; set; } - public string PurchaseUrl { get; set; } - public string SignalrHubUrl { get; set; } + public string PurchaseUrl { get; set; } + public string SignalrHubUrl { get; set; } - public string ActivateCampaignDetailFunction { get; set; } - public bool UseCustomizationData { get; set; } - } + public string ActivateCampaignDetailFunction { get; set; } + public bool UseCustomizationData { get; set; } } diff --git a/src/Web/WebSPA/GlobalUsings.cs b/src/Web/WebSPA/GlobalUsings.cs new file mode 100644 index 000000000..eb6145877 --- /dev/null +++ b/src/Web/WebSPA/GlobalUsings.cs @@ -0,0 +1,27 @@ +global using eShopConContainers.WebSPA; +global using Microsoft.AspNetCore; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.Logging; +global using Serilog; +global using System.IO; +global using eShopOnContainers.WebSPA; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Antiforgery; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.DataProtection; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore.SpaServices.AngularCli; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using StackExchange.Redis; +global using System; +global using WebSPA.Infrastructure; +global using Microsoft.Extensions.Options; +global using System.IO.Compression; +global using System.Linq; +global using System.Collections.Generic; +global using System.Threading.Tasks; diff --git a/src/Web/WebSPA/Program.cs b/src/Web/WebSPA/Program.cs index 4351733cf..2631f7fd3 100644 --- a/src/Web/WebSPA/Program.cs +++ b/src/Web/WebSPA/Program.cs @@ -1,12 +1,4 @@ -using eShopConContainers.WebSPA; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Serilog; -using System.IO; - -BuildWebHost(args).Run(); +await BuildWebHost(args).RunAsync(); IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) diff --git a/src/Web/WebSPA/Server/Controllers/HomeController.cs b/src/Web/WebSPA/Server/Controllers/HomeController.cs index 14e8a8871..792995163 100644 --- a/src/Web/WebSPA/Server/Controllers/HomeController.cs +++ b/src/Web/WebSPA/Server/Controllers/HomeController.cs @@ -1,25 +1,18 @@ // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 +namespace eShopConContainers.WebSPA.Server.Controllers; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Options; -using eShopOnContainers.WebSPA; - -namespace eShopConContainers.WebSPA.Server.Controllers +public class HomeController : Controller { - public class HomeController : Controller - { - private readonly IWebHostEnvironment _env; - private readonly IOptionsSnapshot _settings; + private readonly IWebHostEnvironment _env; + private readonly IOptionsSnapshot _settings; - public HomeController(IWebHostEnvironment env, IOptionsSnapshot settings) - { - _env = env; - _settings = settings; - } - public IActionResult Configuration() - { - return Json(_settings.Value); - } + public HomeController(IWebHostEnvironment env, IOptionsSnapshot settings) + { + _env = env; + _settings = settings; } + public IActionResult Configuration() + { + return Json(_settings.Value); + } } diff --git a/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs b/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs index 0273722b6..b23da90bb 100644 --- a/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs +++ b/src/Web/WebSPA/Server/Infrastructure/WebContextSeed.cs @@ -1,77 +1,67 @@ -using eShopOnContainers.WebSPA; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; +namespace WebSPA.Infrastructure; + using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System; -using System.IO; -using System.IO.Compression; -using System.Linq; -namespace WebSPA.Infrastructure +public class WebContextSeed { - public class WebContextSeed + public static void Seed(IApplicationBuilder applicationBuilder, IWebHostEnvironment env, ILoggerFactory loggerFactory) { - public static void Seed(IApplicationBuilder applicationBuilder, IWebHostEnvironment env, ILoggerFactory loggerFactory) + var log = loggerFactory.CreateLogger(); + + var settings = applicationBuilder + .ApplicationServices.GetRequiredService>().Value; + + var useCustomizationData = settings.UseCustomizationData; + var contentRootPath = env.ContentRootPath; + var webroot = env.WebRootPath; + + if (useCustomizationData) { - var log = loggerFactory.CreateLogger(); - - var settings = applicationBuilder - .ApplicationServices.GetRequiredService>().Value; - - var useCustomizationData = settings.UseCustomizationData; - var contentRootPath = env.ContentRootPath; - var webroot = env.WebRootPath; - - if (useCustomizationData) - { - GetPreconfiguredImages(contentRootPath, webroot, log); - } + GetPreconfiguredImages(contentRootPath, webroot, log); } + } - static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger log) + static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger log) + { + try { - try + string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip"); + if (!File.Exists(imagesZipFile)) { - string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip"); - if (!File.Exists(imagesZipFile)) - { - log.LogError("Zip file '{ZipFileName}' does not exists.", imagesZipFile); - return; - } + log.LogError("Zip file '{ZipFileName}' does not exists.", imagesZipFile); + return; + } - string imagePath = Path.Combine(webroot, "assets", "images"); - if (!Directory.Exists(imagePath)) - { - Directory.CreateDirectory(imagePath); - } - string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); + string imagePath = Path.Combine(webroot, "assets", "images"); + if (!Directory.Exists(imagePath)) + { + Directory.CreateDirectory(imagePath); + } + string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); - using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read)) + using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read)) + { + foreach (ZipArchiveEntry entry in zip.Entries) { - foreach (ZipArchiveEntry entry in zip.Entries) + if (!imageFiles.Contains(entry.Name)) { - if (!imageFiles.Contains(entry.Name)) + string destinationFilename = Path.Combine(imagePath, entry.Name); + if (File.Exists(destinationFilename)) { - string destinationFilename = Path.Combine(imagePath, entry.Name); - if (File.Exists(destinationFilename)) - { - File.Delete(destinationFilename); - } - entry.ExtractToFile(destinationFilename); - } - else - { - log.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); + File.Delete(destinationFilename); } + entry.ExtractToFile(destinationFilename); + } + else + { + log.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); } } } - catch (Exception ex) - { - log.LogError(ex, "ERROR in GetPreconfiguredImages: {Message}", ex.Message); - } + } + catch (Exception ex) + { + log.LogError(ex, "ERROR in GetPreconfiguredImages: {Message}", ex.Message); } } } diff --git a/src/Web/WebSPA/Startup.cs b/src/Web/WebSPA/Startup.cs index 3f44de558..a8812bc94 100644 --- a/src/Web/WebSPA/Startup.cs +++ b/src/Web/WebSPA/Startup.cs @@ -1,164 +1,143 @@ -using eShopOnContainers.WebSPA; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Antiforgery; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.SpaServices.AngularCli; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using StackExchange.Redis; -using System; -using System.IO; -using WebSPA.Infrastructure; +namespace eShopConContainers.WebSPA; -namespace eShopConContainers.WebSPA +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + public Startup() + { + var localPath = new Uri(Configuration["ASPNETCORE_URLS"])?.LocalPath ?? "/"; + Configuration["BaseUrl"] = localPath; + } + + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + RegisterAppInsights(services); + + services.AddHealthChecks() + .AddCheck("self", () => HealthCheckResult.Healthy()) + .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }); + + services.Configure(Configuration); + + if (Configuration.GetValue("IsClusterEnv") == bool.TrueString) { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - public Startup() - { - var localPath = new Uri(Configuration["ASPNETCORE_URLS"])?.LocalPath ?? "/"; - Configuration["BaseUrl"] = localPath; - } - - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - RegisterAppInsights(services); - - services.AddHealthChecks() - .AddCheck("self", () => HealthCheckResult.Healthy()) - .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }); - - services.Configure(Configuration); - - if (Configuration.GetValue("IsClusterEnv") == bool.TrueString) + services.AddDataProtection(opts => { - services.AddDataProtection(opts => - { - opts.ApplicationDiscriminator = "eshop.webspa"; - }) - .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys"); + opts.ApplicationDiscriminator = "eshop.webspa"; + }) + .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys"); + } + + // Add Antiforgery services and configure the header name that angular will use by default. + services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN"); + + // Add controllers support and add a global AutoValidateAntiforgeryTokenFilter that will make the application check for an Antiforgery token on all "mutating" requests (POST, PUT, DELETE). + // The AutoValidateAntiforgeryTokenFilter is an internal class registered when we register views, so we need to register controllers and views also. + services.AddControllersWithViews(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute())) + .AddJsonOptions(options => + { + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + }); + + // Setup where the compiled version of our spa application will be, when in production. + services.AddSpaStaticFiles(configuration => + { + configuration.RootPath = "wwwroot"; + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + // Here we add Angular default Antiforgery cookie name on first load. https://angular.io/guide/http#security-xsrf-protection + // This cookie will be read by Angular app and its value will be sent back to the application as the header configured in .AddAntiforgery() + app.Use(next => context => + { + string path = context.Request.Path.Value; + + if ( + string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) || + string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase)) + { + // The request token has to be sent as a JavaScript-readable cookie, + // and Angular uses it by default. + var tokens = antiforgery.GetAndStoreTokens(context); + context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, + new CookieOptions() { HttpOnly = false }); } - // Add Antiforgery services and configure the header name that angular will use by default. - services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN"); + return next(context); + }); - // Add controllers support and add a global AutoValidateAntiforgeryTokenFilter that will make the application check for an Antiforgery token on all "mutating" requests (POST, PUT, DELETE). - // The AutoValidateAntiforgeryTokenFilter is an internal class registered when we register views, so we need to register controllers and views also. - services.AddControllersWithViews(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute())) - .AddJsonOptions(options => - { - options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; - }); + //Seed Data + WebContextSeed.Seed(app, env, loggerFactory); - // Setup where the compiled version of our spa application will be, when in production. - services.AddSpaStaticFiles(configuration => - { - configuration.RootPath = "wwwroot"; - }); + var pathBase = Configuration["PATH_BASE"]; + + if (!string.IsNullOrEmpty(pathBase)) + { + loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + app.UsePathBase(pathBase); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery) + app.UseDefaultFiles(); + app.UseStaticFiles(); + + // this will make the application to respond with the index.html and the rest of the assets present on the configured folder (at AddSpaStaticFiles() (wwwroot)) + if (!env.IsDevelopment()) { + app.UseSpaStaticFiles(); + } + app.UseRouting(); + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions + { + Predicate = r => r.Name.Contains("self") + }); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + }); + + // Handles all still unnatended (by any other middleware) requests by returning the default page of the SPA (wwwroot/index.html). + app.UseSpa(spa => + { + // To learn more about options for serving an Angular SPA from ASP.NET Core, + // see https://go.microsoft.com/fwlink/?linkid=864501 + + // the root of the angular app. (Where the package.json lives) + spa.Options.SourcePath = "Client"; + if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); + { + + // use the SpaServices extension method for angular, that will make the application to run "ng serve" for us, when in development. + spa.UseAngularCliServer(npmScript: "start"); } + }); + } - // Here we add Angular default Antiforgery cookie name on first load. https://angular.io/guide/http#security-xsrf-protection - // This cookie will be read by Angular app and its value will be sent back to the application as the header configured in .AddAntiforgery() - app.Use(next => context => - { - string path = context.Request.Path.Value; - - if ( - string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) || - string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase)) - { - // The request token has to be sent as a JavaScript-readable cookie, - // and Angular uses it by default. - var tokens = antiforgery.GetAndStoreTokens(context); - context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, - new CookieOptions() { HttpOnly = false }); - } - - return next(context); - }); - - //Seed Data - WebContextSeed.Seed(app, env, loggerFactory); - - var pathBase = Configuration["PATH_BASE"]; - - if (!string.IsNullOrEmpty(pathBase)) - { - loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); - app.UsePathBase(pathBase); - } - - app.UseDefaultFiles(); - app.UseStaticFiles(); - - // this will make the application to respond with the index.html and the rest of the assets present on the configured folder (at AddSpaStaticFiles() (wwwroot)) - if (!env.IsDevelopment()) - { - app.UseSpaStaticFiles(); - } - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - }); - - // Handles all still unnatended (by any other middleware) requests by returning the default page of the SPA (wwwroot/index.html). - app.UseSpa(spa => - { - // To learn more about options for serving an Angular SPA from ASP.NET Core, - // see https://go.microsoft.com/fwlink/?linkid=864501 - - // the root of the angular app. (Where the package.json lives) - spa.Options.SourcePath = "Client"; - - if (env.IsDevelopment()) - { - - // use the SpaServices extension method for angular, that will make the application to run "ng serve" for us, when in development. - spa.UseAngularCliServer(npmScript: "start"); - } - }); - } - - private void RegisterAppInsights(IServiceCollection services) - { - services.AddApplicationInsightsTelemetry(Configuration); - services.AddApplicationInsightsKubernetesEnricher(); - } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + services.AddApplicationInsightsKubernetesEnricher(); } } diff --git a/src/Web/WebSPA/WebSPA.csproj b/src/Web/WebSPA/WebSPA.csproj index 185d4ad8f..a59e0fffe 100644 --- a/src/Web/WebSPA/WebSPA.csproj +++ b/src/Web/WebSPA/WebSPA.csproj @@ -37,10 +37,10 @@ - + - - + +