Skip to content

Commit 18e6dc4

Browse files
committed
Merge branch 'features/net21rc1' of https://github.com/dotnet-architecture/eShopOnContainers into features/net21rc1
2 parents 684aa49 + cf4b7ff commit 18e6dc4

6 files changed

Lines changed: 288 additions & 139 deletions

File tree

src/Web/WebMVC/Controllers/CartController.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ public async Task<IActionResult> AddToCart(CatalogItem productDetails)
7171
{
7272
var user = _appUserParser.Parse(HttpContext.User);
7373
await _basketSvc.AddItemToBasket(user, productDetails.Id);
74-
//await _basketSvc.AddItemToBasket(user, product);
7574
}
7675
return RedirectToAction("Index", "Catalog");
7776
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using Microsoft.AspNetCore.Authentication;
2+
using Microsoft.AspNetCore.Http;
3+
using System.Collections.Generic;
4+
using System.Net.Http;
5+
using System.Net.Http.Headers;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
namespace WebMVC.Infrastructure
10+
{
11+
public class HttpClientAuthorizationDelegatingHandler
12+
: DelegatingHandler
13+
{
14+
private readonly IHttpContextAccessor _httpContextAccesor;
15+
16+
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
17+
{
18+
_httpContextAccesor = httpContextAccesor;
19+
}
20+
21+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
22+
{
23+
var authorizationHeader = _httpContextAccesor.HttpContext
24+
.Request.Headers["Authorization"];
25+
26+
if (!string.IsNullOrEmpty(authorizationHeader))
27+
{
28+
request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
29+
}
30+
31+
var token = await GetToken();
32+
33+
if (token != null)
34+
{
35+
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
36+
}
37+
38+
return await base.SendAsync(request, cancellationToken);
39+
}
40+
41+
async Task<string> GetToken()
42+
{
43+
const string ACCESS_TOKEN = "access_token";
44+
45+
return await _httpContextAccesor.HttpContext
46+
.GetTokenAsync(ACCESS_TOKEN);
47+
}
48+
}
49+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using Microsoft.Extensions.Logging;
2+
using Polly;
3+
using System;
4+
using System.Net.Http;
5+
6+
namespace WebMVC.Infrastructure
7+
{
8+
public class HttpClientDefaultPolicies
9+
{
10+
const int RETRY_COUNT = 6;
11+
const int EXCEPTIONS_ALLOWED_BEFORE_CIRCUIT_BREAKER = 5;
12+
13+
private readonly ILogger<HttpClientDefaultPolicies> _logger;
14+
15+
public HttpClientDefaultPolicies(ILogger<HttpClientDefaultPolicies> logger)
16+
{
17+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
18+
}
19+
20+
public Policy GetWaitAndRetryPolicy()
21+
{
22+
return Policy.Handle<HttpRequestException>()
23+
.WaitAndRetryAsync(
24+
// number of retries
25+
RETRY_COUNT,
26+
// exponential backofff
27+
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
28+
// on retry
29+
(exception, timeSpan, retryCount, context) =>
30+
{
31+
var msg = $"Retry {retryCount} implemented with Polly's RetryPolicy " +
32+
$"of {context.PolicyKey} " +
33+
$"at {context.OperationKey}, " +
34+
$"due to: {exception}.";
35+
_logger.LogWarning(msg);
36+
_logger.LogDebug(msg);
37+
});
38+
}
39+
40+
public Policy GetCircuitBreakerPolicy()
41+
{
42+
return Policy.Handle<HttpRequestException>()
43+
.CircuitBreakerAsync(
44+
// number of exceptions before breaking circuit
45+
EXCEPTIONS_ALLOWED_BEFORE_CIRCUIT_BREAKER,
46+
// time circuit opened before retry
47+
TimeSpan.FromMinutes(1),
48+
(exception, duration) =>
49+
{
50+
// on circuit opened
51+
_logger.LogTrace("Circuit breaker opened");
52+
},
53+
() =>
54+
{
55+
// on circuit closed
56+
_logger.LogTrace("Circuit breaker reset");
57+
});
58+
}
59+
}
60+
}
Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
using Microsoft.AspNetCore.Authentication;
2-
using Microsoft.AspNetCore.Http;
3-
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
4-
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
1+
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
52
using Microsoft.Extensions.Options;
63
using Newtonsoft.Json;
74
using System.Collections.Generic;
85
using System.Linq;
6+
using System.Net.Http;
97
using System.Threading.Tasks;
108
using WebMVC.Infrastructure;
119
using WebMVC.Models;
@@ -15,29 +13,26 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
1513
public class BasketService : IBasketService
1614
{
1715
private readonly IOptionsSnapshot<AppSettings> _settings;
18-
private readonly IHttpClient _apiClient;
16+
private readonly HttpClient _apiClient;
1917
private readonly string _basketByPassUrl;
2018
private readonly string _purchaseUrl;
21-
private readonly IHttpContextAccessor _httpContextAccesor;
2219

2320
private readonly string _bffUrl;
2421

25-
public BasketService(IOptionsSnapshot<AppSettings> settings,
26-
IHttpContextAccessor httpContextAccesor, IHttpClient httpClient)
22+
public BasketService(HttpClient httpClient,IOptionsSnapshot<AppSettings> settings)
2723
{
24+
_apiClient = httpClient;
2825
_settings = settings;
26+
2927
_basketByPassUrl = $"{_settings.Value.PurchaseUrl}/api/v1/b/basket";
3028
_purchaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1";
31-
_httpContextAccesor = httpContextAccesor;
32-
_apiClient = httpClient;
3329
}
3430

3531
public async Task<Basket> GetBasket(ApplicationUser user)
3632
{
37-
var token = await GetUserTokenAsync();
3833
var getBasketUri = API.Basket.GetBasket(_basketByPassUrl, user.Id);
3934

40-
var dataString = await _apiClient.GetStringAsync(getBasketUri, token);
35+
var dataString = await _apiClient.GetStringAsync(getBasketUri);
4136

4237
return string.IsNullOrEmpty(dataString) ?
4338
new Basket() { BuyerId = user.Id} :
@@ -46,10 +41,10 @@ public async Task<Basket> GetBasket(ApplicationUser user)
4641

4742
public async Task<Basket> UpdateBasket(Basket basket)
4843
{
49-
var token = await GetUserTokenAsync();
5044
var updateBasketUri = API.Basket.UpdateBasket(_basketByPassUrl);
45+
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
5146

52-
var response = await _apiClient.PostAsync(updateBasketUri, basket, token);
47+
var response = await _apiClient.PostAsync(updateBasketUri, content);
5348

5449
response.EnsureSuccessStatusCode();
5550

@@ -58,65 +53,63 @@ public async Task<Basket> UpdateBasket(Basket basket)
5853

5954
public async Task Checkout(BasketDTO basket)
6055
{
61-
var token = await GetUserTokenAsync();
6256
var updateBasketUri = API.Basket.CheckoutBasket(_basketByPassUrl);
57+
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
6358

64-
var response = await _apiClient.PostAsync(updateBasketUri, basket, token);
59+
var response = await _apiClient.PostAsync(updateBasketUri, content);
6560

6661
response.EnsureSuccessStatusCode();
6762
}
6863

6964
public async Task<Basket> SetQuantities(ApplicationUser user, Dictionary<string, int> quantities)
7065
{
7166

72-
var token = await GetUserTokenAsync();
7367
var updateBasketUri = API.Purchase.UpdateBasketItem(_purchaseUrl);
74-
var userId = user.Id;
75-
76-
var response = await _apiClient.PutAsync(updateBasketUri, new
68+
var basketUpdate = new
7769
{
78-
BasketId = userId,
70+
BasketId = user.Id,
7971
Updates = quantities.Select(kvp => new
8072
{
8173
BasketItemId = kvp.Key,
8274
NewQty = kvp.Value
8375
}).ToArray()
84-
}, token);
76+
};
77+
78+
var content = new StringContent(JsonConvert.SerializeObject(basketUpdate), System.Text.Encoding.UTF8, "application/json");
79+
80+
var response = await _apiClient.PutAsync(updateBasketUri,content);
8581

8682
response.EnsureSuccessStatusCode();
83+
8784
var jsonResponse = await response.Content.ReadAsStringAsync();
85+
8886
return JsonConvert.DeserializeObject<Basket>(jsonResponse);
8987
}
9088

9189
public async Task<Order> GetOrderDraft(string basketId)
9290
{
93-
var token = await GetUserTokenAsync();
9491
var draftOrderUri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId);
95-
var json = await _apiClient.GetStringAsync(draftOrderUri, token);
96-
return JsonConvert.DeserializeObject<Order>(json);
92+
var response = await _apiClient.GetStringAsync(draftOrderUri);
93+
94+
return JsonConvert.DeserializeObject<Order>(response);
9795
}
9896

9997

10098

10199
public async Task AddItemToBasket(ApplicationUser user, int productId)
102100
{
103-
var token = await GetUserTokenAsync();
104101
var updateBasketUri = API.Purchase.AddItemToBasket(_purchaseUrl);
105-
var userId = user.Id;
106102

107-
var response = await _apiClient.PostAsync(updateBasketUri, new
103+
var newItem = new
108104
{
109105
CatalogItemId = productId,
110-
BasketId = userId,
106+
BasketId = user.Id,
111107
Quantity = 1
112-
}, token);
108+
};
113109

114-
}
110+
var content = new StringContent(JsonConvert.SerializeObject(newItem), System.Text.Encoding.UTF8, "application/json");
115111

116-
async Task<string> GetUserTokenAsync()
117-
{
118-
var context = _httpContextAccesor.HttpContext;
119-
return await context.GetTokenAsync("access_token");
112+
var response = await _apiClient.PostAsync(updateBasketUri, content);
120113
}
121114
}
122115
}

0 commit comments

Comments
 (0)