Browse Source
* Moved Privacy, Home page to Razor Pages * Migrating Basket from RazorPages to Web. * Removed BasketController; refactored viewmodels * Moved BasketComponent into Pages/Shared Added auth rules to Startup for Pages Added notes to controllers about Pages usage. * Fixed broken my orders test Consolidated Functional Tests * Fixed logo link to home page Fixed Order Detail Total $ formatmain
committed by
GitHub
42 changed files with 429 additions and 430 deletions
@ -1,112 +0,0 @@ |
|||||
using Microsoft.AspNetCore.Authorization; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.AspNetCore.Identity; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate; |
|
||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces; |
|
||||
using Microsoft.eShopWeb.Infrastructure.Identity; |
|
||||
using Microsoft.eShopWeb.Web.Interfaces; |
|
||||
using Microsoft.eShopWeb.Web.ViewModels; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace Microsoft.eShopWeb.Web.Controllers |
|
||||
{ |
|
||||
[ApiExplorerSettings(IgnoreApi = true)] |
|
||||
[Route("[controller]/[action]")]
|
|
||||
public class BasketController : Controller |
|
||||
{ |
|
||||
private readonly IBasketService _basketService; |
|
||||
private readonly IUriComposer _uriComposer; |
|
||||
private readonly SignInManager<ApplicationUser> _signInManager; |
|
||||
private readonly IAppLogger<BasketController> _logger; |
|
||||
private readonly IOrderService _orderService; |
|
||||
private readonly IBasketViewModelService _basketViewModelService; |
|
||||
|
|
||||
public BasketController(IBasketService basketService, |
|
||||
IBasketViewModelService basketViewModelService, |
|
||||
IOrderService orderService, |
|
||||
IUriComposer uriComposer, |
|
||||
SignInManager<ApplicationUser> signInManager, |
|
||||
IAppLogger<BasketController> logger) |
|
||||
{ |
|
||||
_basketService = basketService; |
|
||||
_uriComposer = uriComposer; |
|
||||
_signInManager = signInManager; |
|
||||
_logger = logger; |
|
||||
_orderService = orderService; |
|
||||
_basketViewModelService = basketViewModelService; |
|
||||
} |
|
||||
|
|
||||
[HttpGet] |
|
||||
public async Task<IActionResult> Index() |
|
||||
{ |
|
||||
var basketModel = await GetBasketViewModelAsync(); |
|
||||
|
|
||||
return View(basketModel); |
|
||||
} |
|
||||
|
|
||||
[HttpPost] |
|
||||
public async Task<IActionResult> Index(Dictionary<string, int> items) |
|
||||
{ |
|
||||
var basketViewModel = await GetBasketViewModelAsync(); |
|
||||
await _basketService.SetQuantities(basketViewModel.Id, items); |
|
||||
|
|
||||
return View(await GetBasketViewModelAsync()); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// POST: /Basket/AddToBasket
|
|
||||
[HttpPost] |
|
||||
public async Task<IActionResult> AddToBasket(CatalogItemViewModel productDetails) |
|
||||
{ |
|
||||
if (productDetails?.Id == null) |
|
||||
{ |
|
||||
return RedirectToAction("Index", "Catalog"); |
|
||||
} |
|
||||
var basketViewModel = await GetBasketViewModelAsync(); |
|
||||
|
|
||||
await _basketService.AddItemToBasket(basketViewModel.Id, productDetails.Id, productDetails.Price, 1); |
|
||||
|
|
||||
return RedirectToAction("Index"); |
|
||||
} |
|
||||
|
|
||||
[HttpPost] |
|
||||
[Authorize] |
|
||||
public async Task<IActionResult> Checkout(Dictionary<string, int> items) |
|
||||
{ |
|
||||
var basketViewModel = await GetBasketViewModelAsync(); |
|
||||
await _basketService.SetQuantities(basketViewModel.Id, items); |
|
||||
|
|
||||
await _orderService.CreateOrderAsync(basketViewModel.Id, new Address("123 Main St.", "Kent", "OH", "United States", "44240")); |
|
||||
|
|
||||
await _basketService.DeleteBasketAsync(basketViewModel.Id); |
|
||||
|
|
||||
return View("Checkout"); |
|
||||
} |
|
||||
|
|
||||
private async Task<BasketViewModel> GetBasketViewModelAsync() |
|
||||
{ |
|
||||
if (_signInManager.IsSignedIn(HttpContext.User)) |
|
||||
{ |
|
||||
return await _basketViewModelService.GetOrCreateBasketForUser(User.Identity.Name); |
|
||||
} |
|
||||
string anonymousId = GetOrSetBasketCookie(); |
|
||||
return await _basketViewModelService.GetOrCreateBasketForUser(anonymousId); |
|
||||
} |
|
||||
|
|
||||
private string GetOrSetBasketCookie() |
|
||||
{ |
|
||||
if (Request.Cookies.ContainsKey(Constants.BASKET_COOKIENAME)) |
|
||||
{ |
|
||||
return Request.Cookies[Constants.BASKET_COOKIENAME]; |
|
||||
} |
|
||||
string anonymousId = Guid.NewGuid().ToString(); |
|
||||
var cookieOptions = new CookieOptions(); |
|
||||
cookieOptions.Expires = DateTime.Today.AddYears(10); |
|
||||
Response.Cookies.Append(Constants.BASKET_COOKIENAME, anonymousId, cookieOptions); |
|
||||
return anonymousId; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,30 +0,0 @@ |
|||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Microsoft.eShopWeb.Web.Services; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace Microsoft.eShopWeb.Web.Controllers |
|
||||
{ |
|
||||
[ApiExplorerSettings(IgnoreApi = true)] |
|
||||
[Route("")] |
|
||||
public class CatalogController : Controller |
|
||||
{ |
|
||||
private readonly ICatalogService _catalogService; |
|
||||
|
|
||||
public CatalogController(ICatalogService catalogService) => _catalogService = catalogService; |
|
||||
|
|
||||
[HttpGet] |
|
||||
[HttpPost] |
|
||||
public async Task<IActionResult> Index(int? brandFilterApplied, int? typesFilterApplied, int? page) |
|
||||
{ |
|
||||
var itemsPage = 10; |
|
||||
var catalogModel = await _catalogService.GetCatalogItems(page ?? 0, itemsPage, brandFilterApplied, typesFilterApplied); |
|
||||
return View(catalogModel); |
|
||||
} |
|
||||
|
|
||||
[HttpGet("Error")] |
|
||||
public IActionResult Error() |
|
||||
{ |
|
||||
return View(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,4 +1,4 @@ |
|||||
namespace Microsoft.eShopWeb.Web.ViewModels |
namespace Microsoft.eShopWeb.Web.Pages.Basket |
||||
{ |
{ |
||||
public class BasketItemViewModel |
public class BasketItemViewModel |
||||
{ |
{ |
||||
@ -0,0 +1,83 @@ |
|||||
|
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.Interfaces; |
||||
|
using Microsoft.eShopWeb.Infrastructure.Identity; |
||||
|
using Microsoft.eShopWeb.Web.Interfaces; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.Pages.Basket |
||||
|
{ |
||||
|
public class CheckoutModel : PageModel |
||||
|
{ |
||||
|
private readonly IBasketService _basketService; |
||||
|
private readonly IUriComposer _uriComposer; |
||||
|
private readonly SignInManager<ApplicationUser> _signInManager; |
||||
|
private readonly IOrderService _orderService; |
||||
|
private string _username = null; |
||||
|
private readonly IBasketViewModelService _basketViewModelService; |
||||
|
|
||||
|
public CheckoutModel(IBasketService basketService, |
||||
|
IBasketViewModelService basketViewModelService, |
||||
|
IUriComposer uriComposer, |
||||
|
SignInManager<ApplicationUser> signInManager, |
||||
|
IOrderService orderService) |
||||
|
{ |
||||
|
_basketService = basketService; |
||||
|
_uriComposer = uriComposer; |
||||
|
_signInManager = signInManager; |
||||
|
_orderService = orderService; |
||||
|
_basketViewModelService = basketViewModelService; |
||||
|
} |
||||
|
|
||||
|
public BasketViewModel BasketModel { get; set; } = new BasketViewModel(); |
||||
|
|
||||
|
public void OnGet() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public async Task<IActionResult> OnPost(Dictionary<string, int> items) |
||||
|
{ |
||||
|
await SetBasketModelAsync(); |
||||
|
|
||||
|
await _basketService.SetQuantities(BasketModel.Id, items); |
||||
|
|
||||
|
await _orderService.CreateOrderAsync(BasketModel.Id, new Address("123 Main St.", "Kent", "OH", "United States", "44240")); |
||||
|
|
||||
|
await _basketService.DeleteBasketAsync(BasketModel.Id); |
||||
|
|
||||
|
return RedirectToPage(); |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,92 @@ |
|||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.Identity; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
using Microsoft.eShopWeb.ApplicationCore.Interfaces; |
||||
|
using Microsoft.eShopWeb.Infrastructure.Identity; |
||||
|
using Microsoft.eShopWeb.Web.Interfaces; |
||||
|
using Microsoft.eShopWeb.Web.ViewModels; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.Pages.Basket |
||||
|
{ |
||||
|
public class IndexModel : PageModel |
||||
|
{ |
||||
|
private readonly IBasketService _basketService; |
||||
|
private const string _basketSessionKey = "basketId"; |
||||
|
private readonly IUriComposer _uriComposer; |
||||
|
private readonly SignInManager<ApplicationUser> _signInManager; |
||||
|
private string _username = null; |
||||
|
private readonly IBasketViewModelService _basketViewModelService; |
||||
|
|
||||
|
public IndexModel(IBasketService basketService, |
||||
|
IBasketViewModelService basketViewModelService, |
||||
|
IUriComposer uriComposer, |
||||
|
SignInManager<ApplicationUser> signInManager) |
||||
|
{ |
||||
|
_basketService = basketService; |
||||
|
_uriComposer = uriComposer; |
||||
|
_signInManager = signInManager; |
||||
|
_basketViewModelService = basketViewModelService; |
||||
|
} |
||||
|
|
||||
|
public BasketViewModel BasketModel { get; set; } = new BasketViewModel(); |
||||
|
|
||||
|
public async Task OnGet() |
||||
|
{ |
||||
|
await SetBasketModelAsync(); |
||||
|
} |
||||
|
|
||||
|
public async Task<IActionResult> OnPost(CatalogItemViewModel productDetails) |
||||
|
{ |
||||
|
if (productDetails?.Id == null) |
||||
|
{ |
||||
|
return RedirectToPage("/Index"); |
||||
|
} |
||||
|
await SetBasketModelAsync(); |
||||
|
|
||||
|
await _basketService.AddItemToBasket(BasketModel.Id, productDetails.Id, productDetails.Price, 1); |
||||
|
|
||||
|
await SetBasketModelAsync(); |
||||
|
|
||||
|
return RedirectToPage(); |
||||
|
} |
||||
|
|
||||
|
public async Task OnPostUpdate(Dictionary<string, int> items) |
||||
|
{ |
||||
|
await SetBasketModelAsync(); |
||||
|
await _basketService.SetQuantities(BasketModel.Id, items); |
||||
|
|
||||
|
await SetBasketModelAsync(); |
||||
|
} |
||||
|
|
||||
|
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 { IsEssential = true }; |
||||
|
cookieOptions.Expires = DateTime.Today.AddYears(10); |
||||
|
Response.Cookies.Append(Constants.BASKET_COOKIENAME, _username, cookieOptions); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
@page |
||||
|
@model ErrorModel |
||||
|
@{ |
||||
|
ViewData["Title"] = "Error"; |
||||
|
} |
||||
|
|
||||
|
<h1 class="text-danger">Error.</h1> |
||||
|
<h2 class="text-danger">An error occurred while processing your request.</h2> |
||||
|
|
||||
|
@if (Model.ShowRequestId) |
||||
|
{ |
||||
|
<p> |
||||
|
<strong>Request ID:</strong> <code>@Model.RequestId</code> |
||||
|
</p> |
||||
|
} |
||||
|
|
||||
|
<h3>Development Mode</h3> |
||||
|
<p> |
||||
|
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred. |
||||
|
</p> |
||||
|
<p> |
||||
|
<strong>The Development environment shouldn't be enabled for deployed applications.</strong> |
||||
|
It can result in displaying sensitive information from exceptions to end users. |
||||
|
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong> |
||||
|
and restarting the app. |
||||
|
</p> |
||||
@ -0,0 +1,19 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
using System.Diagnostics; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.Pages |
||||
|
{ |
||||
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] |
||||
|
public class ErrorModel : PageModel |
||||
|
{ |
||||
|
public string RequestId { get; set; } |
||||
|
|
||||
|
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); |
||||
|
|
||||
|
public void OnGet() |
||||
|
{ |
||||
|
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,43 +1,40 @@ |
|||||
@{ |
@page |
||||
|
@{ |
||||
ViewData["Title"] = "Catalog"; |
ViewData["Title"] = "Catalog"; |
||||
@model CatalogIndexViewModel |
@model IndexModel |
||||
} |
} |
||||
<section class="esh-catalog-hero"> |
<section class="esh-catalog-hero"> |
||||
<div class="container"> |
<div class="container"> |
||||
<img class="esh-catalog-title" src="~/images/main_banner_text.png" /> |
<img class="esh-catalog-title" src="~/images/main_banner_text.png" /> |
||||
</div> |
</div> |
||||
</section> |
</section> |
||||
|
|
||||
<section class="esh-catalog-filters"> |
<section class="esh-catalog-filters"> |
||||
<div class="container"> |
<div class="container"> |
||||
<form asp-action="Index" asp-controller="Catalog" method="post"> |
<form method="get"> |
||||
<label class="esh-catalog-label" data-title="brand"> |
<label class="esh-catalog-label" data-title="brand"> |
||||
<select asp-for="@Model.BrandFilterApplied" asp-items="@Model.Brands" class="esh-catalog-filter"></select> |
<select asp-for="@Model.CatalogModel.BrandFilterApplied" asp-items="@Model.CatalogModel.Brands" class="esh-catalog-filter"></select> |
||||
</label> |
</label> |
||||
<label class="esh-catalog-label" data-title="type"> |
<label class="esh-catalog-label" data-title="type"> |
||||
<select asp-for="@Model.TypesFilterApplied" asp-items="@Model.Types" class="esh-catalog-filter"></select> |
<select asp-for="@Model.CatalogModel.TypesFilterApplied" asp-items="@Model.CatalogModel.Types" class="esh-catalog-filter"></select> |
||||
</label> |
</label> |
||||
<input class="esh-catalog-send" type="image" src="images/arrow-right.svg" /> |
<input class="esh-catalog-send" type="image" src="images/arrow-right.svg" /> |
||||
</form> |
</form> |
||||
</div> |
</div> |
||||
</section> |
</section> |
||||
|
|
||||
<div class="container"> |
<div class="container"> |
||||
|
@if (Model.CatalogModel.CatalogItems.Any()) |
||||
@if (Model.CatalogItems.Any()) |
|
||||
{ |
{ |
||||
<partial name="_pagination" for="PaginationInfo" /> |
<partial name="_pagination" for="CatalogModel.PaginationInfo" /> |
||||
|
|
||||
<div class="esh-catalog-items row"> |
<div class="esh-catalog-items row"> |
||||
@foreach (var catalogItem in Model.CatalogItems) |
@foreach (var catalogItem in Model.CatalogModel.CatalogItems) |
||||
{ |
{ |
||||
<div class="esh-catalog-item col-md-4"> |
<div class="esh-catalog-item col-md-4"> |
||||
<partial name="_product" model="catalogItem" /> |
<partial name="_product" for="@catalogItem" /> |
||||
</div> |
</div> |
||||
} |
} |
||||
</div> |
</div> |
||||
|
<partial name="_pagination" for="CatalogModel.PaginationInfo" /> |
||||
<partial name="_pagination" for="PaginationInfo" /> |
|
||||
} |
} |
||||
else |
else |
||||
{ |
{ |
||||
@ -0,0 +1,26 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
using Microsoft.eShopWeb.Web.Services; |
||||
|
using Microsoft.eShopWeb.Web.ViewModels; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.Pages |
||||
|
{ |
||||
|
public class IndexModel : PageModel |
||||
|
{ |
||||
|
private readonly ICatalogService _catalogService; |
||||
|
|
||||
|
public IndexModel(ICatalogService catalogService) |
||||
|
{ |
||||
|
_catalogService = catalogService; |
||||
|
} |
||||
|
|
||||
|
public CatalogIndexViewModel CatalogModel { get; set; } = new CatalogIndexViewModel(); |
||||
|
|
||||
|
public async Task OnGet(CatalogIndexViewModel catalogModel, int? pageId) |
||||
|
{ |
||||
|
CatalogModel = await _catalogService.GetCatalogItems(pageId ?? 0, Constants.ITEMS_PER_PAGE, catalogModel.BrandFilterApplied, catalogModel.TypesFilterApplied); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -1,4 +1,6 @@ |
|||||
@{ |
@page |
||||
|
@model PrivacyModel |
||||
|
@{ |
||||
ViewData["Title"] = "Privacy Policy"; |
ViewData["Title"] = "Privacy Policy"; |
||||
} |
} |
||||
<h1>@ViewData["Title"]</h1> |
<h1>@ViewData["Title"]</h1> |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc.RazorPages; |
||||
|
|
||||
|
namespace Microsoft.eShopWeb.Web.Pages |
||||
|
{ |
||||
|
public class PrivacyModel : PageModel |
||||
|
{ |
||||
|
public void OnGet() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,12 +1,13 @@ |
|||||
using Microsoft.eShopWeb.Infrastructure.Identity; |
using Microsoft.AspNetCore.Identity; |
||||
using Microsoft.AspNetCore.Identity; |
|
||||
using Microsoft.AspNetCore.Mvc; |
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.eShopWeb.Infrastructure.Identity; |
||||
using Microsoft.eShopWeb.Web.Interfaces; |
using Microsoft.eShopWeb.Web.Interfaces; |
||||
|
using Microsoft.eShopWeb.Web.Pages.Basket; |
||||
using Microsoft.eShopWeb.Web.ViewModels; |
using Microsoft.eShopWeb.Web.ViewModels; |
||||
using System.Linq; |
using System.Linq; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
namespace Microsoft.eShopWeb.Web.ViewComponents |
namespace Microsoft.eShopWeb.Web.Pages.Shared.Components.BasketComponent |
||||
{ |
{ |
||||
public class Basket : ViewComponent |
public class Basket : ViewComponent |
||||
{ |
{ |
||||
@ -0,0 +1,13 @@ |
|||||
|
@model BasketComponentViewModel |
||||
|
@{ |
||||
|
ViewData["Title"] = "My Basket"; |
||||
|
} |
||||
|
<a class="esh-basketstatus " |
||||
|
asp-page="/Basket/Index"> |
||||
|
<div class="esh-basketstatus-image"> |
||||
|
<img src="~/images/cart.png" /> |
||||
|
</div> |
||||
|
<div class="esh-basketstatus-badge"> |
||||
|
@Model.ItemsCount |
||||
|
</div> |
||||
|
</a> |
||||
@ -1,22 +1,14 @@ |
|||||
@model CatalogItemViewModel |
@model CatalogItemViewModel |
||||
|
|
||||
|
<form asp-page="/Basket/Index" method="post"> |
||||
<form asp-controller="Basket" asp-action="AddToBasket"> |
|
||||
|
|
||||
<img class="esh-catalog-thumbnail" src="@Model.PictureUri" /> |
<img class="esh-catalog-thumbnail" src="@Model.PictureUri" /> |
||||
<input class="esh-catalog-button" type="submit" value="[ ADD TO BASKET ]" /> |
<input class="esh-catalog-button" type="submit" value="[ ADD TO BASKET ]" /> |
||||
|
|
||||
<div class="esh-catalog-name"> |
<div class="esh-catalog-name"> |
||||
<span>@Model.Name</span> |
<span>@Model.Name</span> |
||||
</div> |
</div> |
||||
<div class="esh-catalog-price"> |
<div class="esh-catalog-price"> |
||||
<span>@Model.Price.ToString("N2")</span> |
<span>@Model.Price.ToString("N2")</span> |
||||
</div> |
</div> |
||||
@*<input type="hidden" asp-for="@Model.CatalogBrand" name="brand" /> |
|
||||
<input type="hidden" asp-for="@Model.CatalogBrandId" name="brandId" /> |
|
||||
<input type="hidden" asp-for="@Model.CatalogType" name="type" /> |
|
||||
<input type="hidden" asp-for="@Model.CatalogTypeId" name="typeId" /> |
|
||||
<input type="hidden" asp-for="@Model.Description" name="description" />*@ |
|
||||
<input type="hidden" asp-for="@Model.Id" name="id" /> |
<input type="hidden" asp-for="@Model.Id" name="id" /> |
||||
<input type="hidden" asp-for="@Model.Name" name="name" /> |
<input type="hidden" asp-for="@Model.Name" name="name" /> |
||||
<input type="hidden" asp-for="@Model.PictureUri" name="pictureUri" /> |
<input type="hidden" asp-for="@Model.PictureUri" name="pictureUri" /> |
||||
@ -0,0 +1,9 @@ |
|||||
|
@using Microsoft.eShopWeb.Web |
||||
|
@using Microsoft.eShopWeb.Web.ViewModels |
||||
|
@using Microsoft.eShopWeb.Web.ViewModels.Account |
||||
|
@using Microsoft.eShopWeb.Web.ViewModels.Manage |
||||
|
@using Microsoft.eShopWeb.Web.Pages |
||||
|
@using Microsoft.AspNetCore.Identity |
||||
|
@using Microsoft.eShopWeb.Infrastructure.Identity |
||||
|
@namespace Microsoft.eShopWeb.Web.Pages |
||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
||||
@ -0,0 +1,3 @@ |
|||||
|
@{ |
||||
|
Layout = "_Layout"; |
||||
|
} |
||||
@ -1,8 +0,0 @@ |
|||||
@{ |
|
||||
ViewData["Title"] = "Home Page"; |
|
||||
} |
|
||||
|
|
||||
<div class="text-center"> |
|
||||
<h1 class="display-4">Welcome</h1> |
|
||||
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> |
|
||||
</div> |
|
||||
@ -1,13 +1,14 @@ |
|||||
using Microsoft.eShopWeb.RazorPages; |
using Microsoft.eShopWeb.FunctionalTests.Web.Controllers; |
||||
|
using Microsoft.eShopWeb.Web; |
||||
using System.Net.Http; |
using System.Net.Http; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Xunit; |
using Xunit; |
||||
|
|
||||
namespace Microsoft.eShopWeb.FunctionalTests.WebRazorPages |
namespace Microsoft.eShopWeb.FunctionalTests.WebRazorPages |
||||
{ |
{ |
||||
public class HomePageOnGet : IClassFixture<CustomWebRazorPagesApplicationFactory<Startup>> |
public class HomePageOnGet : IClassFixture<CustomWebApplicationFactory<Startup>> |
||||
{ |
{ |
||||
public HomePageOnGet(CustomWebRazorPagesApplicationFactory<Startup> factory) |
public HomePageOnGet(CustomWebApplicationFactory<Startup> factory) |
||||
{ |
{ |
||||
Client = factory.CreateClient(); |
Client = factory.CreateClient(); |
||||
} |
} |
||||
@ -1,70 +0,0 @@ |
|||||
using Microsoft.AspNetCore.Hosting; |
|
||||
using Microsoft.AspNetCore.Mvc.Testing; |
|
||||
using Microsoft.EntityFrameworkCore; |
|
||||
using Microsoft.eShopWeb.Infrastructure.Data; |
|
||||
using Microsoft.eShopWeb.Infrastructure.Identity; |
|
||||
using Microsoft.eShopWeb.RazorPages; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Microsoft.Extensions.Logging; |
|
||||
using System; |
|
||||
|
|
||||
namespace Microsoft.eShopWeb.FunctionalTests.WebRazorPages |
|
||||
{ |
|
||||
public class CustomWebRazorPagesApplicationFactory<TStartup> |
|
||||
: WebApplicationFactory<Startup> |
|
||||
{ |
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder) |
|
||||
{ |
|
||||
builder.ConfigureServices(services => |
|
||||
{ |
|
||||
// Create a new service provider.
|
|
||||
var serviceProvider = new ServiceCollection() |
|
||||
.AddEntityFrameworkInMemoryDatabase() |
|
||||
.BuildServiceProvider(); |
|
||||
|
|
||||
// Add a database context (ApplicationDbContext) using an in-memory
|
|
||||
// database for testing.
|
|
||||
services.AddDbContext<CatalogContext>(options => |
|
||||
{ |
|
||||
options.UseInMemoryDatabase("InMemoryDbForTesting"); |
|
||||
options.UseInternalServiceProvider(serviceProvider); |
|
||||
}); |
|
||||
|
|
||||
services.AddDbContext<AppIdentityDbContext>(options => |
|
||||
{ |
|
||||
options.UseInMemoryDatabase("Identity"); |
|
||||
options.UseInternalServiceProvider(serviceProvider); |
|
||||
}); |
|
||||
|
|
||||
// Build the service provider.
|
|
||||
var sp = services.BuildServiceProvider(); |
|
||||
|
|
||||
// Create a scope to obtain a reference to the database
|
|
||||
// context (ApplicationDbContext).
|
|
||||
using (var scope = sp.CreateScope()) |
|
||||
{ |
|
||||
var scopedServices = scope.ServiceProvider; |
|
||||
var db = scopedServices.GetRequiredService<CatalogContext>(); |
|
||||
var loggerFactory = scopedServices.GetRequiredService<ILoggerFactory>(); |
|
||||
|
|
||||
var logger = scopedServices |
|
||||
.GetRequiredService<ILogger<CustomWebRazorPagesApplicationFactory<TStartup>>>(); |
|
||||
|
|
||||
// Ensure the database is created.
|
|
||||
db.Database.EnsureCreated(); |
|
||||
|
|
||||
try |
|
||||
{ |
|
||||
// Seed the database with test data.
|
|
||||
CatalogContextSeed.SeedAsync(db, loggerFactory).Wait(); |
|
||||
} |
|
||||
catch (Exception ex) |
|
||||
{ |
|
||||
logger.LogError(ex, $"An error occurred seeding the " + |
|
||||
"database with test messages. Error: {ex.Message}"); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,32 +0,0 @@ |
|||||
using Microsoft.AspNetCore.Mvc.Testing; |
|
||||
using Microsoft.eShopWeb.RazorPages; |
|
||||
using System.Net; |
|
||||
using System.Net.Http; |
|
||||
using System.Threading.Tasks; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Microsoft.eShopWeb.FunctionalTests.WebRazorPages |
|
||||
{ |
|
||||
public class OrderIndexOnGet : IClassFixture<CustomWebRazorPagesApplicationFactory<Startup>> |
|
||||
{ |
|
||||
public OrderIndexOnGet(CustomWebRazorPagesApplicationFactory<Startup> factory) |
|
||||
{ |
|
||||
Client = factory.CreateClient(new WebApplicationFactoryClientOptions |
|
||||
{ |
|
||||
AllowAutoRedirect = false |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
public HttpClient Client { get; } |
|
||||
|
|
||||
[Fact] |
|
||||
public async Task ReturnsRedirectGivenAnonymousUser() |
|
||||
{ |
|
||||
var response = await Client.GetAsync("/Order/Index"); |
|
||||
var redirectLocation = response.Headers.Location.OriginalString; |
|
||||
|
|
||||
Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); |
|
||||
Assert.Contains("Account/Login", redirectLocation); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue