界面组件DevExpress中文教程 - 如何在Node.js应用中创建报表?

DevExpress Reporting是.NET Framework下功能完善的报表平台,它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集,包括数据透视表、图表,因此您可以构建无与伦比、信息清晰的报表。

获取DevExpress Reporting最新正式版下载(Q技术交流:532598169)

为什么选择Node.js和WebAssembly?

自定义DevExpress报表(在后端应用程序中)可能会给刚接触 .NET的前端Web开发人员带来独特的挑战,在本文中我们将向您展示.NET和WebAssembly集成是如何帮助解决这些挑战,并增强整体应用程序的安全性和性能的。

传统的报表开发/定制方法需要 .NET和相关语言的专业知识,但WebAssembly消除了这个困难。通过在WASM环境中运行.NET应用程序,开发人员无需深入了解.NET就可以将交互式报表集成到Node.js应用程序中。

这种集成的第二个好处与安全性有关,WebAssembly在隔离的环境中执行代码。因此开发人员可以完全控制磁盘、网络和其他关键资源,这种隔离的执行环境可以降低与未授权访问相关的风险。

Microsoft在最近的.NET更新中一直致力于 .NET 和WebAssembly的集成,在.NET 7中,Micrsooft引入了CLI模板(如wasmconsole和wasmbrowser),并允许开发人员创建在承载.NET运行时的沙盒WebAssembly环境中运行的控制台和web应用程序。

随着.NET 8的发布,应用程序代码在编译时直接转换为WebAssembly,这一变化带来了与性能相关的显著改进,其特点是延迟减少、用户界面响应更快。

如果您是一个刚接触.NET的前端Web开发人员,并且对这篇内容感兴趣,建议创建一个应用程序,允许创建DevExpress报表并将其导出为PDF文件。

开始前
  • 安装 .NET 8 SDK。
  • 安装最新的CLI模板:

>dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates::8.0.3

  • 安装wasm-tools工作负载:

>dotnet workload install wasm-tools

创建一个简单的Wasmconsole应用

运行以下命令创建一个示例wasm-export应用:

>dotnet new wasmconsole -o wasm-exporter

当示例项目准备好后,导航到项目文件夹:

>cd wasm-exporter

Program.cs文件包含以下代码:

using System;
using System.Runtime.InteropServices.JavaScript;Console.WriteLine("Hello, Console!");return 0;public partial class MyClass
{
[JSExport]
internal static string Greeting()
{
var text = $"Hello, World! Greetings from node version: {GetNodeVersion()}";
return text;
}[JSImport("node.process.version", "main.mjs")]
internal static partial string GetNodeVersion();
}

如您所见,JavaScript导入Greeting .NET函数,而.NET本身导入一个函数,该函数显示当前安装的Node.js版本。

反过来,代码在main.mjs文件加载.NET运行时并将JavaScript函数导入WebAssembly:

import { dotnet } from './_framework/dotnet.js'const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
.withDiagnosticTracing(false)
.create();setModuleImports('main.mjs', {
node: {
process: {
version: () => globalThis.process.version
}
}
});const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
console.log(text);await dotnet.run();

一旦您使用了dotnet build命令构建了这个应用程序,运行它的方式与您通常运行node.js应用程序的方式相同,来查看两个函数的执行结果:

>dotnet build
>node main.mjs
Hello, World! Greetings from node version: v18.12.1
Hello, Console!

通过指定配置设置创建DevExpress报表

对于未安装DevExpress的macOS/Linux或Windows操作系统,请执行以下操作:

  • 创建一个nuget.config文件:

dotnet new nugetconfig

  • 删除nuget.config文件中的“clear /”
  • 更新add key="nuget" value="https://api.nuget.org/v3/index.json" ,并将nuget键替换为自定义提要名称,并将该值替换为从DevExpress NuGet Gallery页面获得的DevExpress NuGet Feed URL。

完成后,安装在WebAssembly应用程序中创建文档所需的NuGet包:

dotnet add package Newtonsoft.Json
dotnet add package DevExpress.Drawing.Skia --version 23.2.*-*
dotnet add package DevExpress.Reporting.Core --version 23.2.*-*
dotnet add package SkiaSharp.HarfBuzz --version 2.88.7
dotnet add package SkiaSharp.NativeAssets.WebAssembly --version 2.88.7
dotnet add package HarfBuzzSharp.NativeAssets.WebAssembly --version 2.8.2.4
dotnet add package SkiaSharp.Views.Blazor --version 2.88.7

在项目配置文件(wasm- exporters .csproj)中添加一个本地SkiaSharp依赖项:

<ItemGroup>
<NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\2.0.23\*.a" />
</ItemGroup>

指定生成的可执行文件和库的路径:

<wasmappdir>./result</wasmappdir>

在这一点上,我们完成了准备工作,并准备开始编码。

我们的应用程序由两个部分组成:一个基于.NET服务器的应用程序编译成程序集,一个JavaScript客户端应用程序创建并配置.NET运行时环境,以便在WASM中运行该程序集。

.NET解决方案

在您喜欢的代码编辑器中打开文件夹,在Program.cs代码单元中实现以下类:ReportExporter、JsonSourceCustomizationService和SimplifiedUriJsonSource:

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices.JavaScript;
using System.Threading;
using System.Threading.Tasks;
using DevExpress.Data;
using DevExpress.DataAccess.Json;
using DevExpress.XtraPrinting;
using DevExpress.XtraReports.UI;return 0;public partial class ReportExporter {
[JSExport]
internal static async Task ExportToPdfAsync(JSObject exportModel, JSObject result) {
using var report = new XtraReport();
((IServiceContainer)report).AddService(typeof(IJsonSourceCustomizationService), new JsonSourceCustomizationService());using var reportStream = new MemoryStream(exportModel.GetPropertyAsByteArray("reportXml"));
report.LoadLayoutFromXml(reportStream, true);PdfExportOptions pdfOptions = report.ExportOptions.Pdf;
if(exportModel.HasProperty("exportOptions")) {
SimplifiedFillExportOptions(pdfOptions, exportModel.GetPropertyAsJSObject("exportOptions"));
}using var resultStream = new MemoryStream();
await report.ExportToPdfAsync(resultStream, pdfOptions);
result.SetProperty("pdf", resultStream.ToArray());
resultStream.Close();
}static void SimplifiedFillExportOptions(object exportOptions, JSObject jsExportOptions) {
PropertyInfo[] propInfos = exportOptions.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach(PropertyInfo pi in propInfos) {
if(!jsExportOptions.HasProperty(pi.Name))
continue;if(pi.PropertyType == typeof(bool)) {
pi.SetValue(exportOptions, jsExportOptions.GetPropertyAsBoolean(pi.Name));} else if(pi.PropertyType == typeof(string)) {
pi.SetValue(exportOptions, jsExportOptions.GetPropertyAsString(pi.Name));} else if(pi.PropertyType.IsEnum) {
string val = jsExportOptions.GetPropertyAsString(pi.Name);
if(Enum.IsDefined(pi.PropertyType, val)) {
pi.SetValue(exportOptions, Enum.Parse(pi.PropertyType, val));
}} else if(pi.PropertyType.IsClass) {
SimplifiedFillExportOptions(pi.GetValue(exportOptions), jsExportOptions.GetPropertyAsJSObject(pi.Name));
}
}
}
}
public class JsonSourceCustomizationService : IJsonSourceCustomizationService {
public JsonSourceBase CustomizeJsonSource(JsonDataSource jsonDataSource) {
return jsonDataSource.JsonSource is UriJsonSource uriJsonSource ? new SimplifiedUriJsonSource(uriJsonSource.Uri) : jsonDataSource.JsonSource;
}
}
public partial class SimplifiedUriJsonSource : UriJsonSource {
public SimplifiedUriJsonSource(Uri uri) : base(uri) { }
public override Task GetJsonStringAsync(IEnumerable sourceParameters, CancellationToken cancellationToken) {
return GetJsonData(Uri.ToString());
}
[JSImport("getJsonData", "main.mjs")]
internal static partial Task GetJsonData(string url);
}

ReportExporter

该类实现ExportToPdfAsync方法并将其导出到JavaScript模块,该方法创建一个XtraReport实例,将JsonSourceCustomizationService自定义服务添加到报表对象模型,并将可选的导出选项从javascript对象映射到本地.NET对象,使用XtraReport.ExportToPdfAsync方法将报表导出为PDF。

JsonSourceCustomizationService

这个服务取代了JsonDataSource.JsonSource值,使用满足Blazor限制的自定义对象。这是因为WebAssembly不允许HTTP请求,而报表模型可能会引用带有URI的JSON源。

SimplifiedUriJsonSource

该类是UriJsonSource类的后代,并将HTTP请求重定向到应用程序的javascript段。

JavaScript实现

main.mjs文件是应用程序的核心JS段,将其内容替换为以下代码:

// Import necessary modules.
import { dotnet } from '._framework/dotnet.js';
import fs from 'fs';
import { get as httpGet } from 'http';
import { get as httpsGet } from 'https';
import url from 'url'// Configure .NET runtime for WASM execution.
const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
.withDiagnosticTracing(false)
.create();
setModuleImports('main.mjs', { getJsonData });// Retrieve the exported methods from the WASM part.
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);// Prepare the report model and related options.
const repx = fs.readFileSync('../reports/report1.repx');
const model = {
reportXml: repx,
exportOptions: {
DocumentOptions: {
Application: "WASM",
Subject: "wasm integration"
},
PdfUACompatibility: "PdfUA1"
}
}// Export the report to PDF.
const result = {};
await exports.ReportExporter.ExportToPdfAsync(model, result);
const buffer = Buffer.from(result.pdf);
fs.writeFileSync('result.pdf', buffer);// Define a method to fetch JSON data from a given URL.
function getJsonData(jsonUrl) {
return new Promise((resolve) => {
const fetchMethod = url.parse(jsonUrl).protocol === 'https:' ? httpsGet : httpGet;
fetchMethod(jsonUrl, res => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(data));
}).on('error', err => resolve(''));
});
}// Initiate the .NET runtime.
await dotnet.run();

该文件中的代码:

  • 在WASM中配置 .NET 运行时。
  • 导入getJsonData()函数来从URL检索JSON文件。
  • 调用并执行ExportToPdfAsync方法来生成PDF文档。
  • 使用本地Node.js函数保存生成的PDF文件。
查看结果

要运行应用程序,首先构建.NET应用程序,导航到result文件夹,然后运行JavaScript应用程序:

>dotnet build
>cd result
>node main.mjs

应用程序在结果目录中创建一个新的result.pdf文件。

使用DevExpress Web文档查看器和报表设计器

按照readme文件中列出的步骤,运行后端和客户端应用程序,并将浏览器指向客户端应用程序中指定的URL。结果将显示如下:

DevExpress XAF (WinForms UI)实用案例图


更多DevExpress线上公开课、中文教程资讯请上中文网获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/830689.shtml

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

相关文章

【SQL Server】入门教程-基础篇(三)

目录 前言 SQL 常用函数学习 AVG – 平均值 COUNT – 汇总函数 ​编辑MAX – 最大值 ​编辑MIN – 最小值 ​编辑SUM – 求和 UCASE/UPPER – 大写 LCASE/LOWER – 小写 ROUND – 数值取舍 NOW/SYSDATE – 当前时间 前言 这一篇博客&#xff0c;是Sql Server函数学…

本地构建编译Apache-Seatunnel2.3.5适配Web1.0.0运行实现Mysql-CDC示例

本地构建编译Apache-Seatunnel2.3.5适配Web1.0.0运行实现Mysql-CDC示例 文章目录 1.前言2.编译2.1版本说明2.2 seatunnel2.3.4-release分支配置2.3maven调优配置 3.web1.0.0适配3.1配置文件修改和新增文件3.2手动拷贝jar修改依赖3.3修改web不兼容的代码3.4 web编译打包 4.运行m…

什么是 Web3 的生成式 AI?

从 Web 1.0 的静态、单向通信到 Web 2.0 的动态、用户驱动的格局&#xff0c;互联网在二十年的时间里经历了一场显着的转变。现在&#xff0c;当我们站在 Web 3.0 时代的边缘时&#xff0c;我们正在见证更具颠覆性的事物的曙光&#xff1a;生成式人工智能 (AI) 融入我们的数字世…

DB-GPT部署验证

一、DB-GPT简介 DB-GPT是一个开源的数据库领域大模型框架。目的是构建大模型领域的基础设施&#xff0c;通过开发多模型管理、Text2SQL效果优化、RAG框架以及优化、Multi-Agents框架协作等多种技术能力&#xff0c;让围绕数据库构建大模型应用更简单&#xff0c;更方便。 GITHU…

找不到msvcr120.dll怎么办,msvcr120.dll丢失的5种修复方法分享

计算机系统在运行某应用程序时无法正常启动&#xff0c;具体表现为缺少了一个至关重要的动态链接库文件——msvcr120.dll。这个DLL文件是微软Visual C Redistributable Package的一部分&#xff0c;对于确保许多基于Windows平台的软件能够顺利运作起着不可或缺的作用。msvcr120…

C、Minimizing the Sum(线性dp)

思路&#xff1a; 用dp[i][j] 来表示前i个数操作了j次的最小和&#xff0c;然后对于每个a[i]&#xff0c;我们分别枚举i前面操作了x次以及后面操作了j次&#xff0c;对于每次操作&#xff0c;都是将一段区间全换位区间最小值. 代码&#xff1a; void solve(){int n, k;cin &…

springboot mongodb分片集群事务

前置 mongodb分片集群想要使用事务,需要对应分片没有仲裁节点 代码 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId><version>2.1.0.RELEASE</version></d…

手拉手CentOS 安装 mysql-5.7

MySQL是一种关系型数据库管理系统&#xff0c;关系数据库将数据保存在不同的表中&#xff0c;而不是将所有数据放在一个大仓库内&#xff0c;这样就增加了速度并提高了灵活性。 tar.gz包安装 #如没有安装wget则无法使用&#xff0c;以装&#xff0c;则直接省略该步~&#xff…

JavaScript系列------2

1. JS 数据类型&#xff1a; 基本数据类型&#xff1a;number数字型,string字符串型,boolean布尔型,undefined未定义型,null空类型 引用数据类型&#xff1a;object对象 js 是弱数据类型的语言&#xff0c;只有当我们赋值了才知道是什么数据类型。 声明一个变量未赋值就是 un…

Arthas进阶

这里写自定义目录标题 六、class和classloader6、dump7、classloader 七、monitor/watch/trace/stack等核心命令的使用1、monitor2、watch3、trace4、stack5、tt6、option7、profiler 六、class和classloader 6、dump 将已加载类的字节码文件保存到特定目录&#xff1a;logs/…

js之JSON

json 是一种轻量级的数据交换格式。 json 就是一种在各个编程语言中流通的数据格式&#xff0c;负责不同编程语言中的数据传递和交互。 let data {name:张三,age:18}; console.log(data); // 对象 let str JSON.stringify(data); console.log(str); // json 数据 l…

环形链表题

1.环形链表1 看题&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 思路1&#xff1a;哈希表 遍历所有节点&#xff0c;每次遍历一个节点时&#xff0c;判断该节点是否被访问过。 可以使用哈希表来存储所有已经访问过的节点。每次到达一个节点&#xff0c;如果该节点已…

Qt | QFrame容器

01、QFrame 一、QFrame 类 1、QFrame类是带有边框的部件的基类,带边框部件的特点是有一个明显的边框,QFrame 类就是用来实现边框的不同效果的(把这种效果称为边框样式),所有继承自 QFrame 的子 类都可以使用 QFrame 类实现的效果。 2、部件通常是矩形的(其他形状的原理…

基于JWT实现的Token认证方案

JSON Web Token是什么&#xff1f; JSON Web Token&#xff08;JWT&#xff09;是目前最流行的跨域身份验证解决方案。 JSON Web Token&#xff08;JWT&#xff09;是一个开放标准&#xff08;RFC 7519&#xff09;&#xff0c;它定义了一种紧凑且自包含的方式&#xff0c;用…

牛客网刷题 | CC1 获取字符串长度

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 键盘输入一个字符串…

Linux操作系统预备 —— 冯·诺伊曼体系结构

一&#xff0c;什么是冯诺伊曼体系结构&#xff1f;&#xff08;是什么&#xff1f;&#xff09; 上面的图就是冯诺伊曼体系结构的总体简略图&#xff0c;不着急&#xff0c;我们一个一个来看&#xff1a; 1.1 输入输出设备 人们要想用计算机处理数据&#xff0c;首先就要把要…

Vue入门到关门之Vue项目工程化

一、创建Vue项目 1、安装node环境 官网下载&#xff0c;无脑下一步&#xff0c;注意别放c盘就行 Node.js — Run JavaScript Everywhere (nodejs.org) 需要两个命令 npm---->pipnode—>python 装完检查一下&#xff0c;hello world检测&#xff0c;退出crtlc 2、搭建vu…

OpenSSH 漏洞补丁更新笔记

OpenSSH 漏洞补丁更新笔记 相关背景OpenSSH 8.8 以后版本弃用RSA 以及影响centos 更新openssh9.7p1通过rpm包进行安装 Ubuntu更新openssh-9.5p1前置条件下载的源码包导入服务器后操作 相关背景 客户通过第三方扫漏工具发现服务器centos8和Ubuntu22.04有OpenSSH 相关高危漏洞 扫…

重新定义什么是共享办公室,一看即懂

共享办公室&#xff0c;也称为联合办公空间&#xff0c;是一种现代的工作空间模式&#xff0c;它允许不同公司或个体在一个共享的环境下工作&#xff0c;同时提供必要的办公设施和服务。这种模式打破了传统办公室的局限&#xff0c;提供了更高的灵活性和社区感。 共享办公室它通…

单片机排队叫号系统Proteus仿真程序 有取号键和叫号键以及重复叫号键 有注释

目录 1、前言 ​ 2、程序 资料下载地址&#xff1a;单片机排队叫号系统Proteus仿真程序 有取号键和叫号键以及重复叫号键 有注释 1、前言 系统组成&#xff1a;STC89C52RCLcd1602蜂鸣器按键 具体介绍&#xff1a; Lcd1602排队叫号系统&#xff0c;有取号显示窗和叫号显示窗…