Abp vnext Web应用程序开发教程 2 —— 图书列表页面

关于本教程

本教程基于版本3.1

在本教程系列中,您将构建一个名为Acme.BookStore的基于ABPWeb应用程序。该应用程序用于管理书籍及其作者的列表。它是使用以下技术开发的:

  • 实体框架核心作为ORM提供者。
  • MVC/Razor页面作为UI框架。

本教程分为以下部分:

第1部分:创建服务器端

第2部分:图书列表页面(此部分)

第3部分:创建、更新和删除书籍

第4部分:集成测试

第5部分:授权

第6部分:作者:领领域层

第7部分:作者:数据库集成

第8部分:作者:应用程序层

第9部分:作者:用户界面

第10部分:书与作者的关系

下载源代码

MVC (Razor Pages) UI with EF Core

动态JavaScript代理

JavaScript端通过AJAX调用HTTP API端点是很常见的。您可以使用$.ajax或其他工具来调用端点。但是,ABP提供了更好的方法。

ABP 为所有API端点动态创建JavaScript代理。因此,您可以使用任何端点,就像调用JavaScript函数一样。

在开发者控制台中进行测试

您可以使用自己喜欢的浏览器的开发者控制台轻松测试JavaScript代理。运行该应用程序,打开浏览器的开发人员工具(快捷方式通常为F12),切换到“控制台”选项卡,键入以下代码,然后按Enter

acme.bookStore.books.book.getList({}).done(function (result) { console.log(result); });
  • acme.bookStore.booksBookAppService转换为camelCase的名称空间。

  • bookBookAppService(已删除AppService的后缀并转换为camelCase)的常规名称。

  • getList是在CrudAppService基类中GetListAsync定义的方法的常规名称(删除Async后缀并转换为camelCase)。

  • {}参数用于将空对象发送给GetListAsync方法,其通常需要类型PagedAndSortedResultRequestDto的对象,该对象用于将分页和排序选项发送至服务器(所有属性都是可选的,具有默认值,因此您可以发送空对象)。

  • getList函数返回promise。您可以将回调传递给then(或done)函数,以获取服务器返回的结果。

运行此代码将产生以下输出:

在这里插入图片描述

您可以看到从服务器返回的图书列表。您还可以检查开发人员工具的“网络”标签以查看客户端与服务器之间的通信:
在这里插入图片描述

让我们使用create函数创建一本新书

acme.bookStore.books.book.create({ 
        name: 'Foundation', 
        type: 7, 
        publishDate: '1951-05-24', 
        price: 21.5 
    }).then(function (result) { 
        console.log('successfully created the book with id: ' + result.id); 
    });

您应该在控制台中看到类似以下的消息:

successfully created the book with id: 439b0ea8-923e-8e1e-5d97-39f2c7ac4246

检查数据库中的Books表以查看一行新书记录。你可以自己试试getupdatedelete功能。

在下一部分中,我们将使用这些动态代理功能与服务器进行通信。

本地化

在开始UI开发之前,我们首先要准备本地化文本(通常在开发应用程序时需要时执行)。

本地化文本位于Acme.BookStore.Domain.Shared项目的Localization/BookStore文件夹下:
在这里插入图片描述

打开en.json(英文翻译)文件,然后更改内容,如下所示:

{
  "Culture": "en",
  "Texts": {
    "Menu:Home": "Home",
    "Welcome": "Welcome",
    "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.",
    "Menu:BookStore": "Book Store",
    "Menu:Books": "Books",
    "Actions": "Actions",
    "Close": "Close",
    "Delete": "Delete",
    "Edit": "Edit",
    "PublishDate": "Publish date",
    "NewBook": "New book",
    "Name": "Name",
    "Type": "Type",
    "Price": "Price",
    "CreationTime": "Creation time",
    "AreYouSure": "Are you sure?",
    "AreYouSureToDelete": "Are you sure you want to delete this item?",
    "Enum:BookType:0": "Undefined",
    "Enum:BookType:1": "Adventure",
    "Enum:BookType:2": "Biography",
    "Enum:BookType:3": "Dystopia",
    "Enum:BookType:4": "Fantastic",
    "Enum:BookType:5": "Horror",
    "Enum:BookType:6": "Science",
    "Enum:BookType:7": "Science fiction",
    "Enum:BookType:8": "Poetry"
  }
}
  • 本地化关键字名称是任意的。您可以设置任何名称。对于特定的文本类型,我们更喜欢一些约定;

    • 为菜单项添加Menu:前缀。
    • 使用Enum:<enum-type>:<enum-value>命名约定对枚举成员进行本地化。当您这样做时,ABP可以在某些适当的情况下自动将枚举本地化。

如果未在本地化文件中定义文本,则文本将回退到本地化键(作为ASP.NET Core的标准行为)。

ABP的本地化系统基于ASP.NET Core的标准本地化系统,并以多种方式进行了扩展。有关详细信息,请参见本地化文档

创建书籍页面

是时候创建可见的和可用的东西了!代替经典的MVC,我们将使用Microsoft建议的Razor Pages UI方法。

Acme.BookStore.Web项目Books文件夹下创建Pages文件夹。右键单击“Books”文件夹,然后选择“添加”>“Razor页面”菜单项,以添加新的Razor页面。命名为Index
在这里插入图片描述

打开Index.cshtml并更改整个内容,如下所示:

@page
@using Acme.BookStore.Web.Pages.Books
@model IndexModel

<h2>Books</h2>

Index.cshtml.cs 内容应该是这样的:

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace Acme.BookStore.Web.Pages.Books
{
    public class IndexModel : PageModel
    {
        public void OnGet()
        {
            
        }
    }
}

将书籍页面添加到主菜单

打开Menus文件夹中的BookStoreMenuContributor类,并将以下代码添加到ConfigureMainMenuAsync方法的末尾:

context.Menu.AddItem(
    new ApplicationMenuItem(
        "BooksStore",
        l["Menu:BookStore"],
        icon: "fa fa-book"
    ).AddItem(
        new ApplicationMenuItem(
            "BooksStore.Books",
            l["Menu:Books"],
            url: "/Books"
        )
    )
);

运行项目,使用用户名admin和密码1q2w3E*登录到应用程序,然后查看新菜单项已添加到主菜单中:
在这里插入图片描述

当您单击到Book Store父项下的Books菜单项时,您将被重定向到新的空白Books Page

图书列表

我们将使用Datatables.net jQuery库显示图书列表。数据表库通过AJAX完全起作用,它快速、流行并且提供了良好的用户体验。

Datatables库是在启动模板中配置的,因此您可以在任何页面中直接使用它,而无需在页面中包含任何样式或脚本文件。

Index.cshtml

更改Pages/Books/Index.cshtml如下:

@page
@using Acme.BookStore.Localization
@using Acme.BookStore.Web.Pages.Books
@using Microsoft.Extensions.Localization
@model IndexModel
@inject IStringLocalizer<BookStoreResource> L
@section scripts
{
    <abp-script src="/Pages/Books/Index.js" />
}
<abp-card>
    <abp-card-header>
        <h2>@L["Books"]</h2>
    </abp-card-header>
    <abp-card-body>
        <abp-table striped-rows="true" id="BooksTable"></abp-table>
    </abp-card-body>
</abp-card>
  • abp-script 标记帮助程序用于将外部脚本添加到页面。与标准script标记相比,它具有许多其他功能。它处理缩小版本控制。有关详细信息,请参见捆绑和缩小文档

  • abp-cardTwitter Bootstrap卡组件的标签帮助器。ABP框架还提供了其他有用的标签帮助程序,可以轻松使用大多数 bootstrap组件。您可以使用常规HTML标记代替这些标记帮助器,但是使用标记帮助器可以减少HTML代码并通过智能感知和编译时类型检查来防止错误。更多信息,请参见标签帮助器文档

Index.js

在文件Pages/Books夹下创建一个Index.js文件:
在这里插入图片描述

该文件的内容如下所示:

$(function () {
    var l = abp.localization.getResource('BookStore');

    var dataTable = $('#BooksTable').DataTable(
        abp.libs.datatables.normalizeConfiguration({
            serverSide: true,
            paging: true,
            order: [[1, "asc"]],
            searching: false,
            scrollX: true,
            ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList),
            columnDefs: [
                {
                    title: l('Name'),
                    data: "name"
                },
                {
                    title: l('Type'),
                    data: "type",
                    render: function (data) {
                        return l('Enum:BookType:' + data);
                    }
                },
                {
                    title: l('PublishDate'),
                    data: "publishDate",
                    render: function (data) {
                        return luxon
                            .DateTime
                            .fromISO(data, {
                                locale: abp.localization.currentCulture.name
                            }).toLocaleString();
                    }
                },
                {
                    title: l('Price'),
                    data: "price"
                },
                {
                    title: l('CreationTime'), data: "creationTime",
                    render: function (data) {
                        return luxon
                            .DateTime
                            .fromISO(data, {
                                locale: abp.localization.currentCulture.name
                            }).toLocaleString(luxon.DateTime.DATETIME_SHORT);
                    }
                }
            ]
        })
    );
});
  • abp.localization.getResource获取一个函数,该函数用于使用服务器端定义的相同JSON文件对文本进行本地化。这样,您可以与客户端共享本地化值。

  • abp.libs.datatables.normalizeConfiguration是ABP框架定义的辅助功能。不需要使用它,但是它通过为丢失的选项提供常规默认值来简化Datatables配置。

  • abp.libs.datatables.createAjax是另一个帮助程序功能,用于使ABP的动态JavaScript API代理适应Datatable的预期参数格式。

  • acme.bookStore.books.book.getList 是之前介绍的动态JavaScript代理功能。

  • luxon库也是解决方案中预先配置的标准库,因此您可以轻松地执行日期/时间操作。

有关所有配置选项,请参见数据表文档

运行最终应用程序

您可以运行该应用程序!这部分的最终用户界面如下所示:
在这里插入图片描述

这是一个完全正常工作的服务器端分页,已排序和本地化的书籍表。

下一部分

请参阅本教程的下一部分

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值