Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.

Commit 7a6e07c

Browse files
ReubenBondtjain-ms
authored andcommitted
WebMVC: Migrate to WebApplicationBuilder and delete Startup
1 parent 242cbea commit 7a6e07c

File tree

7 files changed

+147
-244
lines changed

7 files changed

+147
-244
lines changed

src/Web/WebMVC/AppSettings.cs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,7 @@
22

33
public class AppSettings
44
{
5-
//public Connectionstrings ConnectionStrings { get; set; }
65
public string PurchaseUrl { get; set; }
76
public string SignalrHubUrl { get; set; }
8-
public bool ActivateCampaignDetailFunction { get; set; }
9-
public Logging Logging { get; set; }
107
public bool UseCustomizationData { get; set; }
118
}
12-
13-
public class Connectionstrings
14-
{
15-
public string DefaultConnection { get; set; }
16-
}
17-
18-
public class Logging
19-
{
20-
public bool IncludeScopes { get; set; }
21-
public Loglevel LogLevel { get; set; }
22-
}
23-
24-
public class Loglevel
25-
{
26-
public string Default { get; set; }
27-
public string System { get; set; }
28-
public string Microsoft { get; set; }
29-
}

src/Web/WebMVC/Controllers/TestController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public async Task<IActionResult> Ocelot()
3232
BasketId = _appUserParser.Parse(User).Id
3333
};
3434

35-
var content = new StringContent(JsonSerializer.Serialize(payload), System.Text.Encoding.UTF8, "application/json");
35+
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
3636

3737

3838
var response = await _client.CreateClient(nameof(IBasketService))

src/Web/WebMVC/Infrastructure/WebContextSeed.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ public class WebContextSeed
55
{
66
public static void Seed(IApplicationBuilder applicationBuilder, IWebHostEnvironment env)
77
{
8-
var log = Serilog.Log.Logger;
8+
var log = Log.Logger;
99

1010
var settings = (AppSettings)applicationBuilder
1111
.ApplicationServices.GetRequiredService<IOptions<AppSettings>>().Value;

src/Web/WebMVC/Program.cs

Lines changed: 139 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,70 @@
1-
var configuration = GetConfiguration();
1+
var builder = WebApplication.CreateBuilder(args);
2+
builder.Services.AddControllersWithViews();
23

3-
Log.Logger = CreateSerilogLogger(configuration);
4+
AddApplicationInsights(builder);
5+
AddHealthChecks(builder);
6+
AddCustomMvc(builder);
7+
AddHttpClientServices(builder);
8+
AddCustomAuthentication(builder);
49

5-
try
6-
{
7-
Log.Information("Configuring web host ({ApplicationContext})...", Program.AppName);
8-
var host = BuildWebHost(configuration, args);
10+
builder.WebHost.CaptureStartupErrors(false);
11+
builder.Host.UseSerilog(CreateSerilogLogger(builder.Configuration));
912

10-
Log.Information("Starting web host ({ApplicationContext})...", Program.AppName);
11-
host.Run();
13+
var app = builder.Build();
1214

13-
return 0;
15+
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
16+
if (app.Environment.IsDevelopment())
17+
{
18+
app.UseDeveloperExceptionPage();
1419
}
15-
catch (Exception ex)
20+
else
1621
{
17-
Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", Program.AppName);
18-
return 1;
22+
app.UseExceptionHandler("/Error");
1923
}
20-
finally
24+
25+
var pathBase = builder.Configuration["PATH_BASE"];
26+
27+
if (!string.IsNullOrEmpty(pathBase))
2128
{
22-
Log.CloseAndFlush();
29+
app.UsePathBase(pathBase);
2330
}
2431

25-
IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
26-
WebHost.CreateDefaultBuilder(args)
27-
.CaptureStartupErrors(false)
28-
.ConfigureAppConfiguration(x => x.AddConfiguration(configuration))
29-
.UseStartup<Startup>()
30-
.UseSerilog()
31-
.Build();
32+
app.UseStaticFiles();
33+
app.UseSession();
34+
35+
WebContextSeed.Seed(app, app.Environment);
36+
37+
// Fix samesite issue when running eShop from docker-compose locally as by default http protocol is being used
38+
// Refer to https://github.com/dotnet-architecture/eShopOnContainers/issues/1391
39+
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax });
40+
41+
app.UseRouting();
42+
43+
app.UseAuthentication();
44+
app.UseAuthorization();
45+
46+
app.MapControllerRoute("default", "{controller=Catalog}/{action=Index}/{id?}");
47+
app.MapControllerRoute("defaultError", "{controller=Error}/{action=Error}");
48+
app.MapControllers();
49+
app.MapHealthChecks("/liveness", new HealthCheckOptions
50+
{
51+
Predicate = r => r.Name.Contains("self")
52+
});
53+
app.MapHealthChecks("/hc", new HealthCheckOptions()
54+
{
55+
Predicate = _ => true,
56+
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
57+
});
58+
59+
await app.RunAsync();
3260

3361
Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
3462
{
3563
var seqServerUrl = configuration["Serilog:SeqServerUrl"];
3664
var logstashUrl = configuration["Serilog:LogstashgUrl"];
3765
var cfg = new LoggerConfiguration()
3866
.ReadFrom.Configuration(configuration)
39-
.Enrich.WithProperty("ApplicationContext", Program.AppName)
67+
.Enrich.WithProperty("ApplicationContext", AppName)
4068
.Enrich.FromLogContext()
4169
.WriteTo.Console();
4270
if (!string.IsNullOrWhiteSpace(seqServerUrl))
@@ -50,19 +78,100 @@ Serilog.ILogger CreateSerilogLogger(IConfiguration configuration)
5078
return cfg.CreateLogger();
5179
}
5280

53-
IConfiguration GetConfiguration()
81+
static void AddApplicationInsights(WebApplicationBuilder builder)
82+
{
83+
builder.Services.AddApplicationInsightsTelemetry(builder.Configuration);
84+
builder.Services.AddApplicationInsightsKubernetesEnricher();
85+
}
86+
87+
static void AddHealthChecks(WebApplicationBuilder builder)
88+
{
89+
builder.Services.AddHealthChecks()
90+
.AddCheck("self", () => HealthCheckResult.Healthy())
91+
.AddUrlGroup(new Uri(builder.Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" });
92+
}
93+
94+
static void AddCustomMvc(WebApplicationBuilder builder)
5495
{
55-
var builder = new ConfigurationBuilder()
56-
.SetBasePath(Directory.GetCurrentDirectory())
57-
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
58-
.AddEnvironmentVariables();
96+
builder.Services.AddOptions()
97+
.Configure<AppSettings>(builder.Configuration)
98+
.AddSession()
99+
.AddDistributedMemoryCache();
59100

60-
return builder.Build();
101+
if (builder.Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
102+
{
103+
builder.Services.AddDataProtection(opts =>
104+
{
105+
opts.ApplicationDiscriminator = "eshop.webmvc";
106+
})
107+
.PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(builder.Configuration["DPConnectionString"]), "DataProtection-Keys");
108+
}
109+
}
110+
111+
// Adds all Http client services
112+
static void AddHttpClientServices(WebApplicationBuilder builder)
113+
{
114+
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
115+
116+
//register delegating handlers
117+
builder.Services.AddTransient<HttpClientAuthorizationDelegatingHandler>()
118+
.AddTransient<HttpClientRequestIdDelegatingHandler>();
119+
120+
//set 5 min as the lifetime for each HttpMessageHandler int the pool
121+
builder.Services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5));
122+
123+
//add http client services
124+
builder.Services.AddHttpClient<IBasketService, BasketService>()
125+
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes
126+
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
127+
128+
builder.Services.AddHttpClient<ICatalogService, CatalogService>();
129+
130+
builder.Services.AddHttpClient<IOrderingService, OrderingService>()
131+
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
132+
.AddHttpMessageHandler<HttpClientRequestIdDelegatingHandler>();
133+
134+
135+
//add custom application services
136+
builder.Services.AddTransient<IIdentityParser<ApplicationUser>, IdentityParser>();
61137
}
62138

139+
static void AddCustomAuthentication(WebApplicationBuilder builder)
140+
{
141+
var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl");
142+
var callBackUrl = builder.Configuration.GetValue<string>("CallBackUrl");
143+
var sessionCookieLifetime = builder.Configuration.GetValue("SessionCookieLifetimeMinutes", 60);
144+
145+
// Add Authentication services
146+
147+
builder.Services.AddAuthentication(options =>
148+
{
149+
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
150+
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
151+
})
152+
.AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime))
153+
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
154+
{
155+
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
156+
options.Authority = identityUrl.ToString();
157+
options.SignedOutRedirectUri = callBackUrl.ToString();
158+
options.ClientId = "mvc";
159+
options.ClientSecret = "secret";
160+
options.ResponseType = "code";
161+
options.SaveTokens = true;
162+
options.GetClaimsFromUserInfoEndpoint = true;
163+
options.RequireHttpsMetadata = false;
164+
options.Scope.Add("openid");
165+
options.Scope.Add("profile");
166+
options.Scope.Add("orders");
167+
options.Scope.Add("basket");
168+
options.Scope.Add("webshoppingagg");
169+
options.Scope.Add("orders.signalrhub");
170+
options.Scope.Add("webhooks");
171+
});
172+
}
63173

64174
public partial class Program
65175
{
66-
private static readonly string _namespace = typeof(Startup).Namespace;
67-
public static readonly string AppName = _namespace.Substring(_namespace.LastIndexOf('.', _namespace.LastIndexOf('.') - 1) + 1);
176+
public static readonly string AppName = typeof(Program).Assembly.GetName().Name;
68177
}

src/Web/WebMVC/Services/BasketService.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public async Task<Basket> UpdateBasket(Basket basket)
3939
{
4040
var uri = API.Basket.UpdateBasket(_basketByPassUrl);
4141

42-
var basketContent = new StringContent(JsonSerializer.Serialize(basket), System.Text.Encoding.UTF8, "application/json");
42+
var basketContent = new StringContent(JsonSerializer.Serialize(basket), Encoding.UTF8, "application/json");
4343

4444
var response = await _apiClient.PostAsync(uri, basketContent);
4545

@@ -51,7 +51,7 @@ public async Task<Basket> UpdateBasket(Basket basket)
5151
public async Task Checkout(BasketDTO basket)
5252
{
5353
var uri = API.Basket.CheckoutBasket(_basketByPassUrl);
54-
var basketContent = new StringContent(JsonSerializer.Serialize(basket), System.Text.Encoding.UTF8, "application/json");
54+
var basketContent = new StringContent(JsonSerializer.Serialize(basket), Encoding.UTF8, "application/json");
5555

5656
_logger.LogInformation("Uri chechout {uri}", uri);
5757

@@ -74,7 +74,7 @@ public async Task<Basket> SetQuantities(ApplicationUser user, Dictionary<string,
7474
}).ToArray()
7575
};
7676

77-
var basketContent = new StringContent(JsonSerializer.Serialize(basketUpdate), System.Text.Encoding.UTF8, "application/json");
77+
var basketContent = new StringContent(JsonSerializer.Serialize(basketUpdate), Encoding.UTF8, "application/json");
7878

7979
var response = await _apiClient.PutAsync(uri, basketContent);
8080

@@ -113,7 +113,7 @@ public async Task AddItemToBasket(ApplicationUser user, int productId)
113113
Quantity = 1
114114
};
115115

116-
var basketContent = new StringContent(JsonSerializer.Serialize(newItem), System.Text.Encoding.UTF8, "application/json");
116+
var basketContent = new StringContent(JsonSerializer.Serialize(newItem), Encoding.UTF8, "application/json");
117117

118118
var response = await _apiClient.PostAsync(uri, basketContent);
119119
}

src/Web/WebMVC/Services/OrderingService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ async public Task CancelOrder(string orderId)
5555
};
5656

5757
var uri = API.Order.CancelOrder(_remoteServiceBaseUrl);
58-
var orderContent = new StringContent(JsonSerializer.Serialize(order), System.Text.Encoding.UTF8, "application/json");
58+
var orderContent = new StringContent(JsonSerializer.Serialize(order), Encoding.UTF8, "application/json");
5959

6060
var response = await _httpClient.PutAsync(uri, orderContent);
6161

@@ -75,7 +75,7 @@ async public Task ShipOrder(string orderId)
7575
};
7676

7777
var uri = API.Order.ShipOrder(_remoteServiceBaseUrl);
78-
var orderContent = new StringContent(JsonSerializer.Serialize(order), System.Text.Encoding.UTF8, "application/json");
78+
var orderContent = new StringContent(JsonSerializer.Serialize(order), Encoding.UTF8, "application/json");
7979

8080
var response = await _httpClient.PutAsync(uri, orderContent);
8181

0 commit comments

Comments
 (0)