【ASP.NET Core笔记】 使用razor pages构建网站

news/2025/2/14 4:21:30/

使用ASP.NET Core Razor Pages 构建网站

sqlite 北风数据库

1. Northwind.Common.DataContext.Sqlite

d32927bd1447fd1558a30bcc85eb295b.png


是Sqlite的数据库上下文,有三个类:
ConsoleLogger.cs
NorthwindContext.cs
NorthwindContextExtensions.cs

1.1 NorthwindContext 继承自 Microsoft.EntityFrameworkCore.DbContext

1.1.1 定义了表结构实例

表结构表实例
类别表DbSet<Category> Categories
消费者表DbSet<Customer> Customers
雇员表DbSet<Employee> Employees
员工地域DbSet<EmployeeTerritory> EmployeeTerritories
订单表DbSet<Order> Orders
订单详情表DbSet<OrderDetail> OrderDetails
产品表DbSet<Product> Products
托运人DbSet<Shipper> Shippers
供应商DbSet<Supplier> Suppliers
地域表DbSet<Territory> Territories

1.1.2模型创建 OnModelCreating() 函数

protected override void OnModelCreating(ModelBuilder modelBuilder)//模型创建
{ //订单详情:多个主键,用FLUENT API 来定义modelBuilder.Entity<OrderDetail>(entity =>{   //两个主键entity.HasKey(e => new { e.OrderId, e.ProductId }); //订单ID、产品ID//一个订单有多个订单详情entity.HasOne(d => d.Order).WithMany(p => p.OrderDetails).HasForeignKey(d => d.OrderId)//外键:订单ID.OnDelete(DeleteBehavior.ClientSetNull);//1个产品可以有多个订单详情entity.HasOne(d => d.Product).WithMany(p => p.OrderDetails).HasForeignKey(d => d.ProductId)//外键:产品ID.OnDelete(DeleteBehavior.ClientSetNull);//配置删除主体或切断关系时应用于关系中依赖实体的操作。});//产品modelBuilder.Entity<Product>() //产品单价转为double.Property(product => product.UnitPrice).HasConversion<double>(); OnModelCreatingPartial(modelBuilder);
}

1.2 ConsoleLogger.cs

控制台日志输出功能

1.3 NorthwindContextExtensions.cs

将 NorthwindContext 添加到指定的 IServiceCollection。使用 Sqlite 数据库提供程序。

2. Northwind.Common.EntityModels.Sqlite

8cd76f7c9cf0f01bbd4c3bca9e13ca03.png


2.1 实体的C#类

实体模型表 加粗字段为实体集合需要在类的构造函数中初始化,例如:Customer 类的 Orders

public Customer(){   //初始化订单Orders = new HashSet<Order>();}

粗斜体 为实体对象

实体文件成员
类别Category.csCategoryId、CategoryName、Description、Picture 、Products
消费者Customer.csCustomerId、CompanyName、ContactName、ContactTitle、Address、City、Region、PostalCode、Country、Phone、 Fax、Orders
雇员Employee.csEmployeeId、LastName、FirstName、Title、TitleOfCourtesy、BirthDate、HireDate、Address、City、Region、PostalCode、Country、HomePhone、Extension、Photo、Notes、ReportsTo、PhotoPath、Orders
员工地域EmployeeTerritory.csEmployeeId、TerritoryId
订单Order.csOrderId、CustomerId、EmployeeId、OrderDate、RequiredDate、ShippedDate、ShipVia、Freight、ShipName、ShipAddress、ShipCity、ShipRegion、ShipPostalCode、ShipCountry、CustomerEmployeeShipViaNavigationOrderDetails
订单详情OrderDetail.csOrderId、ProductId、UnitPrice、Quantity、Discount、OrderProduct
产品Product.csProductId、ProductName、SupplierId、CategoryId、QuantityPerUnit、UnitPrice、UnitsInStock、UnitsOnOrder、ReorderLevel、Discontinued、CategorySupplierOrderDetails
托运人Shipper.csShipperId、CompanyName、Phone、Orders
供应商Suppliers.csSupplierId、CompanyName、ContactName、ContactTitle、Address、City、Region、PostalCode、Country、Phone、Fax、HomePage、Products
地域Territory.csTerritoryId、TerritoryDescription、RegionId

2.2 特性

[Key]
设置主键
[Required]
非空,必须有
[Column(TypeName = "nvarchar (15)")]
设置与数据库列对应的属性,数据格式
[StringLength(15)]
自定字段允许的最小和最大字符长度
[InverseProperty(nameof(Product.Supplier))]
指定表示同一关系另一端的导航属性的反转
[Index(nameof(CompanyName), Name = "CompanyNameSuppliers")]
指定要在数据库中生成的索引。
[ForeignKey(nameof(CategoryId))]
外键:类别ID
[Table("Order Details")]
指定类映射到的数据库表。

3. Northwind.Razor.Employees 类库

1f0db8a3268f3caa1c92cf910b82ecf8.png


雇员查询网页razor page.

ef185548253ef79cada32a3db18f225f.png

<!--单个雇员_Employee.cshtml-->
@model Packt.Shared.Employee
<div class="card border-dark mb-3" style="max-width: 18rem;"><div class="card-header">@Model?.LastName, @Model?.FirstName</div><div class="card-body text-dark"><h5 class="card-title">@Model?.Country</h5><p class="card-text">@Model?.Notes</p></div>
</div>
<!--_ViewStart.cshtml 指定共享布局-->
@{Layout = "_Layout";
}
<!-- Employees.cshtml 雇员列表-- >
@page
@using Packt.Shared
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 
@model PacktFeatures.Pages.EmployeesPageModel
<div class="row"><h1 class="display-2">Employees</h1>
</div>
<div class="row">
@foreach(Employee employee in Model.Employees)
{<div class="col-sm-3"><partial name="_Employee" model="employee" /></div>
}
</div>
//查询雇员
using Microsoft.AspNetCore.Mvc.RazorPages; // PageModel
using Packt.Shared; // Employee, NorthwindContextnamespace PacktFeatures.Pages;public class EmployeesPageModel : PageModel
{private NorthwindContext db;public EmployeesPageModel(NorthwindContext injectedContext){db = injectedContext;}public Employee[] Employees { get; set; } = null!;public void OnGet(){ViewData["Title"] = "Northwind B2B - Employees";Employees = db.Employees.OrderBy(e => e.LastName).ThenBy(e => e.FirstName).ToArray();}
}

4. Northwind.Web

c361e3fa1831b9d3a05a5d442e7014e2.png


双击项目在编辑器中打开.csproj 文件可看到Web SDK已引用:
<Project Sdk="Microsoft.NET.Sdk.Web">

添加项目引用

  • Northwind.Common.DataContext.Sqlite\Northwind.Common.DataContext.Sqlite.csproj

  • 1Northwind.Razor.Employees\Northwind.Razor.Employees.csproj

4.1 Program.cs 有一个Main方法作为入口点

使用默认值配置 Microsoft.Extensions.Hosting.IHostBuilder 以托管 Web 应用程序。这应该在应用程序特定配置之前调用,以避免它覆盖提供的服务、配置源、环境、内容根等。

一个 ASP.NET Core 项目就像一个顶级控制台应用程序,以一个隐藏的 Main 方法作为其入口点,该方法有一个使用名称 args 传递的参数。

//对 Run 方法的调用是一个阻塞调用,因此隐藏的 Main 方法在 web 服务器停止运行之前不会返回,如以下代码所示:Host.CreateDefaultBuilder(args).ConfigureWebHostDetails(webBuilder => {webBuilder.UseStartup<Startup>();//指定 Web 主机要使用的启动类型。}).Build().Run();

4.2 Startup.cs 进一步配置网页

using Packt.Shared; // AddNorthwindContext extension method
using static System.Console;
namespace Northwind.Web;public class Startup
{public void ConfigureServices(IServiceCollection services){services.AddRazorPages();//将页面的服务添加到指定的 Microsoft.Extensions.DependencyInjection.IServiceCollection。services.AddNorthwindContext();//将 NorthwindContext 添加到指定的 IServiceCollection。使用 Sqlite 数据库提供程序。}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (!env.IsDevelopment())//检查当前主机环境名称是否为 Microsoft.Extensions.Hosting.EnvironmentName.Development。{app.UseHsts();//添加使用 HSTS 的中间件,它添加了 Strict-Transport-Security 标头。}app.UseRouting(); // 开始端点路由 start endpoint routing/*将内联定义的中间件委托添加到应用程序的请求管道。如果您不调用下一个函数,请改用 Microsoft.AspNetCore.Builder.RunExtensions.Run(Microsoft.AspNetCore.Builder.IApplicationBuilder,Microsoft.AspNetCore.Http.RequestDelegate)。更喜欢使用 Microsoft.AspNetCore.Builder.UseExtensions.Use(Microsoft.AspNetCore.Builder.IApplicationBuilder,System.Func{Microsoft.AspNetCore.Http.HttpContext,Microsoft.AspNetCore.Http.RequestDelegate,System.Threading.Tasks.Task})// 为了获得更好的性能,如下所示:*/app.Use(async (HttpContext context, Func<Task> next) =>{   //表示可用于 URL 匹配或 URL 生成的 Microsoft.AspNetCore.Http.Endpoint。RouteEndpoint? rep = context.GetEndpoint() as RouteEndpoint;//获取当前请求的 Microsoft.AspNetCore.Http.Endpoint 的扩展方法if (rep is not null){WriteLine($"Endpoint name: {rep.DisplayName}");//获取此端点的信息显示名称。WriteLine($"Endpoint route pattern: {rep.RoutePattern.RawText}");//获取解析路由模式时提供的原始文本。可能为空。}if (context.Request.Path == "/bonjour"){// in the case of a match on URL path, this becomes a terminating// delegate that returns so does not call the next delegate// 在 URL 路径匹配的情况下,这将成为返回的终止委托,因此不会调用下一个委托await context.Response.WriteAsync("Bonjour Monde!");//你好世界return;}//我们可以在调用下一个委托之前修改请求 we could modify the request before calling the next delegateawait next();//我们可以在调用下一个委托后修改响应 we could modify the response after calling the next delegate});app.UseHttpsRedirection();//添加用于将 HTTP 请求重定向到 HTTPS 的中间件。app.UseDefaultFiles(); //在当前路径上启用默认文件映射 index.html, default.html, and so onapp.UseStaticFiles();//为当前请求路径启用静-态文件服务app.UseEndpoints(endpoints =>{endpoints.MapRazorPages();//将 Razor Pages 的终结点添加到 Microsoft.AspNetCore.Routing.IEndpointRouteBuilder。//将 Microsoft.AspNetCore.Routing.RouteEndpoint 添加到与指定模式的 HTTP GET 请求匹配的 Microsoft.AspNetCore.Routing.IEndpointRouteBuilder。endpoints.MapGet("/", () => "Hello World!");//该网站将以纯文本响应所有 HTTP GET 请求:Hello World!。});}
}

4.3 共享布局

4.3.1 布局文件:Pages/Shared/_Layout.cshtml

<!doctype html><html lang="en"><head><!-- Required meta tags必需的元标记 --><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /><!-- Bootstrap CSS 样式 --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous"><title>@ViewData["Title"]</title></head><body><div class="container">@RenderBody()<hr /><footer><p>Copyright &copy; 2021 - @ViewData["Title"]</p><!-- @ViewData["Title"],使用该布局的页面的变量 --></footer></div><!-- JavaScript to enable features like carousel 启用轮播等功能的 JavaScript --><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous"></script>@RenderSection("Scripts", required: false)<!-- 在布局页,渲染名为 Scripts 的部分 --></body></html>

4.3.2 _ViewStart.cshtml设置所有 Razor 页面(和所有 MVC 视图)的默认布局文件

@{Layout = "_Layout";}

4.4 索引页面

一些按钮,以及链接href

a4fb6fc63617b900d7a22bfb037b8fb3.png

@page@functions{public string? DayName { get; set; } //日期参数public void OnGet(){ViewData["Title"] = "Northwind B2B";Model.DayName = DateTime.Now.ToString("dddd");}}<div class="jumbotron"><h1 class="display-3">Welcome to Northwind B2B</h1><p class="lead">We supply products to our customers.</p>-<hr /><p>It's @Model.DayName! Our customers include restaurants, hotels, and cruise lines.</p><p><a class="btn btn-primary" href="suppliers">Learn more about our suppliers</a></p><p><a class="btn btn-primary" href="packtfeatures/employees">Contact our employees</a></p><p><a class="btn btn-primary" href="orders">How many orders have we taken?</a></p><p><a class="btn btn-primary" href="customers">Our customers are global</a></p><p><a class="btn btn-primary" href="functions">Play with functions</a></p></div>

4.5 订单页面

注入数据库上下文,没有cs文件

6ec8ed9848e8c75a81f65756730ec630.png

@page
@using Packt.Shared
@inject NorthwindContext db
@{string title = "Orders";ViewData["Title"] = $"Northwind B2B - {title}";
}
<div class="row"><h1 class="display-2">@title</h1><p>There are @db.Orders.Count() orders in the Northwind database.</p>
</div>

4.6 供应商

页面显示供应商表格

94b534a8187699a18a86742437cc82db.png

@page
@using Packt.Shared
@model Northwind.Web.Pages.SuppliersModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<div class="row"><h1 class="display-2">Suppliers</h1><table class="table"><thead class="thead-inverse"><tr><th>Company Name</th><th>Country</th><th>Phone</th></tr></thead><tbody>@if (Model.Suppliers is not null){@foreach(Supplier s in Model.Suppliers){<tr><td>@s.CompanyName</td><td>@s.Country</td><td>@s.Phone</td></tr>}}</tbody></table>
</div>
<div class="row"><p>Enter details for a new supplier:</p><form method="POST"><div><input asp-for="Supplier.CompanyName" placeholder="Company Name" /></div><div><input asp-for="Supplier.Country" placeholder="Country" /></div><div><input asp-for="Supplier.Phone" placeholder="Phone" /></div><input type="submit" /></form>
</div>

SuppliersModel 继承自PageModel

using Microsoft.AspNetCore.Mvc.RazorPages; // PageModel
using Packt.Shared; // NorthwindContext
using Microsoft.AspNetCore.Mvc; // [BindProperty], IActionResultnamespace Northwind.Web.Pages;public class SuppliersModel : PageModel
{public IEnumerable<Supplier>? Suppliers { get; set; }private NorthwindContext db;public SuppliersModel(NorthwindContext injectedContext){db = injectedContext;}public void OnGet(){ViewData["Title"] = "Northwind B2B - Suppliers";Suppliers = db.Suppliers.OrderBy(c => c.Country).ThenBy(c => c.CompanyName);}[BindProperty]public Supplier? Supplier { get; set; }// = null!;public IActionResult OnPost() //提交查询内容{if ((Supplier is not null) && ModelState.IsValid)//获取一个值,该值指示此模型状态字典中的任何模型状态值是否无效或未经验证。{db.Suppliers.Add(Supplier);//添加供应商db.SaveChanges();return RedirectToPage("/suppliers");//重定向到页面,刷新数据}else{return Page(); // return to original page}}
}

4.7 函数计算器页面

20b47c50ba77c344c6c8bbb451c93303.png

@page
@using Northwind.Web.Pages
@using Packt.Shared
@model FunctionsModel
@{string title = "Functions";ViewData["Title"] = $"Northwind B2B - {title}";//共享布局参数string collapsedTimesTable = Model.TimesTableNumberInput.HasValue ? string.Empty : "collapse";string collapsedCalculateTax = Model.Amount.HasValue ? string.Empty : "collapse";string collapsedFactorial = Model.FactorialNumber.HasValue ? string.Empty : "collapse";string collapsedFibonacci = Model.FibonacciNumber.HasValue ? string.Empty : "collapse";
}
<div class="row"><h1 class="display-2">@title</h1><div><h2>Exercise 14.3 – Practice building web pages for console apps</h2><div>Provide a web user interface to output times tables, calculate tax, and generate factorials and the Fibonacci sequence.</div></div><div class="accordion" id="accordionFunctions"> <!--  --><div class="accordion-item"><!-- 按钮 --><h2 class="accordion-header" id="headerTimesTable"><button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTimesTable" aria-expanded="true" aria-controls="collapseTimesTable">Times Table</button></h2><!-- 展开控件 --><div id="collapseTimesTable" class="accordion-collapse @collapsedTimesTable" aria-labelledby="headingTimesTable" data-bs-parent="#accordionTimesTable"><div class="accordion-body"><form><div class="mb-3"><label for="timesTableNumberInput" class="form-label">Number</label><input type="number" class="form-control" id="timesTableNumberInput" name="timesTableNumberInput" aria-describedby="timesTableNumberHelp"><div id="timesTableNumberHelp" class="form-text">Enter an integer between 1 and 100.</div></div><button type="submit" class="btn btn-primary">Submit</button></form>@if (Model.TimesTableNumberInput.HasValue){<div class="card" style="width: 18rem;"><div class="card-body"><h5 class="card-title">@Model.TimesTableNumberInput times table</h5>@for (int i = 1; i <= 12; i++){<div>@i x @Model.TimesTableNumberInput = @(i * Model.TimesTableNumberInput)</div>}</div></div>}</div></div></div><div class="accordion-item"><!-- 税金计算  手风琴项 --><h2 class="accordion-header" id="headerCalculateTax"><button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseCalculateTax" aria-expanded="true" aria-controls="collapseCalculateTax">Calculate Tax</button></h2><!-- 展开控件 --><div id="collapseCalculateTax" class="accordion-collapse @collapsedCalculateTax" aria-labelledby="headingCalculateTax" data-bs-parent="#accordionCalculateTax"><div class="accordion-body"><form><div class="mb-3"><label for="calculateTaxAmountInput" class="form-label">Amount</label><input type="number" class="form-control" id="calculateTaxAmountInput" name="calculateTaxAmountInput" aria-describedby="calculateTaxAmountInputHelp"><div id="calculateTaxAmountInputHelp" class="form-text">Enter a monetary value.</div></div><div class="mb-3"><label for="calculateTaxRegionCodeInput" class="form-label">Region</label><!-- 选择控件:两组选项 --><select class="form-control" id="calculateTaxRegionCodeInput" name="calculateTaxRegionCodeInput" aria-describedby="calculateTaxRegionCodeInputHelp"><optgroup label="Europe"><option value="DK">Denmark</option><option value="FR">France</option><option value="HU">Hungary</option><option value="NO">Norway</option><option value="CH">Switzerland</option><option value="GB">United Kingdom</option></optgroup><optgroup label="United States"><option value="AK">Alaska</option><option value="OR">Oregon</option><option value="MT">Montana</option><option value="ND">North Dakota</option><option value="WI">Wisconsin</option><option value="ME">Maine</option><option value="VA">Virginia</option><option value="CA">California</option><option value="OT">Other</option></optgroup></select><div id="calculateTaxRegionCodeInputHelp" class="form-text">Select a European or US state.</div></div><button type="submit" class="btn btn-primary">Submit</button></form>@if (Model.Amount.HasValue){<div class="card" style="width: 18rem;"><div class="card-body"><h5 class="card-title">You must pay @Model.TaxToPay in tax.</h5></div></div>}</div></div></div><div class="accordion-item"><!-- 阶乘计算 --><h2 class="accordion-header" id="headerFactorials"><button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFactorials" aria-expanded="true" aria-controls="collapseFactorials">Factorials</button></h2><!-- 展开控件 --><div id="collapseFactorials" class="accordion-collapse @collapsedFactorial" aria-labelledby="headingFactorials" data-bs-parent="#accordionFactorials"><div class="accordion-body"><div><form><div class="mb-3"><label for="factorialNumberInput" class="form-label">Number</label><input type="number" class="form-control" id="factorialNumberInput" name="factorialNumberInput" aria-describedby="factorialNumberHelp"><div id="factorialNumberHelp" class="form-text">Enter an integer between 1 and 12.</div></div><button type="submit" class="btn btn-primary">Submit</button></form>@if (Model.FactorialNumber.HasValue){<div class="card" style="width: 18rem;"><div class="card-body"><h5 class="card-title">@(Model.FactorialNumber)!</h5><div>@(Model.FactorialNumber)! = @(Model.FactorialResult is null ? "null" : Model.FactorialResult.Value.ToString("N0"))</div></div></div>}@if (Model.FactorialException is not null){<div class="card" style="width: 18rem;"><div class="card-body"><h5 class="card-title">Exception</h5><div>@Model.FactorialException.Message</div></div></div>}</div></div></div></div><div class="accordion-item"><!-- 斐波那契数列 --><h2 class="accordion-header" id="headerFibonacciSequence"><button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFibonacciSequence" aria-expanded="true" aria-controls="collapseFibonacciSequence">Fibonacci sequence</button></h2><!-- 展开控件 --><div id="collapseFibonacciSequence" class="accordion-collapse @collapsedFibonacci" aria-labelledby="headingFibonacciSequence" data-bs-parent="#accordionCustomers"><div class="accordion-body"><div><form><div class="mb-3"><label for="fibonacciNumberInput" class="form-label">Term</label><input type="number" class="form-control" id="fibonacciNumberInput" name="fibonacciNumberInput" aria-describedby="fibonacciNumberHelp"><div id="fibonacciNumberHelp" class="form-text">Enter an integer between 1 and 40.</div></div><button type="submit" class="btn btn-primary">Submit</button></form>@if (Model.FibonacciNumber.HasValue){<div class="card" style="width: 18rem;"><div class="card-body"><h5 class="card-title">Fibonacci term @Model.FibonacciNumber</h5><div>Term @Model.FibonacciNumber of the fibonacci sequence = @(Model.FibonacciResult is null ? "null" : Model.FibonacciResult.Value.ToString("N0"))</div></div></div>}</div></div></div></div></div>
</div><p data-line="631" class="sync-line" style="margin:0;"></p>
using Microsoft.AspNetCore.Mvc.RazorPages;namespace Northwind.Web.Pages;public class FunctionsModel : PageModel
{public int? TimesTableNumberInput { get; set; }public decimal? Amount { get; set; }public string? RegionCode { get; set; }public decimal? TaxToPay { get; set; }public int? FactorialNumber { get; set; }public int? FactorialResult { get; set; }public Exception? FactorialException { get; set; }public int? FibonacciNumber { get; set; }public int? FibonacciResult { get; set; }public void OnGet()//处理请求{// Times Tableif (int.TryParse(HttpContext.Request.Query["timesTableNumberInput"], out int i)){TimesTableNumberInput = i;//取得乘法表参数}// Calculate Taxif (decimal.TryParse(HttpContext.Request.Query["calculateTaxAmountInput"], out decimal amount)){Amount = amount;RegionCode = HttpContext.Request.Query["calculateTaxRegionCodeInput"];//取得税金计算参数:区域代码TaxToPay = CalculateTax(amount: amount, twoLetterRegionCode: RegionCode);}// Factorialif (int.TryParse(HttpContext.Request.Query["factorialNumberInput"], out int fact)){FactorialNumber = fact;//阶乘计算参数try{FactorialResult = Factorial(fact);}catch (Exception ex){FactorialException = ex;}}// Fibonacciif (int.TryParse(HttpContext.Request.Query["fibonacciNumberInput"], out int fib)){FibonacciNumber = fib; //斐波那契数列计算参数FibonacciResult = FibImperative(term: fib);}}static decimal CalculateTax(//decimal amount, string twoLetterRegionCode){decimal rate = 0.0M;//税率// since we are matching string values a switch// 因为我们匹配字符串值一个switch// 语句比 switch 表达式更简单// statement is easier than a switch expressionswitch (twoLetterRegionCode){case "CH": // Switzerland rate = 0.08M;break;case "DK": // Denmark case "NO": // Norwayrate = 0.25M;break;case "GB": // United Kingdomcase "FR": // Francerate = 0.2M;break;case "HU": // Hungaryrate = 0.27M;break;case "OR": // Oregoncase "AK": // Alaskacase "MT": // Montanarate = 0.0M;break;case "ND": // North Dakotacase "WI": // Wisconsincase "ME": // Mainecase "VA": // Virginiarate = 0.05M;break;case "CA": // Californiarate = 0.0825M;break;default: // most US states rate = 0.06M;break;}return amount * rate;}static int Factorial(int number)//阶乘{if (number < 0){throw new ArgumentException(message: "The factorial function is defined for non-negative integers only.",paramName: "number");}else if (number == 0){return 1;}else{checked // for overflow{return number * Factorial(number - 1);}}}static int FibImperative(int term)//斐波那契数列{if (term == 1){return 0;}else if (term == 2){return 1;}else{return FibImperative(term - 1) + FibImperative(term - 2);}}}

4.8 消费者页面

7085bb98b843502058dcc2ed34fb1f2b.png

@page
@using Northwind.Web.Pages
@using Packt.Shared
@model CustomersModel
@{string title = "Customers by Country";ViewData["Title"] = $"Northwind B2B - {title}";//浏览器选项卡页标题
}
<div class="row"><h1 class="display-2">@title</h1><div><h2>Exercise 14.2 – Practice building a data-driven web page</h2></div><div class="accordion" id="accordionCustomers"><!--accordion手风琴-->@if (Model.CustomersByCountry is not null){@foreach (IGrouping<string?, Customer> cbc in Model.CustomersByCountry){<div class="accordion-item"> <!-- 手风琴项--><h2 class="accordion-header" id="header@(cbc.Key)"><button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapse@(cbc.Key)" aria-expanded="true" aria-controls="collapse@(cbc.Key)">@cbc.Key has @cbc.Count() customers</button></h2><div id="collapse@(cbc.Key)" class="accordion-collapse collapse" aria-labelledby="heading@(cbc.Key)" data-bs-parent="#accordionCustomers"><div class="accordion-body"><ul>  <!-- 列出消费者-->@foreach (Customer c in cbc){<li><a href="customerorders?id=@c.CustomerId">  <!-- 链接到订单页面 customerorders  id 作为请求信息 被 订单页面检索-->@c.CompanyName</a></li>}</ul></div></div></div>}}</div>
</div>
using Microsoft.AspNetCore.Mvc.RazorPages; // PageModel
using Packt.Shared; // Customernamespace Northwind.Web.Pages;public class CustomersModel : PageModel
{//为将键映射到 System.Collections.Generic.IEnumerable`1 值序列的数据结构定义索引器、大小属性和布尔搜索方法。public ILookup<string?, Customer>? CustomersByCountry;private NorthwindContext db;public CustomersModel(NorthwindContext db){this.db = db;//初始化数据库}public void OnGet(){   //根据指定的键选择器函数从 System.Collections.Generic.IEnumerable`1 创建 System.Linq.Lookup`2。//返回:包含键和值的 System.Linq.Lookup`2。每个组中的值与源中的顺序相同。CustomersByCountry = db.Customers.ToLookup(c => c.Country);}
}

4.9 CustomerOrders消费者的订单页面

bc68a681e78260f0abd5712dfad2bc89.png

@page
@using Northwind.Web.Pages
@using Packt.Shared
@model CustomerOrdersModel
@{string title = "Customer and their orders";ViewData["Title"] = $"Northwind B2B - {title}";
}
<div class="row"><h1 class="display-2">@title</h1><div>@if (Model.Customer is not null){<div><div>@Model.Customer.CompanyName</div></div><div><table> <!-- 表--><thead> <!-- 表头--><tr><th>Order Id</th><th>Order Date</th></tr></thead><tbody> <!-- 表数据 -->@foreach (Order o in Model.Customer.Orders){ <!-- td  --><tr><td>@o.OrderId</td><td>@o.OrderDate</td></tr>}</tbody></table></div>}</div>
</div>
using Microsoft.AspNetCore.Mvc.RazorPages; // PageModel
using Microsoft.EntityFrameworkCore; // Include extension method
using Packt.Shared; // Customernamespace Northwind.Web.Pages;public class CustomerOrdersModel : PageModel
{public Customer? Customer;private NorthwindContext db;public CustomerOrdersModel(NorthwindContext db){this.db = db;}public void OnGet(){string id = HttpContext.Request.Query["id"];//获取http请求中的 "id"Customer = db.Customers.Include(c => c.Orders).SingleOrDefault(c => c.CustomerId == id);}
}

The End


http://www.ppmy.cn/news/72664.html

相关文章

【5.20】五、安全测试——概念与漏洞

目录 5.1 安全测试概述 5.1.1 什么是安全测试 5.1.2 安全测试的基本原则 5.2 常见的安全漏洞 5.2.1 SQL注入 5.2.2 XSS跨站脚本攻击 5.2.3 CSRF攻击 软件安全测试是软件测试的重要研究领域&#xff0c;它是保证软件能够安全使用的最主要手段&#xff0c;做好软件安全测试…

〖Python网络爬虫实战㉗〗- Selenium案例实战(一)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 说明&#xff1a;本专栏持续更新中&#xff0c;目前专栏免费订阅&#xff0c;在转为付费专栏前订阅本专栏的&#xff0c;可以免费订阅付…

国内外数据安全治理框架介绍与分析

本文将介绍和分析:微软 DGPC框架,Gartner 数据安全治理框架 DSG,数据安全能力成熟度模型 DSMM 数据治理与数据安全治理系列文章 https://luozhonghua.blog.csdn.net/article/details/130417106 数据安全治理流程设计_luozhonghua2000的博客-CSDN博客 数据治理解决之道探讨…

Aixcoder:AI辅助编程工具

【产品介绍】 aixcoder是一款基于深度学习人工智能技术的AI辅助编程工具。提供了一个由各个领域的专业代码训练出来的“虚拟编程专家”&#xff0c;通过与aixcoder进行结对编程&#xff0c;程序员可以感受到工作效率的显著提升。 借助aixcoder的帮助&#xff0c;程序员可以摆脱…

测试理论----Bug的严重程度(Severity)和优先级(Priority)的分类

【原文链接】测试理论----Bug的严重程度&#xff08;Severity&#xff09;和优先级&#xff08;Priority&#xff09;的分类 一、Bug的严重程度&#xff08;Severity&#xff09; Bug的Severity&#xff08;严重程度&#xff09;指的是一个Bug对软件系统功能影响的程度&#…

JavaScript如何实现上拉加载,下拉刷新?

一、前言 下拉刷新和上拉加载这两种交互方式通常出现在移动端中。本质上等同于PC网页中的分页&#xff0c;只是交互形式不同。开源社区也有很多优秀的解决方案&#xff0c;如iscroll、better-scroll、pulltorefresh.js库等等。这些第三方库使用起来非常便捷。我们通过原生的方式…

Java ArrayList

Java ArrayList 目录 Java ArrayList 添加元素 实例 访问元素 实例 修改元素 实例 删除元素 实例 计算大小 实例 迭代数组列表 实例 实例 其他的引用类型 实例 ArrayList 排序 实例 实例 Java ArrayList 方法 正在上传…重新上传取消 Java 集合框架 Arra…

【Linux】7. 进程概念

在进程的学习之前首先需要理解并掌握冯诺依曼体系结构及操作系统的相关概念 1. 冯诺依曼体系结构 最终我们得到的结论是&#xff1a; 在数据层面上 CPU不与外部设备进行交互&#xff0c;而是直接和内存交互所有的外部设备需要数据载入&#xff0c;只能载入到内存中。数据从内…