Merge pull request #5 from jonhilt/net6

Upgraded to .NET 6
This commit is contained in:
Jon Hilton 2021-11-09 10:45:47 +00:00 committed by GitHub
commit 88fcc46717
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 419 additions and 481 deletions

View file

@ -1,10 +1,12 @@
<Router AppAssembly="@typeof(Program).Assembly"> <Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData"> <Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found> </Found>
<NotFound> <NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)"> <LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p> <p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView> </LayoutView>
</NotFound> </NotFound>
</Router> </Router>

View file

@ -1,5 +1,7 @@
@page "/" @page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1> <h1>Hello, world!</h1>
Welcome to your new app. Welcome to your new app.

View file

@ -1,25 +1,11 @@
using System; using Microsoft.AspNetCore.Components.Web;
using System.Net.Http;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.Configuration; using ShoppingCartStarter.Client;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace ShoppingCartStarter.Client
{
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args); var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app"); builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync(); await builder.Build().RunAsync();
}
}
}

View file

@ -3,11 +3,21 @@
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:65269", "applicationUrl": "http://localhost:24471",
"sslPort": 44368 "sslPort": 44335
} }
}, },
"profiles": { "profiles": {
"ShoppingCartStarter": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7109;http://localhost:5109",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"launchBrowser": true, "launchBrowser": true,
@ -15,15 +25,6 @@
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
},
"ShoppingCartStarter": {
"commandName": "Project",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
} }
} }
} }

View file

@ -1,15 +1,17 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<div class="page">
<div class="sidebar"> <div class="sidebar">
<NavMenu /> <NavMenu />
</div> </div>
<div class="main"> <main>
<div class="top-row px-4"> <div class="top-row px-4">
<a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div> </div>
<div class="content px-4"> <article class="content px-4">
@Body @Body
</div> </article>
</main>
</div> </div>

View file

@ -0,0 +1,81 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}
.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}
.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 640.98px) {
.top-row:not(.auth) {
display: none;
}
.top-row.auth {
justify-content: space-between;
}
.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}
@media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}
.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}

View file

@ -1,24 +1,26 @@
<div class="top-row pl-4 navbar navbar-dark"> <div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">ShoppingCartStarter</a> <a class="navbar-brand" href="">ShoppingCartStarter</a>
<button class="navbar-toggler" @onclick="ToggleNavMenu"> <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
</div> </div>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<ul class="nav flex-column"> <nav class="flex-column">
<li class="nav-item px-3"> <div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home <span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink> </NavLink>
</li> </div>
</ul> </nav>
</div> </div>
@code { @code {
private bool collapseNavMenu = true; private bool collapseNavMenu = true;
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu() private void ToggleNavMenu()
{ {

View file

@ -0,0 +1,62 @@
.navbar-toggler {
background-color: rgba(255, 255, 255, 0.1);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.oi {
width: 2rem;
font-size: 1.1rem;
vertical-align: text-top;
top: -2px;
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep a {
color: #d7d7d7;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.25);
color: white;
}
.nav-item ::deep a:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
}

View file

@ -1,10 +1,10 @@
<div class="alert alert-secondary mt-4" role="alert"> <div class="alert alert-secondary mt-4">
<span class="oi oi-pencil mr-2" aria-hidden="true"></span> <span class="oi oi-pencil me-2" aria-hidden="true"></span>
<strong>@Title</strong> <strong>@Title</strong>
<span class="text-nowrap"> <span class="text-nowrap">
Please take our Please take our
<a target="_blank" class="font-weight-bold" href="https://go.microsoft.com/fwlink/?linkid=2127996">brief survey</a> <a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2148851">brief survey</a>
</span> </span>
and tell us what you think. and tell us what you think.
</div> </div>
@ -12,5 +12,5 @@
@code { @code {
// Demonstrates how a parent component can supply parameters // Demonstrates how a parent component can supply parameters
[Parameter] [Parameter]
public string Title { get; set; } public string? Title { get; set; }
} }

View file

@ -1,39 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0" PrivateAssets="all" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="3.2.0" PrivateAssets="all" />
<PackageReference Include="System.Net.Http.Json" Version="3.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Shared\ShoppingCartStarter.Shared.csproj" /> <ProjectReference Include="..\Shared\ShoppingCartStarter.Shared.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Update="wwwroot\images\test-image.jpg">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Update="Pages\Cart\Item.razor">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</Content>
<Content Update="wwwroot\images\test-image.jpg">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Cart\Cart.razor">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</Content>
</ItemGroup>
</Project> </Project>

View file

@ -3,6 +3,7 @@
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using ShoppingCartStarter.Client @using ShoppingCartStarter.Client

View file

@ -4,8 +4,12 @@ html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
} }
h1:focus {
outline: none;
}
a, .btn-link { a, .btn-link {
color: #0366d6; color: #0071c1;
} }
.btn-primary { .btn-primary {
@ -14,97 +18,10 @@ a, .btn-link {
border-color: #1861ac; border-color: #1861ac;
} }
app {
position: relative;
display: flex;
flex-direction: column;
}
.top-row {
height: 3.5rem;
display: flex;
align-items: center;
}
.main {
flex: 1;
}
.main .top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
}
.main .top-row > a, .main .top-row .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
}
.main .top-row a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.sidebar .top-row {
background-color: rgba(0,0,0,0.4);
}
.sidebar .navbar-brand {
font-size: 1.1rem;
}
.sidebar .oi {
width: 2rem;
font-size: 1.1rem;
vertical-align: text-top;
top: -2px;
}
.sidebar .nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.sidebar .nav-item:first-of-type {
padding-top: 1rem;
}
.sidebar .nav-item:last-of-type {
padding-bottom: 1rem;
}
.sidebar .nav-item a {
color: #d7d7d7;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
}
.sidebar .nav-item a.active {
background-color: rgba(255,255,255,0.25);
color: white;
}
.sidebar .nav-item a:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
.content { .content {
padding-top: 1.1rem; padding-top: 1.1rem;
} }
.navbar-toggler {
background-color: rgba(255, 255, 255, 0.1);
}
.valid.modified:not([type=checkbox]) { .valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050; outline: 1px solid #26b050;
} }
@ -136,48 +53,12 @@ app {
top: 0.5rem; top: 0.5rem;
} }
@media (max-width: 767.98px) { .blazor-error-boundary {
.main .top-row:not(.auth) { background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
display: none; padding: 1rem 1rem 1rem 3.7rem;
color: white;
} }
.main .top-row.auth { .blazor-error-boundary::after {
justify-content: space-between; content: "An error has occurred."
}
.main .top-row a, .main .top-row .btn-link {
margin-left: 0;
}
}
@media (min-width: 768px) {
app {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.main .top-row {
position: sticky;
top: 0;
}
.main > div {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
.navbar-toggler {
display: none;
}
.sidebar .collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
Client/wwwroot/icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
@ -8,10 +8,11 @@
<base href="/" /> <base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /> <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" /> <link href="css/app.css" rel="stylesheet" />
<link href="ShoppingCartStarter.Client.styles.css" rel="stylesheet" />
</head> </head>
<body> <body>
<app>Loading...</app> <div id="app">Loading...</div>
<div id="blazor-error-ui"> <div id="blazor-error-ui">
An unhandled error has occurred. An unhandled error has occurred.

View file

@ -1,9 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ShoppingCartStarter.Server.DomainModels; using ShoppingCartStarter.Server.DomainModels;
namespace ShoppingCartStarter.Server.Data namespace ShoppingCartStarter.Server.Data

View file

@ -2,46 +2,43 @@
using System; using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using ShoppingCartStarter.Server.Data; using ShoppingCartStarter.Server.Data;
#nullable disable
namespace ShoppingCartStarter.Server.Migrations namespace ShoppingCartStarter.Server.Migrations
{ {
[DbContext(typeof(StoreContext))] [DbContext(typeof(StoreContext))]
[Migration("20200619081259_initial")] [Migration("20211109100532_Initial")]
partial class initial partial class Initial
{ {
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder.HasAnnotation("ProductVersion", "6.0.0");
.HasAnnotation("ProductVersion", "3.1.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("ShoppingCartStarter.Server.DomainModels.LineItem", b => modelBuilder.Entity("ShoppingCartStarter.Server.DomainModels.LineItem", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int") .HasColumnType("INTEGER");
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Image") b.Property<string>("Image")
.HasColumnType("nvarchar(max)"); .HasColumnType("TEXT");
b.Property<string>("Name") b.Property<string>("Name")
.HasColumnType("nvarchar(max)"); .HasColumnType("TEXT");
b.Property<decimal>("Price") b.Property<decimal>("Price")
.HasColumnType("decimal(18,2)"); .HasColumnType("TEXT");
b.Property<int>("Quantity") b.Property<int>("Quantity")
.HasColumnType("int"); .HasColumnType("INTEGER");
b.Property<int?>("ShoppingCartId") b.Property<int?>("ShoppingCartId")
.HasColumnType("int"); .HasColumnType("INTEGER");
b.HasKey("Id"); b.HasKey("Id");
@ -54,11 +51,10 @@ namespace ShoppingCartStarter.Server.Migrations
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int") .HasColumnType("INTEGER");
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("SessionId") b.Property<int>("SessionId")
.HasColumnType("int"); .HasColumnType("INTEGER");
b.HasKey("Id"); b.HasKey("Id");
@ -72,6 +68,11 @@ namespace ShoppingCartStarter.Server.Migrations
.HasForeignKey("ShoppingCartId") .HasForeignKey("ShoppingCartId")
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
}); });
modelBuilder.Entity("ShoppingCartStarter.Server.DomainModels.ShoppingCart", b =>
{
b.Navigation("LineItems");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View file

@ -1,8 +1,10 @@
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ShoppingCartStarter.Server.Migrations namespace ShoppingCartStarter.Server.Migrations
{ {
public partial class initial : Migration public partial class Initial : Migration
{ {
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
{ {
@ -10,9 +12,9 @@ namespace ShoppingCartStarter.Server.Migrations
name: "Carts", name: "Carts",
columns: table => new columns: table => new
{ {
Id = table.Column<int>(nullable: false) Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"), .Annotation("Sqlite:Autoincrement", true),
SessionId = table.Column<int>(nullable: false) SessionId = table.Column<int>(type: "INTEGER", nullable: false)
}, },
constraints: table => constraints: table =>
{ {
@ -23,13 +25,13 @@ namespace ShoppingCartStarter.Server.Migrations
name: "LineItem", name: "LineItem",
columns: table => new columns: table => new
{ {
Id = table.Column<int>(nullable: false) Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"), .Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: true), Name = table.Column<string>(type: "TEXT", nullable: true),
Quantity = table.Column<int>(nullable: false), Quantity = table.Column<int>(type: "INTEGER", nullable: false),
Price = table.Column<decimal>(nullable: false), Price = table.Column<decimal>(type: "TEXT", nullable: false),
Image = table.Column<string>(nullable: true), Image = table.Column<string>(type: "TEXT", nullable: true),
ShoppingCartId = table.Column<int>(nullable: true) ShoppingCartId = table.Column<int>(type: "INTEGER", nullable: true)
}, },
constraints: table => constraints: table =>
{ {

View file

@ -2,10 +2,11 @@
using System; using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using ShoppingCartStarter.Server.Data; using ShoppingCartStarter.Server.Data;
#nullable disable
namespace ShoppingCartStarter.Server.Migrations namespace ShoppingCartStarter.Server.Migrations
{ {
[DbContext(typeof(StoreContext))] [DbContext(typeof(StoreContext))]
@ -14,32 +15,28 @@ namespace ShoppingCartStarter.Server.Migrations
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder.HasAnnotation("ProductVersion", "6.0.0");
.HasAnnotation("ProductVersion", "3.1.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("ShoppingCartStarter.Server.DomainModels.LineItem", b => modelBuilder.Entity("ShoppingCartStarter.Server.DomainModels.LineItem", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int") .HasColumnType("INTEGER");
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Image") b.Property<string>("Image")
.HasColumnType("nvarchar(max)"); .HasColumnType("TEXT");
b.Property<string>("Name") b.Property<string>("Name")
.HasColumnType("nvarchar(max)"); .HasColumnType("TEXT");
b.Property<decimal>("Price") b.Property<decimal>("Price")
.HasColumnType("decimal(18,2)"); .HasColumnType("TEXT");
b.Property<int>("Quantity") b.Property<int>("Quantity")
.HasColumnType("int"); .HasColumnType("INTEGER");
b.Property<int?>("ShoppingCartId") b.Property<int?>("ShoppingCartId")
.HasColumnType("int"); .HasColumnType("INTEGER");
b.HasKey("Id"); b.HasKey("Id");
@ -52,11 +49,10 @@ namespace ShoppingCartStarter.Server.Migrations
{ {
b.Property<int>("Id") b.Property<int>("Id")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("int") .HasColumnType("INTEGER");
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("SessionId") b.Property<int>("SessionId")
.HasColumnType("int"); .HasColumnType("INTEGER");
b.HasKey("Id"); b.HasKey("Id");
@ -70,6 +66,11 @@ namespace ShoppingCartStarter.Server.Migrations
.HasForeignKey("ShoppingCartId") .HasForeignKey("ShoppingCartId")
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
}); });
modelBuilder.Entity("ShoppingCartStarter.Server.DomainModels.ShoppingCart", b =>
{
b.Navigation("LineItems");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View file

@ -1,10 +1,20 @@
@page @page
@model ShoppingCartStarter.Server.Pages.ErrorModel @model ShoppingCartStarter.Server.Pages.ErrorModel
@{
Layout = "_Layout";
ViewData["Title"] = "Error";
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Error</title>
<link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="~/css/app.css" rel="stylesheet" asp-append-version="true" />
</head>
<body>
<div class="main">
<div class="content px-4">
<h1 class="text-danger">Error.</h1> <h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2> <h2 class="text-danger">An error occurred while processing your request.</h2>
@ -25,3 +35,8 @@
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong> 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. and restarting the app.
</p> </p>
</div>
</div>
</body>
</html>

View file

@ -1,18 +1,14 @@
using System; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging; using System.Diagnostics;
namespace ShoppingCartStarter.Server.Pages namespace ShoppingCartStarter.Server.Pages
{ {
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel public class ErrorModel : PageModel
{ {
public string RequestId { get; set; } public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

View file

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>@ViewBag.Title</title>
<link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="~/css/app.css" rel="stylesheet" />
</head>
<body>
<div class="main">
<div class="content px-4">
@RenderBody()
</div>
</div>
</body>
</html>

View file

@ -1,26 +1,36 @@
using System; using Microsoft.AspNetCore.ResponseCompression;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ShoppingCartStarter.Server var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{ {
public class Program app.UseWebAssemblyDebugging();
}
else
{ {
public static void Main(string[] args) app.UseExceptionHandler("/Error");
{ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
CreateHostBuilder(args).Build().Run(); app.UseHsts();
} }
public static IHostBuilder CreateHostBuilder(string[] args) => app.UseHttpsRedirection();
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => app.UseBlazorFrameworkFiles();
{ app.UseStaticFiles();
webBuilder.UseStartup<Startup>();
}); app.UseRouting();
}
}
app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile("index.html");
app.Run();

View file

@ -3,11 +3,21 @@
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:65269", "applicationUrl": "http://localhost:24471",
"sslPort": 44368 "sslPort": 44335
} }
}, },
"profiles": { "profiles": {
"ShoppingCartStarter.Server": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7109;http://localhost:5109",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"launchBrowser": true, "launchBrowser": true,
@ -15,15 +25,6 @@
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
},
"ShoppingCartStarter.Server": {
"commandName": "Project",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
} }
} }
} }

View file

@ -1,16 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.0.0" /> <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="3.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.5" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.5" /> <PrivateAssets>all</PrivateAssets>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.5" /> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.5" /> </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,66 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Linq;
using System.Reflection;
using MediatR;
using Microsoft.EntityFrameworkCore;
using ShoppingCartStarter.Server.Data;
namespace ShoppingCartStarter.Server
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
services.AddMediatR(Assembly.GetExecutingAssembly());
services.AddDbContext<StoreContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
Database.InitialiseDatabase(app, env);
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
}
}

View file

@ -2,11 +2,10 @@
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",
"Microsoft": "Warning", "Microsoft.AspNetCore": "Warning"
"Microsoft.Hosting.Lifetime": "Information"
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=BlazorShoppingCartStarter;Trusted_Connection=True;MultipleActiveResultSets=true" "DefaultConnection": "Data Source=shoppingcart.sqlite"
} }
} }

View file

@ -2,8 +2,7 @@
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",
"Microsoft": "Warning", "Microsoft.AspNetCore": "Warning"
"Microsoft.Hosting.Lifetime": "Information"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*"

View file

@ -1,8 +1,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using MediatR; using MediatR;
namespace ShoppingCartStarter.Shared.Cart namespace ShoppingCartStarter.Shared.Cart;
{
public class Details public class Details
{ {
public class Query : IRequest<Model> public class Query : IRequest<Model>
@ -23,4 +23,3 @@ namespace ShoppingCartStarter.Shared.Cart
} }
} }
} }
}

View file

@ -1,7 +1,7 @@
using MediatR; using MediatR;
namespace ShoppingCartStarter.Shared.Cart.LineItem namespace ShoppingCartStarter.Shared.Cart.LineItem;
{
public class Delete public class Delete
{ {
public class Command : IRequest public class Command : IRequest
@ -9,4 +9,3 @@ namespace ShoppingCartStarter.Shared.Cart.LineItem
public int Id { get; set; } public int Id { get; set; }
} }
} }
}

View file

@ -1,7 +1,7 @@
using MediatR; using MediatR;
namespace ShoppingCartStarter.Shared.Cart.LineItem namespace ShoppingCartStarter.Shared.Cart.LineItem;
{
public class Update public class Update
{ {
public class Command : IRequest public class Command : IRequest
@ -10,4 +10,3 @@ namespace ShoppingCartStarter.Shared.Cart.LineItem
public int Quantity { get; set; } public int Quantity { get; set; }
} }
} }
}

View file

@ -1,11 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MediatR" Version="8.0.1" /> <PackageReference Include="MediatR" Version="9.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>
</Project> </Project>