From 095b22ca62b0c21c8b97564d392105b303408fbe Mon Sep 17 00:00:00 2001 From: Mihai Borz Date: Mon, 7 Feb 2022 12:35:28 +0100 Subject: [PATCH 1/3] add application insights --- src/Web/Interfaces/IPublishEventService.cs | 16 ++ src/Web/Pages/Basket/Checkout.cshtml.cs | 203 +++++++++--------- src/Web/Pages/Basket/Index.cshtml.cs | 5 +- src/Web/Pages/Basket/Success.cshtml.cs | 21 +- src/Web/Pages/PageBase.cs | 14 ++ src/Web/Properties/serviceDependencies.json | 7 + .../Properties/serviceDependencies.local.json | 7 + src/Web/Services/PublishEventService.cs | 28 +++ src/Web/Startup.cs | 7 +- src/Web/Web.csproj | 1 + src/Web/appsettings.json | 3 + 11 files changed, 197 insertions(+), 115 deletions(-) create mode 100644 src/Web/Interfaces/IPublishEventService.cs create mode 100644 src/Web/Pages/PageBase.cs create mode 100644 src/Web/Properties/serviceDependencies.json create mode 100644 src/Web/Properties/serviceDependencies.local.json create mode 100644 src/Web/Services/PublishEventService.cs diff --git a/src/Web/Interfaces/IPublishEventService.cs b/src/Web/Interfaces/IPublishEventService.cs new file mode 100644 index 000000000..61d6ba46b --- /dev/null +++ b/src/Web/Interfaces/IPublishEventService.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace Microsoft.eShopWeb.Web.Interfaces; + +public enum EventType +{ + PageOpenings, + AddToCart, + Checkout +} + + +public interface IPublishEventService +{ + void PublishEvent(EventType eventType, IDictionary properties); +} diff --git a/src/Web/Pages/Basket/Checkout.cshtml.cs b/src/Web/Pages/Basket/Checkout.cshtml.cs index be616891b..f2b78678f 100644 --- a/src/Web/Pages/Basket/Checkout.cshtml.cs +++ b/src/Web/Pages/Basket/Checkout.cshtml.cs @@ -1,101 +1,102 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate; -using Microsoft.eShopWeb.ApplicationCore.Exceptions; -using Microsoft.eShopWeb.ApplicationCore.Interfaces; -using Microsoft.eShopWeb.Infrastructure.Identity; -using Microsoft.eShopWeb.Web.Interfaces; - -namespace Microsoft.eShopWeb.Web.Pages.Basket; - -[Authorize] -public class CheckoutModel : PageModel -{ - private readonly IBasketService _basketService; - private readonly SignInManager _signInManager; - private readonly IOrderService _orderService; - private string _username = null; - private readonly IBasketViewModelService _basketViewModelService; - private readonly IAppLogger _logger; - - public CheckoutModel(IBasketService basketService, - IBasketViewModelService basketViewModelService, - SignInManager signInManager, - IOrderService orderService, - IAppLogger logger) - { - _basketService = basketService; - _signInManager = signInManager; - _orderService = orderService; - _basketViewModelService = basketViewModelService; - _logger = logger; - } - - public BasketViewModel BasketModel { get; set; } = new BasketViewModel(); - - public async Task OnGet() - { - await SetBasketModelAsync(); - } - - public async Task OnPost(IEnumerable items) - { - try - { - await SetBasketModelAsync(); - - if (!ModelState.IsValid) - { - return BadRequest(); - } - - var updateModel = items.ToDictionary(b => b.Id.ToString(), b => b.Quantity); - await _basketService.SetQuantities(BasketModel.Id, updateModel); - await _orderService.CreateOrderAsync(BasketModel.Id, new Address("123 Main St.", "Kent", "OH", "United States", "44240")); - await _basketService.DeleteBasketAsync(BasketModel.Id); - } - catch (EmptyBasketOnCheckoutException emptyBasketOnCheckoutException) - { - //Redirect to Empty Basket page - _logger.LogWarning(emptyBasketOnCheckoutException.Message); - return RedirectToPage("/Basket/Index"); - } - - return RedirectToPage("Success"); - } - - private async Task SetBasketModelAsync() - { - if (_signInManager.IsSignedIn(HttpContext.User)) - { - BasketModel = await _basketViewModelService.GetOrCreateBasketForUser(User.Identity.Name); - } - else - { - GetOrSetBasketCookieAndUserName(); - BasketModel = await _basketViewModelService.GetOrCreateBasketForUser(_username); - } - } - - private void GetOrSetBasketCookieAndUserName() - { - if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME)) - { - _username = Request.Cookies[Constants.BASKET_COOKIENAME]; - } - if (_username != null) return; - - _username = Guid.NewGuid().ToString(); - var cookieOptions = new CookieOptions(); - cookieOptions.Expires = DateTime.Today.AddYears(10); - Response.Cookies.Append(Constants.BASKET_COOKIENAME, _username, cookieOptions); - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate; +using Microsoft.eShopWeb.ApplicationCore.Exceptions; +using Microsoft.eShopWeb.ApplicationCore.Interfaces; +using Microsoft.eShopWeb.Infrastructure.Identity; +using Microsoft.eShopWeb.Web.Interfaces; + +namespace Microsoft.eShopWeb.Web.Pages.Basket; + +[Authorize] +public class CheckoutModel : PageBase +{ + private readonly IBasketService _basketService; + private readonly SignInManager _signInManager; + private readonly IOrderService _orderService; + private string _username = null; + private readonly IBasketViewModelService _basketViewModelService; + private readonly IAppLogger _logger; + + public CheckoutModel(IBasketService basketService, + IBasketViewModelService basketViewModelService, + SignInManager signInManager, + IOrderService orderService, + IAppLogger logger, + IPublishEventService publishEventService) : base(publishEventService) + { + _basketService = basketService; + _signInManager = signInManager; + _orderService = orderService; + _basketViewModelService = basketViewModelService; + _logger = logger; + } + + public BasketViewModel BasketModel { get; set; } = new BasketViewModel(); + + public async Task OnGet() + { + await SetBasketModelAsync(); + } + + public async Task OnPost(IEnumerable items) + { + try + { + await SetBasketModelAsync(); + + if (!ModelState.IsValid) + { + return BadRequest(); + } + + var updateModel = items.ToDictionary(b => b.Id.ToString(), b => b.Quantity); + await _basketService.SetQuantities(BasketModel.Id, updateModel); + await _orderService.CreateOrderAsync(BasketModel.Id, new Address("123 Main St.", "Kent", "OH", "United States", "44240")); + await _basketService.DeleteBasketAsync(BasketModel.Id); + } + catch (EmptyBasketOnCheckoutException emptyBasketOnCheckoutException) + { + //Redirect to Empty Basket page + _logger.LogWarning(emptyBasketOnCheckoutException.Message); + return RedirectToPage("/Basket/Index"); + } + + return RedirectToPage("Success"); + } + + private async Task SetBasketModelAsync() + { + if (_signInManager.IsSignedIn(HttpContext.User)) + { + BasketModel = await _basketViewModelService.GetOrCreateBasketForUser(User.Identity.Name); + } + else + { + GetOrSetBasketCookieAndUserName(); + BasketModel = await _basketViewModelService.GetOrCreateBasketForUser(_username); + } + } + + private void GetOrSetBasketCookieAndUserName() + { + if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME)) + { + _username = Request.Cookies[Constants.BASKET_COOKIENAME]; + } + if (_username != null) return; + + _username = Guid.NewGuid().ToString(); + var cookieOptions = new CookieOptions(); + cookieOptions.Expires = DateTime.Today.AddYears(10); + Response.Cookies.Append(Constants.BASKET_COOKIENAME, _username, cookieOptions); + } +} diff --git a/src/Web/Pages/Basket/Index.cshtml.cs b/src/Web/Pages/Basket/Index.cshtml.cs index ad42bf784..b5abfd0f8 100644 --- a/src/Web/Pages/Basket/Index.cshtml.cs +++ b/src/Web/Pages/Basket/Index.cshtml.cs @@ -11,13 +11,14 @@ namespace Microsoft.eShopWeb.Web.Pages.Basket; -public class IndexModel : PageModel +public class IndexModel : PageBase { private readonly IBasketService _basketService; private readonly IBasketViewModelService _basketViewModelService; public IndexModel(IBasketService basketService, - IBasketViewModelService basketViewModelService) + IBasketViewModelService basketViewModelService, + IPublishEventService publishService) : base(publishService) { _basketService = basketService; _basketViewModelService = basketViewModelService; diff --git a/src/Web/Pages/Basket/Success.cshtml.cs b/src/Web/Pages/Basket/Success.cshtml.cs index e105aa38e..0c9181690 100644 --- a/src/Web/Pages/Basket/Success.cshtml.cs +++ b/src/Web/Pages/Basket/Success.cshtml.cs @@ -1,18 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - +using Microsoft.AspNetCore.Authorization; +using Microsoft.eShopWeb.Web.Interfaces; + namespace Microsoft.eShopWeb.Web.Pages.Basket; [Authorize] -public class SuccessModel : PageModel -{ +public class SuccessModel : PageBase +{ + + public SuccessModel(IPublishEventService publishEventService) : base(publishEventService) + { + } + public void OnGet() { - } } diff --git a/src/Web/Pages/PageBase.cs b/src/Web/Pages/PageBase.cs new file mode 100644 index 000000000..a68a5e475 --- /dev/null +++ b/src/Web/Pages/PageBase.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.eShopWeb.Web.Interfaces; + +namespace Microsoft.eShopWeb.Web.Pages; + +public abstract class PageBase : PageModel +{ + public PageBase(IPublishEventService publishEventService) + { + publishEventService.PublishEvent(EventType.PageOpenings, new Dictionary {{ "PageName", this.GetType().Name }}); + } + +} diff --git a/src/Web/Properties/serviceDependencies.json b/src/Web/Properties/serviceDependencies.json new file mode 100644 index 000000000..6d97b246e --- /dev/null +++ b/src/Web/Properties/serviceDependencies.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights" + } + } +} \ No newline at end of file diff --git a/src/Web/Properties/serviceDependencies.local.json b/src/Web/Properties/serviceDependencies.local.json new file mode 100644 index 000000000..22c7f0839 --- /dev/null +++ b/src/Web/Properties/serviceDependencies.local.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk" + } + } +} \ No newline at end of file diff --git a/src/Web/Services/PublishEventService.cs b/src/Web/Services/PublishEventService.cs new file mode 100644 index 000000000..c4ddfecca --- /dev/null +++ b/src/Web/Services/PublishEventService.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using Microsoft.ApplicationInsights; +using Microsoft.eShopWeb.Web.Interfaces; + +namespace Microsoft.eShopWeb.Web.Services; + +public class PublishEventService : IPublishEventService +{ + private readonly TelemetryClient _telemetryClient; + + public PublishEventService(TelemetryClient telemetryClient) + { + _telemetryClient = telemetryClient; + } + + + public void PublishEvent(EventType eventType, IDictionary properties) + { + try + { + _telemetryClient.TrackEvent(eventType.ToString(), properties); + } + catch + { + //ignore; + } + } +} diff --git a/src/Web/Startup.cs b/src/Web/Startup.cs index 541ca5861..cb8c7c497 100644 --- a/src/Web/Startup.cs +++ b/src/Web/Startup.cs @@ -22,6 +22,8 @@ using Microsoft.eShopWeb.Infrastructure.Data; using Microsoft.eShopWeb.Infrastructure.Identity; using Microsoft.eShopWeb.Web.Configuration; +using Microsoft.eShopWeb.Web.Interfaces; +using Microsoft.eShopWeb.Web.Services; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; @@ -164,8 +166,11 @@ public void ConfigureServices(IServiceCollection services) services.AddBlazorServices(); services.AddDatabaseDeveloperPageExceptionFilter(); + services.AddApplicationInsightsTelemetry(); + services.AddScoped(); - _services = services; // used to debug registered services + _services = services; // used to debug registered services + } diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index f4d7fd65d..1746a6a21 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -18,6 +18,7 @@ + diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index c2bc65927..e41213306 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -16,5 +16,8 @@ "System": "Warning" }, "AllowedHosts": "*" + }, + "ApplicationInsights": { + "InstrumentationKey": "00000000-0000-0000-0000-000000000000" } } From 489a60d4fd1feed39a687fcb7dd293d4271c409b Mon Sep 17 00:00:00 2001 From: Mihai Borz Date: Mon, 7 Feb 2022 12:40:26 +0100 Subject: [PATCH 2/3] fix issues after merge ? --- src/Web/Pages/Basket/Checkout.cshtml.cs | 2 +- src/Web/Pages/Basket/Success.cshtml.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Web/Pages/Basket/Checkout.cshtml.cs b/src/Web/Pages/Basket/Checkout.cshtml.cs index d10baeb64..2ef417cc7 100644 --- a/src/Web/Pages/Basket/Checkout.cshtml.cs +++ b/src/Web/Pages/Basket/Checkout.cshtml.cs @@ -13,7 +13,7 @@ namespace Microsoft.eShopWeb.Web.Pages.Basket; -public class CheckoutModel : PageModel +public class CheckoutModel : PageBase { private readonly IBasketService _basketService; private readonly IOrderService _orderService; diff --git a/src/Web/Pages/Basket/Success.cshtml.cs b/src/Web/Pages/Basket/Success.cshtml.cs index 43ba839f5..048e380ec 100644 --- a/src/Web/Pages/Basket/Success.cshtml.cs +++ b/src/Web/Pages/Basket/Success.cshtml.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc.RazorPages; - +using Microsoft.eShopWeb.Web.Interfaces; + namespace Microsoft.eShopWeb.Web.Pages.Basket; public class SuccessModel : PageBase From 467a0f180b2ca1ab21f2c1ac0f77b0f52b12416b Mon Sep 17 00:00:00 2001 From: Mihai Borz Date: Tue, 1 Mar 2022 17:48:01 +0100 Subject: [PATCH 3/3] add chackout and add to cart event --- src/Web/Pages/Basket/Checkout.cshtml.cs | 18 ++++++++++++++---- src/Web/Pages/Basket/Index.cshtml.cs | 20 +++++++++++++++----- src/Web/Pages/PageBase.cs | 1 - src/Web/Services/PublishEventService.cs | 1 - 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/Web/Pages/Basket/Checkout.cshtml.cs b/src/Web/Pages/Basket/Checkout.cshtml.cs index 2ef417cc7..e91602c61 100644 --- a/src/Web/Pages/Basket/Checkout.cshtml.cs +++ b/src/Web/Pages/Basket/Checkout.cshtml.cs @@ -19,8 +19,9 @@ public class CheckoutModel : PageBase private readonly IOrderService _orderService; private string _username = null; private readonly IBasketViewModelService _basketViewModelService; - private readonly IAppLogger _logger; - + private readonly IAppLogger _logger; + private readonly IPublishEventService _publishService; + public CheckoutModel(IBasketService basketService, IBasketViewModelService basketViewModelService, IOrderService orderService, @@ -30,7 +31,8 @@ public CheckoutModel(IBasketService basketService, _basketService = basketService; _orderService = orderService; _basketViewModelService = basketViewModelService; - _logger = logger; + _logger = logger; + _publishService = publishEventService; } public BasketViewModel BasketModel { get; set; } = new BasketViewModel(); @@ -53,7 +55,15 @@ public async Task OnPost(IEnumerable items) var updateModel = items.ToDictionary(b => b.Id.ToString(), b => b.Quantity); await _basketService.SetQuantities(BasketModel.Id, updateModel); - await _orderService.CreateOrderAsync(BasketModel.Id, new Address("123 Main St.", "Kent", "OH", "United States", "44240")); + await _orderService.CreateOrderAsync(BasketModel.Id, new Address("123 Main St.", "Kent", "OH", "United States", "44240")); + + var dictionary = new Dictionary + { + { "Username", BasketModel.BuyerId}, + { "Total", BasketModel.Total().ToString()} + }; + + _publishService.PublishEvent(EventType.Checkout, dictionary); await _basketService.DeleteBasketAsync(BasketModel.Id); } catch (EmptyBasketOnCheckoutException emptyBasketOnCheckoutException) diff --git a/src/Web/Pages/Basket/Index.cshtml.cs b/src/Web/Pages/Basket/Index.cshtml.cs index b5abfd0f8..56afed532 100644 --- a/src/Web/Pages/Basket/Index.cshtml.cs +++ b/src/Web/Pages/Basket/Index.cshtml.cs @@ -11,17 +11,19 @@ namespace Microsoft.eShopWeb.Web.Pages.Basket; -public class IndexModel : PageBase +public class IndexModel : PageModel { private readonly IBasketService _basketService; - private readonly IBasketViewModelService _basketViewModelService; - + private readonly IBasketViewModelService _basketViewModelService; + private readonly IPublishEventService _publishService; + public IndexModel(IBasketService basketService, IBasketViewModelService basketViewModelService, - IPublishEventService publishService) : base(publishService) + IPublishEventService publishService) //: base(publishService) { _basketService = basketService; - _basketViewModelService = basketViewModelService; + _basketViewModelService = basketViewModelService; + _publishService = publishService; } public BasketViewModel BasketModel { get; set; } = new BasketViewModel(); @@ -42,6 +44,14 @@ public async Task OnPost(CatalogItemViewModel productDetails) var basket = await _basketService.AddItemToBasket(username, productDetails.Id, productDetails.Price); + var dictionary = new Dictionary + { + { "Username", username}, + { "ProductId", productDetails.Id.ToString()}, + { "Price", productDetails.Price.ToString() } + }; + + _publishService.PublishEvent(EventType.AddToCart, dictionary); BasketModel = await _basketViewModelService.Map(basket); return RedirectToPage(); diff --git a/src/Web/Pages/PageBase.cs b/src/Web/Pages/PageBase.cs index a68a5e475..3c0568f0b 100644 --- a/src/Web/Pages/PageBase.cs +++ b/src/Web/Pages/PageBase.cs @@ -10,5 +10,4 @@ public PageBase(IPublishEventService publishEventService) { publishEventService.PublishEvent(EventType.PageOpenings, new Dictionary {{ "PageName", this.GetType().Name }}); } - } diff --git a/src/Web/Services/PublishEventService.cs b/src/Web/Services/PublishEventService.cs index c4ddfecca..1344075c5 100644 --- a/src/Web/Services/PublishEventService.cs +++ b/src/Web/Services/PublishEventService.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using Microsoft.ApplicationInsights; using Microsoft.eShopWeb.Web.Interfaces; - namespace Microsoft.eShopWeb.Web.Services; public class PublishEventService : IPublishEventService