diff --git a/docs/Architecting and Developing Modern Web Applications with ASP.NET Core and Azure.pdf b/docs/Architecting and Developing Modern Web Applications with ASP.NET Core and Azure.pdf index 19871d0..080b396 100644 Binary files a/docs/Architecting and Developing Modern Web Applications with ASP.NET Core and Azure.pdf and b/docs/Architecting and Developing Modern Web Applications with ASP.NET Core and Azure.pdf differ diff --git a/src/ApplicationCore/Entities/CatalogBrand.cs b/src/ApplicationCore/Entities/CatalogBrand.cs index 5c1e493..ffa6d0f 100644 --- a/src/ApplicationCore/Entities/CatalogBrand.cs +++ b/src/ApplicationCore/Entities/CatalogBrand.cs @@ -1,4 +1,6 @@ -namespace Microsoft.eShopWeb.ApplicationCore.Entities +using System.Collections.Generic; + +namespace Microsoft.eShopWeb.ApplicationCore.Entities { public class CatalogBrand : BaseEntity { diff --git a/src/Web/Infrastructure/CatalogContext.cs b/src/Web/Infrastructure/CatalogContext.cs index 576a9c2..066025f 100644 --- a/src/Web/Infrastructure/CatalogContext.cs +++ b/src/Web/Infrastructure/CatalogContext.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.eShopWeb.ApplicationCore.Entities; + namespace Microsoft.eShopWeb.Infrastructure { diff --git a/src/Web/Services/CachedCatalogService.cs b/src/Web/Services/CachedCatalogService.cs new file mode 100644 index 0000000..c17daff --- /dev/null +++ b/src/Web/Services/CachedCatalogService.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.eShopWeb.ViewModels; +using Microsoft.Extensions.Caching.Memory; +using System; + +namespace Microsoft.eShopWeb.Services +{ + public class CachedCatalogService : ICatalogService + { + private readonly IMemoryCache _cache; + private readonly CatalogService _catalogService; + private static readonly string _brandsKey = "brands"; + private static readonly string _typesKey = "types"; + private static readonly string _itemsKeyTemplate = "items-{0}-{1}-{2}-{3}"; + private static readonly TimeSpan _defaultCacheDuration = TimeSpan.FromSeconds(30); + + public CachedCatalogService(IMemoryCache cache, + CatalogService catalogService) + { + _cache = cache; + _catalogService = catalogService; + } + + public async Task> GetBrands() + { + return await _cache.GetOrCreateAsync(_brandsKey, async entry => + { + entry.SlidingExpiration = _defaultCacheDuration; + return await _catalogService.GetBrands(); + }); + } + + public async Task GetCatalogItems(int pageIndex, int itemsPage, int? brandID, int? typeId) + { + string cacheKey = String.Format(_itemsKeyTemplate, pageIndex, itemsPage, brandID, typeId); + return await _cache.GetOrCreateAsync(cacheKey, async entry => + { + entry.SlidingExpiration = _defaultCacheDuration; + return await _catalogService.GetCatalogItems(pageIndex, itemsPage, brandID, typeId); + }); + } + + public async Task> GetTypes() + { + return await _cache.GetOrCreateAsync(_typesKey, async entry => + { + entry.SlidingExpiration = _defaultCacheDuration; + return await _catalogService.GetTypes(); + }); + } + } +} diff --git a/src/Web/Services/CatalogService.cs b/src/Web/Services/CatalogService.cs index b399350..52dbed9 100644 --- a/src/Web/Services/CatalogService.cs +++ b/src/Web/Services/CatalogService.cs @@ -7,6 +7,9 @@ using Microsoft.Extensions.Options; using Microsoft.eShopWeb.Infrastructure; using Microsoft.eShopWeb.ViewModels; using Microsoft.eShopWeb.ApplicationCore.Entities; +using System.Data.SqlClient; +using Dapper; +using Microsoft.Extensions.Logging; namespace Microsoft.eShopWeb.Services { @@ -14,15 +17,20 @@ namespace Microsoft.eShopWeb.Services { private readonly CatalogContext _context; private readonly IOptionsSnapshot _settings; + private readonly ILogger _logger; - public CatalogService(CatalogContext context, IOptionsSnapshot settings) + public CatalogService(CatalogContext context, + IOptionsSnapshot settings, + ILoggerFactory loggerFactory) { _context = context; - _settings = settings; + _settings = settings; + _logger = loggerFactory.CreateLogger(); } public async Task GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId) { + _logger.LogInformation("GetCatalogItems called."); var root = (IQueryable)_context.CatalogItems; if (typeId.HasValue) @@ -50,7 +58,29 @@ namespace Microsoft.eShopWeb.Services public async Task> GetBrands() { + _logger.LogInformation("GetBrands called."); var brands = await _context.CatalogBrands.ToListAsync(); + +//// create +//var newBrand = new CatalogBrand() { Brand = "Acme" }; +//_context.Add(newBrand); +//await _context.SaveChangesAsync(); + +//// read and update +//var existingBrand = _context.Find(1); +//existingBrand.Brand = "Updated Brand"; +//await _context.SaveChangesAsync(); + +//// delete +//var brandToDelete = _context.Find(2); +//_context.CatalogBrands.Remove(brandToDelete); +//await _context.SaveChangesAsync(); + +//var brandsWithItems = await _context.CatalogBrands +// .Include(b => b.Items) +// .ToListAsync(); + + var items = new List { new SelectListItem() { Value = null, Text = "All", Selected = true } @@ -65,6 +95,7 @@ namespace Microsoft.eShopWeb.Services public async Task> GetTypes() { + _logger.LogInformation("GetTypes called."); var types = await _context.CatalogTypes.ToListAsync(); var items = new List { @@ -88,5 +119,16 @@ namespace Microsoft.eShopWeb.Services return items; } + + //public async Task> GetCatalogTypes() + //{ + // return await _context.CatalogTypes.ToListAsync(); + //} + + //private readonly SqlConnection _conn; + //public async Task> GetCatalogTypesWithDapper() + //{ + // return await _conn.QueryAsync("SELECT * FROM CatalogType"); + //} } } diff --git a/src/Web/Startup.cs b/src/Web/Startup.cs index 35ad1d7..0bf788f 100644 --- a/src/Web/Startup.cs +++ b/src/Web/Startup.cs @@ -9,11 +9,14 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Infrastructure.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using System.Text; +using Microsoft.AspNetCore.Http; namespace Microsoft.eShopWeb { public class Startup { + private IServiceCollection _services; public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() @@ -35,8 +38,8 @@ namespace Microsoft.eShopWeb { try { - c.UseInMemoryDatabase("Catalog"); - //c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection")); + //c.UseInMemoryDatabase("Catalog"); + c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection")); c.ConfigureWarnings(wb => { //By default, in this application, we don't want to have client evaluations @@ -51,17 +54,20 @@ namespace Microsoft.eShopWeb // Add Identity DbContext services.AddDbContext(options => - options.UseInMemoryDatabase("Identity")); -// options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection"))); + //options.UseInMemoryDatabase("Identity")); + options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection"))); services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); - - services.AddTransient(); + services.AddMemoryCache(); + services.AddScoped(); + services.AddScoped(); services.Configure(Configuration); services.AddMvc(); + + _services = services; } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -74,6 +80,25 @@ namespace Microsoft.eShopWeb { app.UseDeveloperExceptionPage(); app.UseBrowserLink(); + + app.Map("/allservices", builder => builder.Run(async context => + { + var sb = new StringBuilder(); + sb.Append("

All Services

"); + sb.Append(""); + sb.Append(""); + sb.Append(""); + foreach (var svc in _services) + { + sb.Append(""); + sb.Append($""); + sb.Append($""); + sb.Append($""); + sb.Append(""); + } + sb.Append("
TypeLifetimeInstance
{svc.ServiceType.FullName}{svc.Lifetime}{svc.ImplementationType?.FullName}
"); + await context.Response.WriteAsync(sb.ToString()); + })); } else { diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 7714b09..cc12cec 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -11,6 +11,7 @@ + @@ -20,6 +21,7 @@ + diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index c3ebcd8..44433fe 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -7,7 +7,8 @@ "Logging": { "IncludeScopes": false, "LogLevel": { - "Default": "Warning" + "Default": "Warning", + "Microsoft" : "Warning" } } }