revert git version

This commit is contained in:
zedy
2023-01-31 13:34:42 +08:00
parent 9955c69264
commit d27aeffeac
42 changed files with 338 additions and 236 deletions

View File

@@ -3,7 +3,8 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
FROM mcr.microsoft.com/dotnet/sdk:6.0
FROM mcr.microsoft.com/dotnet/sdk:7.0
# This Dockerfile adds a non-root user with sudo access. Use the "remoteUser"
# property in devcontainer.json to use it. On Linux, the container user's GID/UIDs

View File

@@ -25,15 +25,22 @@
// Comment out to connect as root user. See https://aka.ms/vscode-remote/containers/non-root.
// make sure this is the same as USERNAME above
"remoteUser": "vscode",
"runArgs": [
"-v",
"/var/run/docker.sock:/var/run/docker.sock"
],
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
"terminal.integrated.profiles.linux": {
"bash": {
"path": "bash",
"icon": "terminal-bash"
}
}
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-azuretools.azure-dev",
"ms-dotnettools.csharp",
"formulahendry.dotnet-test-explorer",
"ms-vscode.vscode-node-azure-pack",

View File

@@ -12,7 +12,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.0.x'
dotnet-version: '7.0.x'
include-prerelease: true
- name: Build with dotnet

View File

@@ -12,7 +12,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.x
dotnet-version: 7.0.x
- name: Build with dotnet
run: dotnet build ./eShopOnWeb.sln --configuration Release

2
.vscode/launch.json vendored
View File

@@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/Web/bin/Debug/net5.0/Web.dll",
"program": "${workspaceFolder}/src/Web/bin/Debug/net7.0/Web.dll",
"args": [],
"cwd": "${workspaceFolder}/src/Web",
"stopAtEntry": false,

68
Directory.Packages.props Normal file
View File

@@ -0,0 +1,68 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Ardalis.ApiEndpoints" Version="4.0.1" />
<PackageVersion Include="Ardalis.GuardClauses" Version="4.0.1" />
<PackageVersion Include="Ardalis.Specification.EntityFrameworkCore" Version="6.1.0" />
<PackageVersion Include="Ardalis.Result" Version="4.1.0" />
<PackageVersion Include="Ardalis.Specification" Version="6.1.0" />
<PackageVersion Include="Ardalis.ListStartupServices" Version="1.1.4" />
<PackageVersion Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.1" />
<PackageVersion Include="Azure.Identity" Version="1.6.0" />
<PackageVersion Include="BlazorInputFile" Version="0.2.0" />
<PackageVersion Include="Blazored.LocalStorage" Version="4.3.0" />
<PackageVersion Include="BuildBundlerMinifier" Version="3.2.449" PrivateAssets="All" />
<PackageVersion Include="FluentValidation" Version="11.4.0" />
<PackageVersion Include="MediatR" Version="11.1.0" />
<PackageVersion Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.Authorization" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.2" PrivateAssets="all" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageVersion Include="Microsoft.Extensions.Identity.Core" Version="7.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.Configuration" Version="7.0.0" />
<PackageVersion Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.2" />
<PackageVersion Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageVersion Include="MinimalApi.Endpoint" Version="1.3.0" />
<PackageVersion Include="System.Net.Http.Json" Version="7.0.0" />
<PackageVersion Include="System.Security.Claims" Version="4.3.0" />
<PackageVersion Include="System.Text.Json" Version="7.0.1" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.25.1" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
<PackageVersion Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<!-- Test -->
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageVersion Include="xunit" Version="2.4.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageVersion>
<PackageVersion Include="xunit.runner.console" Version="2.4.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageVersion>
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.0.2" />
<PackageVersion Include="MSTest.TestFramework" Version="3.0.2" />
<PackageVersion Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>
</Project>

View File

@@ -24,7 +24,7 @@ The **eShopOnWeb** sample is related to the [eShopOnContainers](https://github.c
The goal for this sample is to demonstrate some of the principles and patterns described in the [eBook](https://aka.ms/webappebook). It is not meant to be an eCommerce reference application, and as such it does not implement many features that would be obvious and/or essential to a real eCommerce application.
> ### VERSIONS
> #### The `main` branch is currently running ASP.NET Core 6.0.
> #### The `main` branch is currently running ASP.NET Core 7.0.
> #### Older versions are tagged.
## Topics (eBook TOC)
@@ -47,7 +47,9 @@ The store's home page should look like this:
![eShopOnWeb home page screenshot](https://user-images.githubusercontent.com/782127/88414268-92d83a00-cdaa-11ea-9b4c-db67d95be039.png)
Most of the site's functionality works with just the web application running. However, the site's Admin page relies on Blazor WebAssembly running in the browser, and it must communicate with the server using the site's PublicApi web application. You'll need to also run this project. You can configure Visual Studio to start multiple projects, or just go to the PublicApi folder in a terminal window and run `dotnet run` from there. After that from the Web folder you should run `dotnet run --launch-profile Web`. Now you should be able to browse to `https://localhost:5001/`. Note that if you use this approach, you'll need to stop the application manually in order to build the solution (otherwise you'll get file locking errors).
Most of the site's functionality works with just the web application running. However, the site's Admin page relies on Blazor WebAssembly running in the browser, and it must communicate with the server using the site's PublicApi web application. You'll need to also run this project. You can configure Visual Studio to start multiple projects, or just go to the PublicApi folder in a terminal window and run `dotnet run` from there. After that from the Web folder you should run `dotnet run --launch-profile Web`. Now you should be able to browse to `https://localhost:5001/`. The admin part in Blazor is accessible to `https://localhost:5001/admin`
Note that if you use this approach, you'll need to stop the application manually in order to build the solution (otherwise you'll get file locking errors).
After cloning or downloading the sample you must setup your database.
To use the sample with a persistent database, you will need to run its Entity Framework Core migrations before you will be able to run the app.

View File

@@ -24,6 +24,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0BD72BEA-EF42-4B72-8B69-12A39EC76FBA}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
Directory.Packages.props = Directory.Packages.props
docker-compose.override.yml = docker-compose.override.yml
docker-compose.yml = docker-compose.yml
.github\workflows\dotnetcore.yml = .github\workflows\dotnetcore.yml
@@ -38,7 +39,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorAdmin", "src\BlazorAd
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorShared", "src\BlazorShared\BlazorShared.csproj", "{715CF7AF-A1EE-40A6-94A0-8DA3F3B2CAE9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PublicApiIntegrationTests", "tests\PublicApiIntegrationTests\PublicApiIntegrationTests.csproj", "{D53EF010-8F8C-4337-A059-456E19D8AE63}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PublicApiIntegrationTests", "tests\PublicApiIntegrationTests\PublicApiIntegrationTests.csproj", "{D53EF010-8F8C-4337-A059-456E19D8AE63}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -1,6 +1,6 @@
{
"sdk": {
"version": "6.0.x",
"version": "7.0.x",
"rollForward": "latestFeature"
}
}

View File

@@ -1,18 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Microsoft.eShopWeb.ApplicationCore</RootNamespace>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ardalis.GuardClauses" Version="4.0.1" />
<PackageReference Include="Ardalis.Result" Version="4.1.0" />
<PackageReference Include="Ardalis.Specification" Version="6.1.0" />
<PackageReference Include="MediatR" Version="10.0.1" />
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="6.0.5" />
<PackageReference Include="Ardalis.GuardClauses" />
<PackageReference Include="Ardalis.Result" />
<PackageReference Include="Ardalis.Specification" />
<PackageReference Include="System.Security.Claims" />
<PackageReference Include="System.Text.Json" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,19 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.2.0" />
<PackageReference Include="BlazorInputFile" Version="0.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.8" PrivateAssets="all" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="6.0.0" />
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
<PackageReference Include="Blazored.LocalStorage" />
<PackageReference Include="BlazorInputFile" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" />
<PackageReference Include="System.Net.Http.Json" />
</ItemGroup>
<ItemGroup>

View File

@@ -63,7 +63,7 @@ public class CustomAuthStateProvider : AuthenticationStateProvider
if (user == null || !user.IsAuthenticated)
{
return null;
return new ClaimsPrincipal(new ClaimsIdentity());
}
var identity = new ClaimsIdentity(

View File

@@ -7,7 +7,7 @@
protected override async Task OnInitializedAsync()
{
await HttpClient.PostAsync("Identity/Account/Logout", null);
await HttpClient.PostAsync("User/Logout", null);
await new Route(JSRuntime).RouteOutside("/Identity/Account/Login");
}

View File

@@ -1,9 +1,12 @@
@inject NavigationManager Navigation
@using System.Web;
@inject NavigationManager Navigation
@inject IJSRuntime JsRuntime
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo($"Identity/Account/Login?returnUrl=" +
$"/{Uri.EscapeDataString(Navigation.ToBaseRelativePath(Navigation.Uri))}");
var returnUrl = HttpUtility.UrlEncode($"/{Uri.EscapeDataString(Navigation.ToBaseRelativePath(Navigation.Uri))}");
JsRuntime.InvokeVoidAsync("location.replace", $"Identity/Account/Login?returnUrl={returnUrl}");
}
}

View File

@@ -1,14 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>BlazorShared</RootNamespace>
<AssemblyName>BlazorShared</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BlazorInputFile" Version="0.2.0" />
<PackageReference Include="FluentValidation" Version="11.2.1" />
<PackageReference Include="BlazorInputFile" />
<PackageReference Include="FluentValidation" />
</ItemGroup>
</Project>

View File

@@ -1,17 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Microsoft.eShopWeb.Infrastructure</RootNamespace>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="6.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.23.0" />
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ApplicationCore\ApplicationCore.csproj" />

View File

@@ -13,9 +13,8 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogBrandEndpoints;
/// <summary>
/// List Catalog Brands
/// </summary>
public class CatalogBrandListEndpoint : IEndpoint<IResult>
public class CatalogBrandListEndpoint : IEndpoint<IResult, IRepository<CatalogBrand>>
{
private IRepository<CatalogBrand> _catalogBrandRepository;
private readonly IMapper _mapper;
public CatalogBrandListEndpoint(IMapper mapper)
@@ -28,18 +27,17 @@ public class CatalogBrandListEndpoint : IEndpoint<IResult>
app.MapGet("api/catalog-brands",
async (IRepository<CatalogBrand> catalogBrandRepository) =>
{
_catalogBrandRepository = catalogBrandRepository;
return await HandleAsync();
return await HandleAsync(catalogBrandRepository);
})
.Produces<ListCatalogBrandsResponse>()
.WithTags("CatalogBrandEndpoints");
}
public async Task<IResult> HandleAsync()
public async Task<IResult> HandleAsync(IRepository<CatalogBrand> catalogBrandRepository)
{
var response = new ListCatalogBrandsResponse();
var items = await _catalogBrandRepository.ListAsync();
var items = await catalogBrandRepository.ListAsync();
response.CatalogBrands.AddRange(items.Select(_mapper.Map<CatalogBrandDto>));

View File

@@ -11,9 +11,8 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
/// <summary>
/// Get a Catalog Item by Id
/// </summary>
public class CatalogItemGetByIdEndpoint : IEndpoint<IResult, GetByIdCatalogItemRequest>
public class CatalogItemGetByIdEndpoint : IEndpoint<IResult, GetByIdCatalogItemRequest, IRepository<CatalogItem>>
{
private IRepository<CatalogItem> _itemRepository;
private readonly IUriComposer _uriComposer;
public CatalogItemGetByIdEndpoint(IUriComposer uriComposer)
@@ -26,18 +25,17 @@ public class CatalogItemGetByIdEndpoint : IEndpoint<IResult, GetByIdCatalogItemR
app.MapGet("api/catalog-items/{catalogItemId}",
async (int catalogItemId, IRepository<CatalogItem> itemRepository) =>
{
_itemRepository = itemRepository;
return await HandleAsync(new GetByIdCatalogItemRequest(catalogItemId));
return await HandleAsync(new GetByIdCatalogItemRequest(catalogItemId), itemRepository);
})
.Produces<GetByIdCatalogItemResponse>()
.WithTags("CatalogItemEndpoints");
}
public async Task<IResult> HandleAsync(GetByIdCatalogItemRequest request)
public async Task<IResult> HandleAsync(GetByIdCatalogItemRequest request, IRepository<CatalogItem> itemRepository)
{
var response = new GetByIdCatalogItemResponse(request.CorrelationId());
var item = await _itemRepository.GetByIdAsync(request.CatalogItemId);
var item = await itemRepository.GetByIdAsync(request.CatalogItemId);
if (item is null)
return Results.NotFound();

View File

@@ -15,9 +15,8 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
/// <summary>
/// List Catalog Items (paged)
/// </summary>
public class CatalogItemListPagedEndpoint : IEndpoint<IResult, ListPagedCatalogItemRequest>
public class CatalogItemListPagedEndpoint : IEndpoint<IResult, ListPagedCatalogItemRequest, IRepository<CatalogItem>>
{
private IRepository<CatalogItem> _itemRepository;
private readonly IUriComposer _uriComposer;
private readonly IMapper _mapper;
@@ -32,19 +31,19 @@ public class CatalogItemListPagedEndpoint : IEndpoint<IResult, ListPagedCatalogI
app.MapGet("api/catalog-items",
async (int? pageSize, int? pageIndex, int? catalogBrandId, int? catalogTypeId, IRepository<CatalogItem> itemRepository) =>
{
_itemRepository = itemRepository;
return await HandleAsync(new ListPagedCatalogItemRequest(pageSize, pageIndex, catalogBrandId, catalogTypeId));
return await HandleAsync(new ListPagedCatalogItemRequest(pageSize, pageIndex, catalogBrandId, catalogTypeId), itemRepository);
})
.Produces<ListPagedCatalogItemResponse>()
.WithTags("CatalogItemEndpoints");
}
public async Task<IResult> HandleAsync(ListPagedCatalogItemRequest request)
public async Task<IResult> HandleAsync(ListPagedCatalogItemRequest request, IRepository<CatalogItem> itemRepository)
{
await Task.Delay(1000);
var response = new ListPagedCatalogItemResponse(request.CorrelationId());
var filterSpec = new CatalogFilterSpecification(request.CatalogBrandId, request.CatalogTypeId);
int totalItems = await _itemRepository.CountAsync(filterSpec);
int totalItems = await itemRepository.CountAsync(filterSpec);
var pagedSpec = new CatalogFilterPaginatedSpecification(
skip: request.PageIndex.Value * request.PageSize.Value,
@@ -52,7 +51,7 @@ public class CatalogItemListPagedEndpoint : IEndpoint<IResult, ListPagedCatalogI
brandId: request.CatalogBrandId,
typeId: request.CatalogTypeId);
var items = await _itemRepository.ListAsync(pagedSpec);
var items = await itemRepository.ListAsync(pagedSpec);
response.CatalogItems.AddRange(items.Select(_mapper.Map<CatalogItemDto>));
foreach (CatalogItemDto item in response.CatalogItems)

View File

@@ -15,9 +15,8 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
/// <summary>
/// Creates a new Catalog Item
/// </summary>
public class CreateCatalogItemEndpoint : IEndpoint<IResult, CreateCatalogItemRequest>
public class CreateCatalogItemEndpoint : IEndpoint<IResult, CreateCatalogItemRequest, IRepository<CatalogItem>>
{
private IRepository<CatalogItem> _itemRepository;
private readonly IUriComposer _uriComposer;
public CreateCatalogItemEndpoint(IUriComposer uriComposer)
@@ -31,26 +30,25 @@ public class CreateCatalogItemEndpoint : IEndpoint<IResult, CreateCatalogItemReq
[Authorize(Roles = BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] async
(CreateCatalogItemRequest request, IRepository<CatalogItem> itemRepository) =>
{
_itemRepository = itemRepository;
return await HandleAsync(request);
return await HandleAsync(request, itemRepository);
})
.Produces<CreateCatalogItemResponse>()
.WithTags("CatalogItemEndpoints");
}
public async Task<IResult> HandleAsync(CreateCatalogItemRequest request)
public async Task<IResult> HandleAsync(CreateCatalogItemRequest request, IRepository<CatalogItem> itemRepository)
{
var response = new CreateCatalogItemResponse(request.CorrelationId());
var catalogItemNameSpecification = new CatalogItemNameSpecification(request.Name);
var existingCataloogItem = await _itemRepository.CountAsync(catalogItemNameSpecification);
var existingCataloogItem = await itemRepository.CountAsync(catalogItemNameSpecification);
if (existingCataloogItem > 0)
{
throw new DuplicateException($"A catalogItem with name {request.Name} already exists");
}
var newItem = new CatalogItem(request.CatalogTypeId, request.CatalogBrandId, request.Description, request.Name, request.Price, request.PictureUri);
newItem = await _itemRepository.AddAsync(newItem);
newItem = await itemRepository.AddAsync(newItem);
if (newItem.Id != 0)
{
@@ -59,7 +57,7 @@ public class CreateCatalogItemEndpoint : IEndpoint<IResult, CreateCatalogItemReq
// In production, we recommend uploading to a blob storage and deliver the image via CDN after a verification process.
newItem.UpdatePictureUri("eCatalog-item-default.png");
await _itemRepository.UpdateAsync(newItem);
await itemRepository.UpdateAsync(newItem);
}
var dto = new CatalogItemDto

View File

@@ -13,32 +13,29 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
/// <summary>
/// Deletes a Catalog Item
/// </summary>
public class DeleteCatalogItemEndpoint : IEndpoint<IResult, DeleteCatalogItemRequest>
public class DeleteCatalogItemEndpoint : IEndpoint<IResult, DeleteCatalogItemRequest, IRepository<CatalogItem>>
{
private IRepository<CatalogItem> _itemRepository;
public void AddRoute(IEndpointRouteBuilder app)
{
app.MapDelete("api/catalog-items/{catalogItemId}",
[Authorize(Roles = BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] async
(int catalogItemId, IRepository<CatalogItem> itemRepository) =>
{
_itemRepository = itemRepository;
return await HandleAsync(new DeleteCatalogItemRequest(catalogItemId));
return await HandleAsync(new DeleteCatalogItemRequest(catalogItemId), itemRepository);
})
.Produces<DeleteCatalogItemResponse>()
.WithTags("CatalogItemEndpoints");
}
public async Task<IResult> HandleAsync(DeleteCatalogItemRequest request)
public async Task<IResult> HandleAsync(DeleteCatalogItemRequest request, IRepository<CatalogItem> itemRepository)
{
var response = new DeleteCatalogItemResponse(request.CorrelationId());
var itemToDelete = await _itemRepository.GetByIdAsync(request.CatalogItemId);
var itemToDelete = await itemRepository.GetByIdAsync(request.CatalogItemId);
if (itemToDelete is null)
return Results.NotFound();
await _itemRepository.DeleteAsync(itemToDelete);
await itemRepository.DeleteAsync(itemToDelete);
return Results.Ok(response);
}

View File

@@ -13,9 +13,8 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
/// <summary>
/// Updates a Catalog Item
/// </summary>
public class UpdateCatalogItemEndpoint : IEndpoint<IResult, UpdateCatalogItemRequest>
public class UpdateCatalogItemEndpoint : IEndpoint<IResult, UpdateCatalogItemRequest, IRepository<CatalogItem>>
{
private IRepository<CatalogItem> _itemRepository;
private readonly IUriComposer _uriComposer;
public UpdateCatalogItemEndpoint(IUriComposer uriComposer)
@@ -29,25 +28,24 @@ public class UpdateCatalogItemEndpoint : IEndpoint<IResult, UpdateCatalogItemReq
[Authorize(Roles = BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS, AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] async
(UpdateCatalogItemRequest request, IRepository<CatalogItem> itemRepository) =>
{
_itemRepository = itemRepository;
return await HandleAsync(request);
return await HandleAsync(request, itemRepository);
})
.Produces<UpdateCatalogItemResponse>()
.WithTags("CatalogItemEndpoints");
}
public async Task<IResult> HandleAsync(UpdateCatalogItemRequest request)
public async Task<IResult> HandleAsync(UpdateCatalogItemRequest request, IRepository<CatalogItem> itemRepository)
{
var response = new UpdateCatalogItemResponse(request.CorrelationId());
var existingItem = await _itemRepository.GetByIdAsync(request.Id);
var existingItem = await itemRepository.GetByIdAsync(request.Id);
CatalogItem.CatalogItemDetails details = new(request.Name, request.Description, request.Price);
existingItem.UpdateDetails(details);
existingItem.UpdateBrand(request.CatalogBrandId);
existingItem.UpdateType(request.CatalogTypeId);
await _itemRepository.UpdateAsync(existingItem);
await itemRepository.UpdateAsync(existingItem);
var dto = new CatalogItemDto
{

View File

@@ -13,9 +13,8 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogTypeEndpoints;
/// <summary>
/// List Catalog Types
/// </summary>
public class CatalogTypeListEndpoint : IEndpoint<IResult>
public class CatalogTypeListEndpoint : IEndpoint<IResult, IRepository<CatalogType>>
{
private IRepository<CatalogType> _catalogTypeRepository;
private readonly IMapper _mapper;
public CatalogTypeListEndpoint(IMapper mapper)
@@ -28,18 +27,17 @@ public class CatalogTypeListEndpoint : IEndpoint<IResult>
app.MapGet("api/catalog-types",
async (IRepository<CatalogType> catalogTypeRepository) =>
{
_catalogTypeRepository = catalogTypeRepository;
return await HandleAsync();
return await HandleAsync(catalogTypeRepository);
})
.Produces<ListCatalogTypesResponse>()
.WithTags("CatalogTypeEndpoints");
}
public async Task<IResult> HandleAsync()
public async Task<IResult> HandleAsync(IRepository<CatalogType> catalogTypeRepository)
{
var response = new ListCatalogTypesResponse();
var items = await _catalogTypeRepository.ListAsync();
var items = await catalogTypeRepository.ListAsync();
response.CatalogTypes.AddRange(items.Select(_mapper.Map<CatalogTypeDto>));

View File

@@ -1,11 +1,11 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app
COPY . .
#COPY ["src/PublicApi/PublicApi.csproj", "./PublicApi/"]

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Text;
using BlazorShared;
using BlazorShared.Models;
using MediatR;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
@@ -83,9 +82,8 @@ builder.Services.AddCors(options =>
});
builder.Services.AddControllers();
builder.Services.AddMediatR(typeof(CatalogItem).Assembly);
builder.Services.AddAutoMapper(typeof(MappingProfile).Assembly);
builder.Configuration.AddEnvironmentVariables();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>

View File

@@ -1,13 +1,4 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52023",
"sslPort": 44339
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
@@ -25,6 +16,32 @@
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5099;http://localhost:5098"
},
"WSL": {
"commandName": "WSL2",
"launchBrowser": true,
"launchUrl": "https://localhost:5099/swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "https://localhost:5099;http://localhost:5098"
},
"distributionName": ""
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"publishAllPorts": true,
"useSSL": true
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:52023",
"sslPort": 44339
}
}
}

View File

@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Microsoft.eShopWeb.PublicApi</RootNamespace>
<UserSecretsId>5b662463-1efd-4bae-bde4-befe0be3e8ff</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
@@ -10,28 +9,26 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ardalis.ApiEndpoints" Version="4.0.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageReference Include="MediatR" Version="10.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
<PackageReference Include="MinimalApi.Endpoint" Version="1.2.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
<PackageReference Include="Ardalis.ApiEndpoints" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" />
<PackageReference Include="MinimalApi.Endpoint" />
<PackageReference Include="Swashbuckle.AspNetCore" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" >
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.8" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.23.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" />
</ItemGroup>
<ItemGroup>

View File

@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "6.0.4",
"version": "7.0.2",
"commands": [
"dotnet-ef"
]

View File

@@ -1,7 +1,4 @@
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
@@ -10,7 +7,6 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.eShopWeb.Infrastructure.Identity;
using Microsoft.eShopWeb.Web.Configuration;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account;

View File

@@ -1,8 +1,6 @@
using MediatR;
using Microsoft.eShopWeb.Web.Interfaces;
using Microsoft.eShopWeb.Web.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.eShopWeb.Web.Configuration;

View File

@@ -1,11 +1,14 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Security.Claims;
using BlazorShared.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.Infrastructure.Identity;
using Microsoft.eShopWeb.Web.Configuration;
using Microsoft.Extensions.Caching.Memory;
namespace Microsoft.eShopWeb.Web.Controllers;
@@ -14,10 +17,19 @@ namespace Microsoft.eShopWeb.Web.Controllers;
public class UserController : ControllerBase
{
private readonly ITokenClaimsService _tokenClaimsService;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly ILogger<UserController> _logger;
private readonly IMemoryCache _cache;
public UserController(ITokenClaimsService tokenClaimsService)
public UserController(ITokenClaimsService tokenClaimsService,
SignInManager<ApplicationUser> signInManager,
ILogger<UserController> logger,
IMemoryCache cache)
{
_tokenClaimsService = tokenClaimsService;
_signInManager = signInManager;
_logger = logger;
_cache = cache;
}
[HttpGet]
@@ -26,6 +38,25 @@ public class UserController : ControllerBase
public async Task<IActionResult> GetCurrentUser() =>
Ok(await CreateUserInfo(User));
[Route("Logout")]
[HttpPost]
[Authorize]
[AllowAnonymous]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
var userId = _signInManager.Context.User.Claims.First(c => c.Type == ClaimTypes.Name);
var identityKey = _signInManager.Context.Request.Cookies[ConfigureCookieSettings.IdentifierCookieName];
_cache.Set($"{userId.Value}:{identityKey}", identityKey, new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTime.Now.AddMinutes(ConfigureCookieSettings.ValidityMinutesPeriod)
});
_logger.LogInformation("User logged out.");
return Ok();
}
private async Task<UserInfo> CreateUserInfo(ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal.Identity == null || claimsPrincipal.Identity.Name == null || !claimsPrincipal.Identity.IsAuthenticated)

View File

@@ -7,7 +7,7 @@
#
# RUN COMMAND
# docker run --name eshopweb --rm -it -p 5106:5106 web
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app
COPY *.sln .
@@ -17,7 +17,7 @@ RUN dotnet restore
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS runtime
WORKDIR /app
COPY --from=build /app/src/Web/out ./

View File

@@ -1,8 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using MediatR;
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.ApplicationCore.Specifications;

View File

@@ -1,7 +1,4 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using MediatR;
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
using Microsoft.eShopWeb.ApplicationCore.Specifications;

View File

@@ -53,7 +53,7 @@ builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
.AddDefaultTokenProviders();
builder.Services.AddScoped<ITokenClaimsService, IdentityTokenClaimService>();
builder.Configuration.AddEnvironmentVariables();
builder.Services.AddCoreServices(builder.Configuration);
builder.Services.AddWebServices(builder.Configuration);

View File

@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>Microsoft.eShopWeb.Web</RootNamespace>
@@ -14,28 +13,28 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Ardalis.ListStartupServices" Version="1.1.4" />
<PackageReference Include="Ardalis.Specification" Version="6.1.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="11.0.0" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.1" />
<PackageReference Include="Azure.Identity" Version="1.5.0" />
<PackageReference Include="MediatR" Version="10.0.1" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" Condition="'$(Configuration)'=='Release'" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.8" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
<PackageReference Include="Ardalis.ListStartupServices" />
<PackageReference Include="Ardalis.Specification" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="MediatR" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" />
<PackageReference Include="BuildBundlerMinifier" Condition="'$(Configuration)'=='Release'" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.23.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\fonts\" />

View File

@@ -3,11 +3,11 @@
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "jquery@3.3.1",
"library": "jquery@3.6.3",
"destination": "wwwroot/lib/jquery/"
},
{
"library": "twitter-bootstrap@3.3.7",
"library": "twitter-bootstrap@5.2.3",
"files": [
"css/bootstrap.css",
"css/bootstrap.css.map",
@@ -19,11 +19,11 @@
"destination": "wwwroot/lib/bootstrap/dist/"
},
{
"library": "jquery-validation-unobtrusive@3.2.10",
"library": "jquery-validation-unobtrusive@4.0.0",
"destination": "wwwroot/lib/jquery-validation-unobtrusive/"
},
{
"library": "jquery-validate@1.17.0",
"library": "jquery-validate@1.19.5",
"destination": "wwwroot/lib/jquery-validate/",
"files": [
"jquery.validate.min.js",
@@ -35,7 +35,7 @@
"destination": "wwwroot/lib/toastr/"
},
{
"library": "aspnet-signalr@1.0.3",
"library": "aspnet-signalr@1.0.27",
"files": [
"signalr.js",
"signalr.min.js"

View File

@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Microsoft.eShopWeb.FunctionalTests</RootNamespace>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
@@ -15,15 +14,12 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<DotNetCliToolReference Include="dotnet-xunit" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,17 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>Microsoft.eShopWeb.IntegrationTests</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Moq" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" >
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>

View File

@@ -2,7 +2,10 @@
using Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints;
using Microsoft.eShopWeb.Web.ViewModels;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Threading.Tasks;
namespace PublicApiIntegrationTests.CatalogItemEndpoints
@@ -45,5 +48,26 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
Assert.AreEqual(totalExpected, model2.CatalogItems.Count());
}
[DataTestMethod]
[DataRow("catalog-items")]
[DataRow("catalog-brands")]
[DataRow("catalog-types")]
[DataRow("catalog-items/1")]
public async Task SuccessFullMutipleParallelCall(string endpointName)
{
var client = ProgramTest.NewClient;
var tasks = new List<Task<HttpResponseMessage>>();
for (int i = 0; i < 100; i++)
{
var task = client.GetAsync($"/api/{endpointName}");
tasks.Add(task);
}
await Task.WhenAll(tasks.ToList());
var totalKO = tasks.Count(t => t.Result.StatusCode != HttpStatusCode.OK);
Assert.AreEqual(0, totalKO);
}
}
}

View File

@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
@@ -20,11 +19,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="6.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="MSTest.TestAdapter" />
<PackageReference Include="MSTest.TestFramework" />
<PackageReference Include="coverlet.collector">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>

View File

@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<RootNamespace>Microsoft.eShopWeb.UnitTests</RootNamespace>
<IsPackable>false</IsPackable>
@@ -10,18 +9,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="Moq" Version="4.18.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.console" Version="2.4.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Mvc" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Moq" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="xunit.runner.console" />
</ItemGroup>
<ItemGroup>