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

news2024/12/26 13:53:18

使用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, NorthwindContext


namespace 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 delegate
            await next();
            //我们可以在调用下一个委托后修改响应 we could modify the response after calling the next delegate
        });

        app.UseHttpsRedirection();//添加用于将 HTTP 请求重定向到 HTTPS 的中间件。

        app.UseDefaultFiles(); //在当前路径上启用默认文件映射 index.html, default.html, and so on
        app.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], IActionResult

namespace 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 Table
        if (int.TryParse(HttpContext.Request.Query["timesTableNumberInput"], out int i))
        {
            TimesTableNumberInput = i;//取得乘法表参数
        }

        // Calculate Tax
        if (decimal.TryParse(HttpContext.Request.Query["calculateTaxAmountInput"], out decimal amount))
        {
            Amount = amount;
            RegionCode = HttpContext.Request.Query["calculateTaxRegionCodeInput"];//取得税金计算参数:区域代码
            TaxToPay = CalculateTax(amount: amount, twoLetterRegionCode: RegionCode);
        }

        // Factorial
        if (int.TryParse(HttpContext.Request.Query["factorialNumberInput"], out int fact))
        {
            FactorialNumber = fact;//阶乘计算参数
            try
            {
                FactorialResult = Factorial(fact);
            }
            catch (Exception ex)
            {
                FactorialException = ex;
            }
        }

        // Fibonacci
        if (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 expression

		switch (twoLetterRegionCode)
        {
            case "CH": // Switzerland 
                rate = 0.08M;
                break;
            case "DK": // Denmark 
            case "NO": // Norway
                rate = 0.25M;
                break;
            case "GB": // United Kingdom
            case "FR": // France
                rate = 0.2M;
                break;
            case "HU": // Hungary
                rate = 0.27M;
                break;
            case "OR": // Oregon
            case "AK": // Alaska
            case "MT": // Montana
                rate = 0.0M;
                break;
            case "ND": // North Dakota
            case "WI": // Wisconsin
            case "ME": // Maine
            case "VA": // Virginia
                rate = 0.05M;
                break;
            case "CA": // California
                rate = 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; // Customer

namespace 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; // Customer

namespace 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.coloradmin.cn/o/547166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机图形学-GAMES101-10

一、纹理 原模型网格->逐面Shading->逐像素Phong Shading->纹理贴图->换个纹理再贴图->环境光照。 &#xff08;1&#xff09;环境贴图 纹理就是一张图&#xff0c;纹理是GPU里的一块内存&#xff0c;可以进行点查询、范围查询、滤波。  环境光贴图、环境光映…

The authenticity of host ‘gitee.com (212.64.63.190)‘ can‘t be established.

在将本地仓库的代码推送到远程仓库时&#xff0c;出现下面报错。 $ git push -u origin master The authenticity of host gitee.com (212.64.63.190) cant be established. ECDSA key fingerprint is SHA256:FQGC9Kn/eye1W8icdBgrQpKkGYoFgbVr17bmjey0Wc. Are you sure you w…

Kali-linux分析密码

在实现密码破解之前&#xff0c;介绍一下如何分析密码。分析密码的目的是&#xff0c;通过从目标系统、组织中收集信息来获得一个较小的密码字典。本节将介绍使用Ettercap工具或MSFCONSOLE来分析密码。 8.2.1 Ettercap工具 Ettercap是Linux下一个强大的欺骗工具&#xff0c;也…

Mysql中常用到的查询关键字

文章目录 1、join2、like 模糊查询3、or4、distinct5、in 包含6、group by 分组7、order by8、limit 1、join MySQL 的连接主要分为内连接和外连接。 什么是内连接&#xff1a; 取得两张表中满足存在连接匹配关系的记录。 什么是外连接&#xff1a; 不只取得两张表中满足存在…

设计高端大气上档次的时尚品?!微软工程师借助AIGC成功圆梦!

&#xff08;本文阅读时间&#xff1a;5 分钟&#xff09; 在这个创意横飞、想象力爆棚的时代中&#xff0c;有很多美丽且吸引人的东西围绕在我们身边。然而&#xff0c;遗憾的是&#xff0c;被誉为“攻城狮”的我&#xff0c;内心里虽然非常喜欢且欣赏这些夺目的作品&#xff…

手动输入域账号自动禁用windows域用户的脚本

禁用windows域用户的脚本&#xff0c;需求&#xff1a; 1、显示该域用户的创建时间&#xff0c;最后登录时间和存放的OU&#xff0c; 2、将该账号禁用&#xff1b; 3、禁用后重新返回交互界面等待输入新的域账号。 Powershell脚本内如下&#xff1a; # 无限循环等待用户的输入…

Meta没做成的事OpenAI要干?ChatGPT之父推出加密项目Worldcoin

大模型焦虑还未停歇&#xff0c;鬼才创始人瞄准了加密领域。 继ChatPT之后&#xff0c;OpenAI的首席执行官Sam Altman推出的加密货币项目Worldcoin近日被透露融资近一亿美金&#xff0c;彻底搅翻了科技界与Web3的平静。 据官网描述&#xff0c;Worldcoin由Sam和Max Novendstern…

奇舞周刊第492期:提升 Web 核心性能指标的 9 个建议

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 提升 Web 核心性能指标的 9 个建议 大家好&#xff0c;我是 ConardLi。今天继续来为大家解读今年的 Google I/O&#xff0c;我会重点为大家解读前端开发者应该关注的信息&#xff…

软考初级程序员上午单选题(13)

1、下列不能兼作输入设备和输出设备的是______。 A&#xff0e;可擦除型光盘 B&#xff0e;软盘 C&#xff0e;硬盘 D&#xff0e;键盘 2、文件型计算机病毒主要感染______。 A&#xff0e;.TXT文件 B&#xff0e;.GIF文件 C&#xff0e;.EXE文件 D&#xff0e;.MP3文件 3、_…

【Error】Error: Cannot find module ‘babel-preset-es2015‘

启动项目时出现了下面的错误&#xff0c;错误图如下&#xff1a; 解决办法&#xff1a; 在项目的babel.config.js文件中修改presets的参数&#xff0c;修改如下&#xff1a; 原文件&#xff1a; 修改成babel/preset-env&#xff0c;修改后文件&#xff1a;

SpringBoot源码分析之Tomcat是如何在SpringBoot中启动的?

一.前言 我们知道SpringBoot可以直接把传统的war包打成可执行的jar包&#xff0c;直接启动。这得益于SpringBoot内置了容器可以直接启动。本文将以 Tomcat 为例&#xff0c;来看看 SpringBoot 是如何启动 Tomcat 的。 二.源码分析 一.SpringApplication初始化 public class…

【STC8】热启动串口指令下载

前言 在目标开发板没有装载自动下载电路的时候&#xff0c;往往需要冷启动&#xff0c;也就是需要手动开关电源&#xff0c;来达到单片机复位下载。当然还有一种方法是热启动&#xff0c;通过串口接收到自定义的指令后&#xff0c;软件执行复位下载。这就是本文介绍的内容。 材…

理解神经网络的数学原理(四)多层感知机(MLP)与二叉空间分割树(BSP Tree)

概述 最近发现了一个传统算法&#xff0c;非常适合描述多层感知机&#xff08;Multi-Layer Perceptron&#xff0c;MLP&#xff09;的模型逻辑&#xff0c;其算法逻辑也非常清晰简单&#xff0c;所以在这里再对比一下&#xff0c;方便大家更容易理解多层感知机的内容&#xff…

手写Docker之认识NameSpace、CGroups、Union file system

关于NameSpace Linux NameSpace主要是kernel中用于隔离系统资源的功能&#xff0c;而docker就是基于NameSpace去隔离系统资源达到容器化的效果 以下案例均以该代码进行举例&#xff1a; package mainimport ("fmt""os""os/exec""syscall&…

【C++】mapsetmultimapmultiset使用说明

文章目录 关联式容器键值对pair的定义(键值对) 树形结构的关联式容器Set -> 排序去重Set的文档介绍Set的使用:set的构造set的迭代器set的容量set修改操作API接口总结: multiset -> 排序 可重复lower_bound&&upper_bound mapmap的模板参数说明map的构造map的迭代…

毕业季,各互联网大厂急缺这类 Python 人才!

又快到了应届毕业生找工作的季节了&#xff0c;一大波大厂高薪岗位陆续开放&#xff0c;想拿 Offer、升职加薪的你准备得怎么样了&#xff1f; 今年的招聘力度可以说是近几年最大&#xff0c;比如字节跳动旗下的大力教育&#xff0c;高调宣布&#xff1a;“未来 4 个月&#x…

最新整理Java面试八股文,大厂必备神器

在看这篇文章之前&#xff0c;我想我们需要先搞明白八股文是什么&#xff1f;&#xff1f;&#xff1f; 明清科举考试的一种文体&#xff0c;也称制义、制艺、时文、八比文。八股文章就四书五经取题&#xff0c;内容必须用古人的语气&#xff0c;绝对不允许自由发挥&#xff0…

记录--axios和loading不得不说的故事

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 loading的展示和取消可以说是每个前端对接口的时候都要关心的一个问题。这篇文章将要帮你解决的就是如何结合axios更加简洁的处理loading展示与取消的逻辑。 首先在我们平时处理业务的时候loading一般…

OpenAI 重磅发布 ChatGPT iOS 客户端!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 今天凌晨&#xff0c;OpenAI 正式发布了 iOS 客户端&#xff01; 这代表你可以直接在 iPhone 和 iPad 上直接使用 ChatGPT 进行聊天了。 该客户端基于 Whisper 开源模型&#xff0c;集成了…

用排列组合来编码通信(七)——《我的5/4张牌的预言》

早点关注我&#xff0c;精彩不错过&#xff01; 从《5张牌的预言》开始&#xff0c;前面介绍了3个拓展思路&#xff0c;分别从引入额外信息解放选牌&#xff08;Eigens value&#xff09;&#xff0c;引入正反信息来编码&#xff08;ups and downs&#xff09;&#xff0c;继续…