创建网络应用程序
一个项目很少只由后端组成。 使用 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。别名 webapp 和 web 存在是为了提高生产力,但文档和示例应该更好 lino web-app new 以保持一致性。
生成了什么
Lino 生成的 Blazor Web App 不只是零散的页面文件夹。它会加入同一个 .NET 解决方案,并遵循后端使用的模块化组织,在 host、client、共享组件以及按服务或模块划分的 UI 项目之间分离职责。
- 服务器项目:托管 Blazor Web 应用程序,映射根组件,配置服务默认值、静态资产、防伪、HTTPS、MudBlazor 服务和交互式渲染模式。
- 客户项目:集中在 WebAssembly 端运行的组件、路由、布局、菜单结构、浏览器设置、本地化功能以及与 MudBlazor 的集成。
- 共享 WebApps 项目:集中常见的 UI 资源、通知、对话框、查询字符串模板、客户端结果、文化/时区服务和可重用组件。
- 按服务和模块进行 UI 设计:当解决方案具有服务和模块时,Lino 在 Web 应用程序框架内创建前端项目,以维护上下文隔离的页面、菜单和资源。
生成的主机寄存器 AddInteractiveServerComponents 和 AddInteractiveWebAssemblyComponents。
根组件 HeadOutlet 和 Routes 使用 InteractiveAuto,允许应用程序通过服务器开始交互,并在客户端运行时可用时迁移到 WebAssembly。
与后端 API 集成
当 Web 应用程序存在时,Lino 使后端为前端的类型化消费做好准备。
服务和模块可以接收项目 Api.Contracts 和 Api.Client,向生成的端点公开请求/响应契约和类型化客户端。
- UI 不需要为每个功能手动组装原始 HTTP 调用。
- 生成的页面调用类型化的 API 客户端,并使用与后端一起创建的请求和响应模型。
-
模型共享为
ClientResult,QueryParams和PagedQueryParams标准化结果处理、过滤器、分页和视觉反馈。 -
通过类型化
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 了解已经为实体生成的内容。
推荐流量
-
创建或选择 Web 应用程序
lino web-app new。 - 对实体进行建模并生成用例、查询、命令、端点、API 合约和持久性工件。
-
跑步
lino page new并选择将接收接口的实体。 - 仔细选择网格中的字段。它们成为可见列,有助于设置查询参数、过滤器和分页。
- 通过 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 生成的起点必须被视为连贯且集成的基础。 在此基础上,团队调整视觉密度、字段顺序、显示规则、权限和文本以反映实际的产品流程。
