Creating Elegant Reports in WebAssembly Apps with DevExpress Reporting and Uno Platform

Good engineers integrate when and where it makes sense regardless of the territory being charted. Great engineers and community members explore that uncharted territory and map it out for othersThis is what one of our clients and contributors – Kahua – faced when facing a business challenge. They solved it and shared some tips on how to go about it for anyone who walks the same path.  

The Challenge

Kahua needed to create a large number of dashboards and reports across platforms and devices on top of the Uno Platform powered Web Application and soon mobile and desktop applications. 

On the technical side, this meant connecting two advanced and complex frameworks with an enterprise application and bringing forward what all three entities do the best. 

  1. DevExpress is a widely used powerful reporting framework which is highly configurable and works cross-platform.  

  2. Uno Platform provides multi-platform support for applications built with C# and XAML.

  3. Kahua is an enterprise application which provides complex configuration, user-defined applications and runs on .NET.  

Uno Platform and DevExpress are using .NET and JavaScript to provide their functionality beside other technologies. Meanwhile, Kahua is utilizing .NET and XAML for its client application.  

Kahua was already utilizing Uno Platform to provide Web-based client applications by XAML definition, which Uno Platform framework uses to render JavaScript code. However, DevExpress does not provide out-of-box support for Uno platform, so it was impossible to use DevExpress ASP.NET (Web Forms, MVC, Core) Reporting approach. But on a technology level, we thought we could get all these systems to work together.  

DevExpress framework provides a way to use JavaScript frameworks like Angular, React, Vue and Knockout to render client-site reporting. That’s currently the only way to use DevExpress reporting components in Kahua’s solution. 

The Solution

Angular, React and Vue offered by DevExpress require an additional complex framework to manipulate the DOM tree and maintain the application state. The advantage of using Uno Platform is that it already manipulates the DOM tree and keeps track of the current application state by its internal JavaScript binding to .NET web assembly. Because of that, Knockout solutions seemed to be the easiest approach, which is what we used.  

Knockout DevExpress integration uses 5 JavaScript libraries that work together and need to be loaded in a certain order (https://docs.devexpress.com/XtraReports/401546/web-reporting/javascript-reporting/knockout/document-viewer/document-viewer-integration-with-npm-yarn).  

Base libraries are jQuery, jQuery-UI and Knockout. Those need to be loaded and initialized before other libraries are loaded in the browser. DevExpress library DevExtreme contains checks and will fail to load if they are not in place. DevExpress AnalyticsCore library contains a check for DevExtreme. Finally, DevExpress DocumentViewer library has to be loaded last and contains component configuration to set up UI Reporting DocumentViewer.  

Thankfully Uno Platform provides an easy way to use JavaScript in .NET components which are rendered by its platform (https://platform.uno/docs/articles/interop/wasm-javascript-3.html). Also, it utilizes RequireJS framework to load JavaScript dependencies. At Kahua, we could load DevExpress JavaScript libraries in order inside Kahua’s .NET user control in proper order and let Uno Platform render DevExpress DocumentViewer reporting component in DOM tree.  

A great performance tip is that to minimize the number of server round tips; JavaScript libraries were added as ‘Assets’ in Uno Platform. Using Assets, JavaScript libraries will be loaded only once and stored on the client site after the first load. This is required because DocumentViewer component will be used multiple times on different application pages.  

This is just the beginning; more work is needed for DocumentViewer configuration, passing state from .NET user control to Reporting component and back. Maintaining multiple DocumentViewer components in DOM tree etc.  

All that said, it is a great achievement to connect pure JavaScript libraries (jQuery, Knockout, …) with two complex cross-platform frameworks (DevExpress, Uno Platform) and a big enterprise application (Kahua) to provide customers seamless web experience with similar UI and same business functionalities on multiple platforms.  

				
					<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <NoWarn>NU1701</NoWarn>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
    <MonoRuntimeDebuggerEnabled>true</MonoRuntimeDebuggerEnabled>
    <DefineConstants>$(DefineConstants);TRACE;DEBUG</DefineConstants>
    <DebugType>portable</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <!--
		IL Linking is disabled in Debug configuration.
		When building in Release, see https://platform.uno/docs/articles/features/using-il-linker-webassembly.html
		-->
    <WasmShellILLinkerEnabled>false</WasmShellILLinkerEnabled>
  </PropertyGroup>
  <ItemGroup>
    <Content Include="Assets\js\dx-analytics-core.js" />
    <Content Include="Assets\js\dx-webdocumentviewer.js" />
    <Content Include="Assets\js\dx.all.js" />
    <Content Include="Assets\js\jquery-ui.min.js" />
    <Content Include="Assets\js\jquery.min.js" />
    <Content Include="Assets\js\knockout-latest.js" />
    <Content Include="Assets\SplashScreen.png" />
  </ItemGroup>
  <ItemGroup>
    <UpToDateCheckInput Include="..\UnoDXDocumentViewer.Shared\**\*.xaml" />
  </ItemGroup>
  <ItemGroup>
    <None Remove="Assets\js\dx-analytics-core.js" />
    <None Remove="Assets\js\dx-webdocumentviewer.js" />
    <None Remove="Assets\js\dx.all.js" />
    <None Remove="Assets\js\jquery-ui.min.js" />
    <None Remove="Assets\js\jquery.min.js" />
    <None Remove="Assets\js\knockout-latest.js" />
    <None Remove="WasmCSS\dx-analytics.common.css" />
    <None Remove="WasmCSS\dx-analytics.light.compact.css" />
    <None Remove="WasmCSS\dx-analytics.light.css" />
    <None Remove="WasmCSS\dx-webdocumentviewer.css" />
    <None Remove="WasmCSS\dx.light.compact.css" />
    <None Remove="WasmCSS\dx.light.css" />
    <None Remove="WasmCSS\jquery-ui.min.css" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="WasmCSS\dx-analytics.common.css" />
    <EmbeddedResource Include="WasmCSS\dx-analytics.light.compact.css" />
    <EmbeddedResource Include="WasmCSS\dx-analytics.light.css" />
    <EmbeddedResource Include="WasmCSS\dx-webdocumentviewer.css" />
    <EmbeddedResource Include="WasmCSS\dx.light.compact.css" />
    <EmbeddedResource Include="WasmCSS\dx.light.css" />
    <EmbeddedResource Include="WasmCSS\Fonts.css" />
    <EmbeddedResource Include="WasmCSS\jquery-ui.min.css" />
    <EmbeddedResource Include="WasmScripts\AppManifest.js" />
  </ItemGroup>
  <ItemGroup>
    <LinkerDescriptor Include="LinkerConfig.xml" />
  </ItemGroup>
  <ItemGroup>
    <!--
		This item group is required by the project template because of the
		new SDK-Style project, otherwise some files are not added automatically.

		You can safely remove this ItemGroup completely.
		-->
    <None Include="Program.cs" />
    <None Include="LinkerConfig.xml" />
    <None Include="wwwroot\web.config" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Windows.Compatibility" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Filter" Version="1.1.1" />
    <PackageReference Include="Uno.Extensions.Logging.WebAssembly.Console" Version="1.3.0" />
    <PackageReference Include="Uno.Microsoft.Toolkit.Uwp.UI.Controls" Version="7.1.10" />
    <PackageReference Include="Uno.Toolkit.UI" Version="1.4.0-dev.3" />
    <PackageReference Include="Uno.Toolkit.UI.Material" Version="1.4.0-dev.3" />
    <PackageReference Include="Uno.UI.WebAssembly" Version="4.4.0-dev.205" />
    <PackageReference Include="Uno.UI.RemoteControl" Version="4.4.0-dev.218" Condition="'$(Configuration)'=='Debug'" />
    <PackageReference Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="4.4.0-dev.205" />
    <PackageReference Include="Uno.Wasm.Bootstrap" Version="4.0.0-dev.174" />
    <PackageReference Include="Uno.Wasm.Bootstrap.DevServer" Version="4.0.0-dev.174" />
    <PackageReference Include="Uno.XamlMerge.Task" Version="1.1.0-dev.13" />
  </ItemGroup>
  <Import Project="..\UnoDXDocumentViewer.Shared\UnoDXDocumentViewer.Shared.projitems" Label="Shared" Condition="Exists('..\UnoDXDocumentViewer.Shared\UnoDXDocumentViewer.Shared.projitems')" />
</Project>
				
			

The dll is licensed but DevExpress provides a free 30-day trial version which you can download here.

Lesson Learned

Along the way, we learned a few lessons we’d love to share with all of you who wish to connect technologies that don’t necessarily offer out-of-the-box support for each other. However, it just makes sense to try to integrate them as, on a technology level, there isn’t anything that’d prevent its joint work. Furthermore, with Uno Platform, you are never locked into a particular way of doing things. Every time you need to step out into either the native world on the mobile side of the JavaScript world on the Web side – that is entirely possible.

When integrating complex frameworks, start with the smallest example. Take the Hello World example from one framework and try integrating the second one into it. Instead of integrating the DevExpress framework directly into Kahua + Uno Platform solution, I’ve started with Uno example from their web page.

The difference between pure Html + JavaScript and using a framework like Uno Platform that utilizes WebAssemblies. Many moving pieces and loading orders can differ from what you are used to on a web page. I’ve split the loading of JavaScript libraries one by one to find the correct order. DevExpress libraries have checks that previous packages were loaded. I had to find the right order and initialize the Knockout library into the windows.ko variable.

Read documentation and examples of used frameworks.
Uno’s example 
https://platform.uno/docs/articles/interop/wasm-javascript-3.html provides a great baseline to integrate a simple JavaScript library.

DevExpress documentation is robust https://docs.devexpress.com/XtraReports/118599/web-reporting/javascript-reporting and has a lot of valuable information. Read the MVC vs Core section to properly configure the Reporting component’s reportUrl variable.  

				
					// Use this line if you use an ASP.NET MVC backend  
invokeAction = "/WebDocumentViewer/Invoke"  
// Uncomment this line if you use an ASP.NET Core backend  
//invokeAction = "DXXRDV" 
				
			

Once the integration works, replicate it in the main project using the simplest use case. You’ve already learned integrated frameworks and found the main pitfalls.

About Kahua 

Kahua provides capital project management and collaboration software focused on real estate, engineering, construction, education, and government sectors. Kahua’s solution helps manage project and program costs, documents, and processes from inception through implementation to improve efficiency and reduce risk. 

About Uno Platform

For those new to the Uno Platform, it allows for creating pixel-perfect, single-source C# and XAML apps that run natively on Windows, iOS, Android, macOS, Linux and Web via WebAssembly. In addition, it offers Figma integration for design-development handoff and a set of extensions to bootstrap your projects. Uno Platform is free, open-source (Apache 2.0), and available on GitHub.

Next Steps

To upgrade to the latest release of Uno Platform, please update your packages to 4.7 via your Visual Studio NuGet package manager! If you are new to Uno Platform, following our official getting started guide is the best way to get started. (5 min to complete)

Share this post:
Tune in Today at 12 PM EST for our free Uno Platform 5.0 Live Webinar
Watch Here