创建网络应用程序

一个项目很少只由后端组成。 使用 Lino,还可以创建 Web 应用程序来使用生成的 API,为最终用户或内部团队提供接口。


目前框架原生支持Blazor Web App(渲染模式 interactive auto)。 然而,该架构的设计允许在同一解决方案中添加多个前端,为不同的场景和受众提供服务。

具有 Blazor Web 应用程序的前端架构

Lino 生成的 Web 应用程序通过真实的接口将用户连接到后端用例,而不仅仅是通过调用 API 工具。 当前的本机前端类型是 Blazor 网页应用程序,为管理应用程序、公共门户、后台、合作伙伴区域和特定领域的界面做好准备。

lino web-app new --name <WebAppName>

该命令必须在 Lino 项目内运行。它请求 Web 应用程序的名称,使用 Blazor Web 应用程序模板,确认所选数据,创建必要的文件并执行将前端连接到解决方案的命令。 规范形式是 web-app。别名 webappweb 存在是为了提高生产力,但文档和示例应该更好 lino web-app new 以保持一致性。

生成了什么

Lino 生成的 Blazor Web App 不只是零散的页面文件夹。它会加入同一个 .NET 解决方案,并遵循后端使用的模块化组织,在 host、client、共享组件以及按服务或模块划分的 UI 项目之间分离职责。

  • 服务器项目:托管 Blazor Web 应用程序,映射根组件,配置服务默认值、静态资产、防伪、HTTPS、MudBlazor 服务和交互式渲染模式。
  • 客户项目:集中在 WebAssembly 端运行的组件、路由、布局、菜单结构、浏览器设置、本地化功能以及与 MudBlazor 的集成。
  • 共享 WebApps 项目:集中常见的 UI 资源、通知、对话框、查询字符串模板、客户端结果、文化/时区服务和可重用组件。
  • 按服务和模块进行 UI 设计:当解决方案具有服务和模块时,Lino 在 Web 应用程序框架内创建前端项目,以维护上下文隔离的页面、菜单和资源。

生成的主机寄存器 AddInteractiveServerComponentsAddInteractiveWebAssemblyComponents。 根组件 HeadOutletRoutes 使用 InteractiveAuto,允许应用程序通过服务器开始交互,并在客户端运行时可用时迁移到 WebAssembly。

与后端 API 集成

当 Web 应用程序存在时,Lino 使后端为前端的类型化消费做好准备。 服务和模块可以接收项目 Api.ContractsApi.Client,向生成的端点公开请求/响应契约和类型化客户端。

  • UI 不需要为每个功能手动组装原始 HTTP 调用。
  • 生成的页面调用类型化的 API 客户端,并使用与后端一起创建的请求和响应模型。
  • 模型共享为 ClientResult, QueryParamsPagedQueryParams 标准化结果处理、过滤器、分页和视觉反馈。
  • 通过类型化 HttpClient 集成,可以让 frontend 与解决方案其他部分使用的契约、权限、验证消息和区域文化保持一致。

实际流程是:

Blazor 页面 -> 类型化 API 客户端 -> Minimal API endpoint -> Command/Query -> 数据库

此路径保留了全栈一致性:域模型、用例、端点、契约、本地化接口、导航和权限遵循相同的项目约定。

包含的用户界面功能

生成的Web App已经为实际应用程序的常见问题做好了准备:

  • 组件布线 Routes.razor 生成的。
  • 基于 MudBlazor 的布局、导航和可视化组件。
  • 从每个服务或模块中可用的页面生成菜单。
  • 使用 .resx 文件对项目中配置的各个区域文化进行文本本地化。
  • 启用认证功能后,支持认证、令牌存储、保护路由和权限服务。
  • 授权敏感菜单,仅当当前用户具有所需权限时才显示条目。

多个前端

单个后端可以支持多个 Web 应用程序。当不同的受众需要不同的导航、安全性、体验和部署,但必须继续共享相同的服务、模块、用例和 API 时,这非常有用。

  • 公共网站:尚未经过身份验证的客户、访客或用户可以访问的页面。
  • 后台/管理员:操作员、支持和管理团队的内部管理小组。
  • 合作伙伴门户:合作伙伴、经销商、供应商或运营集成的访问受到限制。
  • 自助服务区:专注于最终客户的体验,拥有自己的菜单和权限。

每个前端都可以发展自己的布局、资源、菜单和访问规则,而后端仍然按服务、模块、用例和合同进行组织。

生成网页

在对实体进行建模、定义用例并生成命令、查询、端点和持久性之后,下一步通常是在界面中公开功能。 Lino 使用页面生成器自动执行此步骤:

lino page new --service <ServiceName> --module <ModuleName> --entity <EntityName> --webapp <WebAppName>
lino page edit --service <ServiceName> --module <ModuleName> --entity <EntityName> --webapp <WebAppName>
lino page list --service <ServiceName> --module <ModuleName> --entity <EntityName> --webapp <WebAppName>

选项也可以交互地告知。该命令要求提供应出现在网格中的服务、模块、实体、目标 Web 应用程序、页面类型和属性。 最常见的类型是 CRUD;当实体只支持查询时,Lino可以生成类似的页面 DataGrid

使用 page new 创建屏幕的第一个版本, page edit 当页面需要跟踪字段、契约或行为的更改时,以及 page list 了解已经为实体生成的内容。

推荐流量

  1. 创建或选择 Web 应用程序 lino web-app new
  2. 对实体进行建模并生成用例、查询、命令、端点、API 合约和持久性工件。
  3. 跑步 lino page new 并选择将接收接口的实体。
  4. 仔细选择网格中的字段。它们成为可见列,有助于设置查询参数、过滤器和分页。
  5. 通过 AppHost 运行解决方案以验证 UI、API、身份验证、权限和数据库集成。

生成的结构

对于 CRUD 页面,Lino 创建完整的 Blazor 页面包,而不是单个 Razor 文件:

  • 记录页面或索引协调列表、创建、编辑、详细信息和删除。
  • 基于 MudBlazor 的网格组件,具有服务器端加载、分页、过滤器和查询参数映射。
  • 具有类型化 ViewModel 的表单组件以及用于映射创建、更新和按 ID 获取请求的扩展。
  • 标题、标签、按钮、验证消息和本地化界面文本的资源。
  • 启用身份验证时进行权限检查,包括页面访问验证和条件按钮。

为实体创建 CRUD 页面 Vehicle,例如,在服务中 Fleet, 模块 Operations 和网络应用程序 Backoffice,结构遵循以下格式:

src/WebApps/Backoffice/Services/Fleet/Operations/Pages/Vehicles/Registration/
├── Vehicle.razor
├── Vehicle.razor.cs
├── Resources/
│   ├── VehicleResources.resx
│   └── VehicleResources.Designer.cs
└── Components/
    ├── Form/
    │   ├── VehicleForm.razor
    │   ├── VehicleForm.razor.cs
    │   ├── VehicleFormExtensions.cs
    │   ├── VehicleViewModel.cs
    │   └── Resources/
    │       ├── VehicleFormResources.resx
    │       └── VehicleFormResources.Designer.cs
    └── Grid/
        ├── VehicleGrid.razor
        ├── VehicleGrid.razor.cs
        ├── VehicleGridExtensions.cs
        ├── VehiclePagedQueryParams.cs
        └── Resources/
            ├── VehicleGridResources.resx
            └── VehicleGridResources.Designer.cs

这个想法保留了示例中使用的先前结构,例如 Order:主页、代码隐藏、表单组件、网格组件、扩展和分页参数。 当前版本通过 Web 应用程序、服务和模块添加了功能以及与组织的显式集成。

生成的页面如何工作

该页面使用为 API 生成的相同合约。网格将过滤器和分页转换为列表请求;表单将 ViewModel 转换为创建或更新请求;类型化的 API 客户端将调用发送到相应的端点。 端点执行生成的命令或查询并向 UI 返回键入的响应。

Frontend -> API -> Commands/Queries -> 数据库

当授权存在时,生成的代码还会根据标识符检查列出、创建、编辑、删除、查询等权限。 这会影响对页面的访问以及用户操作的可见性。

结果是一致的全栈流程:域模型、用例、端点、类型化客户端、本地化 UI、导航和权限遵循相同的设计约定。 生成器减少了重复,但组件仍可编辑以进行产品调整、可用性和特定规则。

多语言界面

Lino使用文件生成的Web应用程序 .resx 对于本地化文本。 这使您可以保持相同的 Razor 结构,并根据活动区域性改变标题、标签、按钮、错误消息、验证文本和描述。

本地化不应被视为视觉收尾工作。在管理页面和操作门户上,不一致的术语会引起对业务规则的怀疑。 因此,资源是 UI 架构的一部分,必须伴随页面、表单、网格和共享组件。

  • 保持按键稳定、具有描述性且以意义为导向,避免名称与临时屏幕布局绑定。
  • 避免在页面和组件上硬编码文本;使用标签、消息、标题、面包屑、菜单和确认的资源。
  • 检查技术术语以保持文档、CLI、API 合约和接口之间的一致性。
  • 跨文化保留同一组按键,以防止意外回退或部分翻译的屏幕。
  • 将直译与产品适应分开:当需要为最终用户本地化术语时,保持操作的功能含义。

在生成的页面上,通常存在页面、表单和网格级别的资源。 这种分离允许每个部分不断发展,而无需混合列表、编辑、验证和导航文本。

响应式、开箱即用的 CRUD

生成的 CRUD 加快了交付速度,因为它创建了屏幕的重复基础:列表、表单、与 API 的集成、资源、分页、过滤器、操作和隐藏代码。 尽管如此,它应该被视为一种产品体验,而不仅仅是一个技术支架。

良好的 CRUD 屏幕需要允许用户查找记录、了解当前状态、自信地采取行动并从故障中恢复。 这既适用于内部后台屏幕,也适用于针对客户或合作伙伴的门户。

  • 选择有助于决策的列表栏目;避免使用对操作员没有任何影响的技术领域的网格。
  • 根据预期的数据量和用户的主要搜索条件配置过滤器和分页。
  • 检查验证和错误消息,以领域语言(而不仅仅是实现术语)解释问题。
  • 确保空、加载和崩溃状态,以避免在没有数据、API 需要时间或操作未完成时出现静默屏幕。
  • 确认不可逆的删除和操作,明确哪些记录会受到影响。
  • 在保存、编辑、删除或使用本地化通知和消息失败后显示清晰的反馈。
  • 通过后端和前端的权限保护操作;隐藏按钮可以改善体验,但不能取代真正的授权。
  • 检查较小屏幕上的响应能力,尤其是操作菜单、过滤器、必填字段和具有许多列的网格。

Lino 生成的起点必须被视为连贯且集成的基础。 在此基础上,团队调整视觉密度、字段顺序、显示规则、权限和文本以反映实际的产品流程。

发生了未处理的错误。 重新加载 🗙