ASP.NET Core Blazor 1:创建准备项目

  本章将创建贯穿这一部分的示例项目。

1 创建项目

dotnet new globaljson --sdk-version 3.1.101 --output MyAdvanced
dotnet new web --no-https --output MyAdvanced --framework netcoreapp3.1
dotnet new sln -o MyAdvanced
dotnet sln MyAdvanced add MyAdvanced

  向项目中添加 NuGet 包

dotnet add package Microsoft.EntityFrameworkCore.Design --version 3.1.1
dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 3.1.1

  安装全局工具包

dotnet tool uninstall --global dotnet-ef
dotnet tool install --global dotnet-ef --version 3.1.1

2 添加数据模型

  这个应用程序的数据模型由三个类组成,分别代表人员、工作部门和位置。创建一个 Model 文件夹,并向其中添加一个名为 Person.cs 的类文件。

public class Person
{
    public long PersonId { get; set; }
    public string Firstname { get; set; }
    public string Surname { get; set; }
    public long DepartmentId { get; set; }
    public long LocationId { get; set; }
    
    public Department Department { get; set; }
    public Location Location { get; set; }
}

  将一个名为 Department.cs 的类文件添加到 Models 文件夹中。

public class Department
{
    public long Departmentid { get; set; }
    public string Name { get; set; }
    
    public IEnumerable<Person> People { get; set; }
}

  在 Models 文件夹中添加一个名为 Location.cs 的类文件。

public class Location
{
    public long LocationId { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    
    public IEnumerable<Person> People { get; set; }
}

  要创建提供对数据库的访问的 EF Core 的上下文类, Models 文件夹添加 DataContext.cs。

public class DataContext : DbContext
{
    public DataContext(DbContextOptions<DataContext> opts)
    : base(opts) { }
    public DbSet<Person> People { get; set; }
    public DbSet<Department> Departments { get; set; }
    public DbSet<Location> Locations { get; set; }
}

2.1 准备种子数据

  将一个名为 SeedData.cs 的类添加到 Models 文件夹中,以定义用于填充数据库的种子数据。

public static class SeedData
{
    public static void SeedDatabase(DataContext context)
    {
        context.Database.Migrate();
        if (context.People.Count() == 0 && context.Departments.Count() == 0 &&
            context.Locations.Count() == 0)
        {

            Department d1 = new Department { Name = "Sales" };
            Department d2 = new Department { Name = "Development" };
            Department d3 = new Department { Name = "Support" };
            Department d4 = new Department { Name = "Facilities" };

            context.Departments.AddRange(d1, d2, d3, d4);
            context.SaveChanges();

            Location l1 = new Location { City = "Oakland", State = "CA" };
            Location l2 = new Location { City = "San Jose", State = "CA" };
            Location l3 = new Location { City = "New York", State = "NY" };
            context.Locations.AddRange(l1, l2, l3);

            context.People.AddRange(
                new Person
                {
                    Firstname = "Francesca",
                    Surname = "Jacobs",
                    Department = d2,
                    Location = l1
                },
                new Person
                {
                    Firstname = "Charles",
                    Surname = "Fuentes",
                    Department = d2,
                    Location = l3
                },
                new Person
                {
                    Firstname = "Bright",
                    Surname = "Becker",
                    Department = d4,
                    Location = l1
                },
                new Person
                {
                    Firstname = "Murphy",
                    Surname = "Lara",
                    Department = d1,
                    Location = l3
                },
                new Person
                {
                    Firstname = "Beasley",
                    Surname = "Hoffman",
                    Department = d4,
                    Location = l3
                },
                new Person
                {
                    Firstname = "Marks",
                    Surname = "Hays",
                    Department = d4,
                    Location = l1
                },
                new Person
                {
                    Firstname = "Underwood",
                    Surname = "Trujillo",
                    Department = d2,
                    Location = l1
                },
                new Person
                {
                    Firstname = "Randall",
                    Surname = "Lloyd",
                    Department = d3,
                    Location = l2
                },
                new Person
                {
                    Firstname = "Guzman",
                    Surname = "Case",
                    Department = d2,
                    Location = l2
                });
            context.SaveChanges();
        }
    }
}

2.2 配置 Entity Framework Core 服务和中间件

  对 Startup 类进行更改,它配置 Entity Framewonk Core 并设置 DataContext 服务,将使用该服务访问数据库。

public class Startup
{
    public Startup(IConfiguration config)
    {
        Configuration = config;
    }
    public IConfiguration Configuration { get; set; }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<DataContext>(opts =>
        {
            opts.UseSqlServer(Configuration[
                "ConnectionStrings:PeopleConnection"]);
            opts.EnableSensitiveDataLogging(true);
        });
    }

    public void Configure(IApplicationBuilder app, DataContext context)
    {
        app.UseDeveloperExceptionPage();
        app.UseStaticFiles();
        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute("controllers",
                "controllers/{controller=Home}/{action=Index}/{id?}");
            endpoints.MapDefaultControllerRoute();
            endpoints.MapRazorPages();
        });

        SeedData.SeedDatabase(context);
    }
}

  要定义用于应用程序数据的连接字符串,在 appsetingsjson 文件中添加配置。

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "Microsoft.EntityFrameworkCore": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "ProductConnection": "Server=.;Database=People;MultipleActiveResultSets=true;User ID=sa;Pwd=Admin123;"
  }
}

2.3 创建和应用迁移

  创建 Entity Framework Core 迁移

dotnet ef migrations add Initial

  创建迁移后,将其应用到数据库。

dotnet ef database update

3 添加引导 CSS 框架

  用引导 CSS 框架为示例应用程序生成的 HTML 元素设置样式要安装引导包。

libman init -p cdnjs
libman install twitter-bootstrap@4.3.1 -d wwwroot/lib/twitter-bootstrap

  如果使用的是 Visual Studio,可以通过单击项目并从弹出菜单中选择客户端库来安装客户端包。

4 配置服务和中间件

  在这个项目中启用运行时 Razor 视图编译,安装提供运行时编译服务的包。

dotnet add package Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation --version 3.1.1

  同时会使用 MVC 控制器和 Razor Pages 响应请求。Startup 类中配置应用程序使用的服务和中间件。

services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddRazorPages().AddRazorRuntimeCompilation();
public void Configure(IApplicationBuilder app, DataContext context)
{
    app.UseDeveloperExceptionPage();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute("controllers",
            "controllers/{controller=Home}/{action=Index}/{id?}");
        endpoints.MapDefaultControllerRoute();
        endpoints.MapRazorPages();
    });
    SeedData.SeedDatabase(context);
}

  除了默认的控制器路由之外,还添加了一个匹配以控制器开始的 URL 路径的路由,这将使后续章节中的示例在控制器和 Razor Pages 之间切换时更容易理解。这与在前几章中采用的约定相同,把以 /pages 开头的 URL 路径路由到 Razor 页面。

5 创建控制器和视图

  添加 Controllers 文件夹,并添加 HomeController.cs。

public class HomeController : Controller
{
    private DataContext context;
    public HomeController(DataContext dbContext)
    {
        context = dbContext;
    }
    public IActionResult Index([FromQuery] string selectedCity)
    {
        return View(new PeopleListViewModel
        {
            People = context.People
                .Include(p => p.Department).Include(p => p.Location),
            Cities = context.Locations.Select(l => l.City).Distinct(),
            SelectedCity = selectedCity
        });
    }
}
public class PeopleListViewModel
{
    public IEnumerable<Person> People { get; set; }
    public IEnumerable<string> Cities { get; set; }
    public string SelectedCity { get; set; }
    public string GetClass(string city) =>
        SelectedCity == city ? "bg-info text-white" : "";
}

  为给控制器提供视图,创建 Views/Home 文件夹,并添加一个名为Index.cshtml 的 Razor 视图。

@model PeopleListViewModel

<h4 class="bg-primary text-white text-center p-2">People</h4>

<table class="table table-sm table-bordered table-striped">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Dept</th>
            <th>Location</th>
        </tr>
    </thead>
    <tbody>
        @foreach (Person p in Model.People)
        {
            <tr class="@Model.GetClass(p.Location.City)">
                <td>@p.PersonId</td>
                <td>@p.Surname, @p.Firstname</td>
                <td>@p.Department.Name</td>
                <td>@p.Location.City, @p.Location.State</td>
            </tr>
        }
    </tbody>
</table>

<form asp-action="Index" method="get">
    <div class="form-group">
        <label for="selectedCity">City</label>
        <select name="selectedCity" class="form-control">
            <option disabled selected>Select City</option>
            @foreach (string city in Model.Cities)
            {
                <option selected="@(city == Model.SelectedCity)">
                    @city
                </option>
            }
        </select>
    </div>
    <button class="btn btn-primary" type="submit">Select</button>
</form>

  要启用标签助手并添加视图中默认可用的名称空间,请给 Views 文件夹添加一个名为 _ViewImports.cshtml 的 Razor 视图导入文件。

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using MyAdvanced.Models
@using MyAdvanced.Controllers

  Views 文件夹添加 _ViewStart.cshtml。

@{
    Layout = "_Layout";
}

  要创建布局,请创建 Views/Shared 文件夹,并向其中添加一个名为 _Layout.cshtml。

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>    
    <div class="m-2">
        @RenderBody()
    </div>
</body>
</html>

6 创建 Razor Pages

  创建 Pages 文件夹,Index.cshtml 的 Razor Pages。

@page "/pages"
@model IndexModel

<h4 class="bg-primary text-white text-center p-2">People</h4>

<table class="table table-sm table-bordered table-striped">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Dept</th>
            <th>Location</th>
        </tr>
    </thead>
    <tbody>
        @foreach (Person p in Model.People)
        {
            <tr class="@Model.GetClass(p.Location.City)">
                <td>@p.PersonId</td>
                <td>@p.Surname, @p.Firstname</td>
                <td>@p.Department.Name</td>
                <td>@p.Location.City, @p.Location.State</td>
            </tr>
        }
    </tbody>
</table>

<form asp-page="Index" method="get">
    <div class="form-group">
        <label for="selectedCity">City</label>
        <select name="selectedCity" class="form-control">
            <option disabled selected>Select City</option>
            @foreach (string city in Model.Cities)
            {
                <option selected="@(city == Model.SelectedCity)">
                    @city
                </option>
            }
        </select>
    </div>
    <button class="btn btn-primary" type="submit">Select</button>
</form>

@functions
{
    public class IndexModel : PageModel
    {
        private DataContext context;

        public IndexModel(DataContext dbContext)
        {
            context = dbContext;
        }
        public IEnumerable<Person> People { get; set; }
        public IEnumerable<string> Cities { get; set; }

        [FromQuery]
        public string SelectedCity { get; set; }

        public void OnGet()
        {
            People = context.People.Include(p => p.Department)
                .Include(p => p.Location);
            Cities = context.Locations.Select(l => l.City).Distinct();
        }

        public string GetClass(string city) =>
            SelectedCity == city ? "bg-info text-white" : "";
    }
}

  要启用标签助手并在 Razor Pages 的 View 部分添加默认可用的名称空间,给 Pages 文件夹添 _Viewlmports.cshtml。

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using MyAdvanced.Models
@using Microsoft.AspNetCore.Mvc.RazorPages
@using Microsoft.EntityFrameworkCore

  要指定 Razor Pages 的默认布局,给 Pages 文件夹添加 _ViewStart.cshiml。

@{
    Layout = "_Layout";
}

  要创建布局,给 Pagcs 文件夹添加 _Layout.cshtml的 Razor 布局。

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>    
    <div class="m-2">
        <h5 class="bg-secondary text-white text-center p-2">Razor Page</h5>
        @RenderBody()
    </div>
</body>
</html>

7 运行

  使用浏览器请求 http:/localhost:5000/controllershttp:/localhost:5000/pages

posted @ 2024-06-22 17:45  一纸年华  阅读(16)  评论(0编辑  收藏  举报