Web Report Designer/Web Report Viewer: Daten vom Frontend (Client) ins Backend (Server) senden

Click here for the English article.

Allgemein

In der Web-Entwicklung wird zwischen Frontend (Client) und Backend (Server) unterschieden. Das ermöglicht allgemein eine sauberere Architektur für bessere Wartbarkeit, Skalierbarkeit, Sicherheit und klare Verantwortlichkeiten/Trennung zwischen der Oberfläche (UI) und der Geschäftslogik.

Frontend: UI im Browser (Client)

Das Frontend umfasst alles, was im Browser oder auf dem Endgerät des Anwenders ausgeführt wird: zum Beispiel Razor, HTML, CSS oder JavaScript. Es ist für die Darstellung der Benutzeroberfläche sowie für die Interaktion des Anwenders mit der Webanwendung zuständig.

Backend: Verarbeitung/Daten/Geschäftslogik (Server)

Das Backend umfasst alles, was auf dem Server ausgeführt wird: zum Beispiel ASP.NET Core. Es ist für die Geschäftslogik, die Datenverarbeitung, die Authentifizierung sowie den Zugriff auf Datenquellen wie Datenbanken zuständig.

Struktur und Komponenten von List & Label

Die in den .NET bereitgestellten Komponenten des List & Label Web Report Designers (WRD) und des Web Report Viewers (WRV) sind entsprechend dieser Trennung und Architektur getrennt aufgestellt. Doch wie bekommt man nun Informationen vom Client (Frontend) auf den Server (Backend) transportiert, um damit weiterarbeiten zu können?

Anwendungsszenarien

Typische Anwendungsfälle können sein:

  • die Übergabe eines Authentifizierungsschlüssels (authKey)
  • die Angabe der List & Label-Anzeigesprache direkt vom Frontend, zum Beispiel anhand der System- oder Browser-Sprache des Clients, anstatt diese vom Backend beziehungsweise Server bestimmen zu lassen
  • die Übergabe der gesamten Datenquelle für einen Bericht, beispielsweise als JSON-Stream
  • und vieles mehr

Umsetzung

Die Web-Komponenten für WRD und WRV stellen dafür entsprechend das Attribut clientData bereit. Das ermöglicht die Übergabe beliebiger clientspezifischer Daten vom Frontend (Client) an den serverseitigen Kontext des WRD/WRV ins Backend (Server).

Frontend (Client): JavaScript-Frameworks

Vue.js (*.vue)

...
<template>
    <div>
        <ll-webreportdesigner 
          backendurl="https://localhost:<PORT>/LLWebReportDesigner" 
          showTutorial="true"
          clientData="MyCustomClientDataFromFrontEnd"
         />
    </div>
</template>

<script lang="ts">
</script>
...

React (*.tsx)

...
import { useExternalScript } from './hooks/useExternalScript';
export const WebReportDesigner = () => {
    const state = useExternalScript("https://localhost:<PORT>/WebReportDesigner.js");

    return (
        <div>
            <div>
                <title>WebReportDesigner</title>
            </div>
            <div>
                {state === "loading" && <p>Loading...</p>}
                {state === "ready" && 
                <ll-webreportdesigner 
                backendurl="https://localhost:<PORT>/LLWebReportDesigner"
                showTutorial="true"
                clientData="MyCustomClientDataFromFrontEnd" />
                }
            </div>
        </div>
    );
}
...

Angular (*.html)

...
<div>
    <ll-webreportdesigner 
        backendUrl="http://localhost:<PORT>/LLWebReportDesigner"
        showTutorial="true"
        clientData="MyCustomClientDataFromFrontEnd"
         />
</div>
...

Frontend (Client): MVC/Razor (*.cshtml)

...
@using combit.Reporting.Web
@using combit.Reporting.Web.WebReportDesigner
@model MVC_Web_Reporting_Sample.ViewModels.CustomViewModel

@{
    Layout = null;
    var options = new WebReportDesignerMVCOptions(string.Empty)
    {
        ShowTutorial = true,
        ClientData = "MyCustomClientDataFromFrontEnd"
    };
}

<!DOCTYPE html>

@Html.WebReportDesigner(options);
...

Backend (Server): C#

...
public override void OnProvideListLabel(
          ProvideListLabelContext provideListLabelContext)
{
    // verify if the context is in the initialization phase, if not, you can
    // access the client data (if sent by the client) and handle it accordingly
    if (!provideListLabelContext.Initializing)
    {
        // check, if clientData exists and is valid
        if(provideListLabelContext.ClientData != null)
        {
            // Handle/Access the client data here e.g. a simple string
            // or more complex JSON object
            var myClientData = provideListLabelContext.ClientData;
        }
    }
    
    // Forward with creating the ListLabel object, defining the dataprovider etc.
    // and returning the prepared object 
    ListLabel ll = DefaultSettings.GetListLabelInstance(
                              provideListLabelContext.RepositoryId, null);
    provideListLabelContext.NewInstance = ll;
}
...