NBoomackClient
Show / Hide Table of Contents

Display Request

Display requests send hyper media content to the Boomack Server for display.

Content can be send in four different ways:

  1. As string (DisplayRequest.Text)
  2. As BAS64 encoded BLOB (DisplayRequest.Data)
  3. As source URL (DisplayRequest.Src)
  4. Streamed (DisplayRequest.Stream)

In the basic programming style, you have to decide yourself in what way your content is encoded. In the fluent style, this decision is made for you.

Besides the content, the display request contains a number of metadata with instructions for the Boomack Server how to process and display the content.

  • Target panel and slot
  • Title
  • Medias Type of the content
  • Preset IDs
  • Display Options

The following examples assume you already have a configured BoomackClient instance in the variable client. See Get Started if you do not know how to configure a BoomackClient instance.

Basic Metadata

Basic style:

var request = new DisplayRequest
{
    Panel = "my-panel",
    Slot = "my-slot",
    Title = "My Content Title",
    Type = "text/plain",
    Text = "Your plain text to display",
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .Target(panel: "my-panel", slot: "my-slot")
    .WithTitle("My Content Title")
    .Text("Your plain text to display"));

HTML Fragment

Basic style:

var request = new DisplayRequest()
{
    Type = "text/html",
    Text = "<h1>My Headline</h1>",
    Options = new DisplayOptions() { IFrame = false },
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .Html("<h1>My Headline</h1>", iFrame: false));

Standalone HTML Page in IFRAME

Given a HTML page stored in a string:

var html = "<!DOCTYPE html>\n"
    + "<html><head>\n"
    + "<style> body { background: Navy; color: White; } </style>\n"
    + "</head><body>\n"
    + "<h1>My Page</h1>\n"
    + "<p>Hello World!</p>\n"
    + "</body></html>";

Basic style:

var request = new DisplayRequest()
{
    Type = "text/html",
    Text = html,
    Options = new DisplayOptions { IFrame = true },
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .Html(html, iFrame: true));

HTML Fragment from File

Basic style:

var path = "my-fragment.html";
using var s = File.OpenRead(path);
var request = new DisplayRequest()
{
    Type = "text/html",
    Stream = s,
    Options = new DisplayOptions { IFrame = false },
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .LocalHtmlFile("my-fragment.html", iFrame: false));

Image from File

Basic style:

var path = "my-image.png";
using var s = File.OpenRead(path);
var request = new DisplayRequest()
{
    Stream = s,
    Type = "image/png",
    Options = new DisplayOptions()
    {
        Scale = ScaleMode.Contain,
        Cache = CacheMode.Memory,
    },
};

Fluent style:

await client.Display(builder => builder
    .LocalImageFile("my-image.png", scale: ScaleMode.Contain, cache: CacheMode.Memory));

Vega Lite Plot from File

Basic style:

var path = "my-plot.vegalite";
var request = new DisplayRequest()
{
    Text = System.IO.File.ReadAllText(path, System.Text.Encoding.UTF8),
    Type = "application/x-vega-lite-spec",
};

Fluent style:

await client.Display(builder => builder
    .LocalFile("my-plot.vegalite"));

Vega Lite Plot from Object

Given the following object, declared with an anonymous type, you can use JSON serialization to build the request.

Because the Vega Lite plot is displayed using a text transformation from a plugin, its specific display options can not be known to this library. Therefore, the display option vega must be set as an entry on the display options dictionary in the basic style, or set as a dynamic property in the fluent style.

var vegaLiteSpec = new
{
    data = new
    {
        values = new[]
            {
                new { a = "A", b = 28 },
                new { a = "B", b = 55 },
                new { a = "C", b = 43 },
                new { a = "D", b = 91 },
                new { a = "E", b = 81 },
                new { a = "F", b = 53 },
            },
    },
    mark = "bar",
    encoding = new
    {
        x = new { field = "a", type = "nominal", axis = new { labelAngle = 0 } },
        y = new { field = "b", type = "quantitative" },
    },
};

Basic style:

var displayOptions = new DisplayOptions();
displayOptions["Vega"] = new
{
    Padding = 20,
    Renderer = "svg",
};
var request = new DisplayRequest()
{
    Text = client.SerializeToJson(vegaLiteSpec),
    Type = "application/x-vega-lite-spec",
    Options = displayOptions,
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .Json(vegaLiteSpec, "application/x-vega-lite-spec")
    .ConfigureDynamic(options =>
    {
        options.Vega = new
        {
            Padding = 20,
            Renderer = "svg",
        };
    }));

Remote Resources

You can tell the Boomack Server to display some content from another HTTP server.

Basic style:

var request = new DisplayRequest()
{
    Src = new Uri("https://bit.ly/3tgSmpM"),
    Type = "image/jpeg",
    Options = new DisplayOptions()
    {
        Scale = ScaleMode.None,
        Align = Alignment.TopLeft,
        Cache = CacheMode.Embed,
    },
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .RemoteContent("https://bit.ly/3tgSmpM")
    .Scale(ScaleMode.None)
    .Align(Alignment.TopLeft)
    .Embed());

Or, because you know the content is an image:

await client.Display(builder => builder
    .RemoteImage("https://bit.ly/3tgSmpM",
        scale: ScaleMode.None, align: Alignment.TopLeft));

Website

You can show a complete website with an IFRAME in a slot.

However, an HTTP server can send the X-Frame-Options header field, or the newer frame-ancestors directive in the Content-Security-Policy field, to tell the browser that a website is not supposed to be displayed in a frame. In that case the browser only displays a warning instead of the webpage. Unfortunately, a lot of large sites do send this header field for security or corporate brand reasons.

To ignore theses headers in your own web browser, you can try to install a web extension or addon for that purpose.

For Firefox try the following search: https://addons.mozilla.org/en-US/firefox/search/?q=X-Frame-Options

For Chrome the following search should yield some results: https://chrome.google.com/webstore/search/X-Frame-Options

Warning: Be aware that installing one of these plugins can make you vulnerable for click-jacking attacks. Maybe only activate the plugin when you really need it, or use a whitelist if supported by the plugin.

Basic style:

var request = new DisplayRequest()
{
    Src = new Uri("https://duckduckgo.com/?q=boomack"),
    Type = "text/html",
    Options = new DisplayOptions() { IFrame = true },
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .Website("https://duckduckgo.com/?q=boomack"));

Stream

Sending a stream is an allpurpose tool of course, but particularly useful for embedded manifest resources.

Important: A stream passed inside a display request is disposed automatically by the Boomack client.

In order to use this approach, you include your media content file into your project and set the build action in the properties to embedded resource. Then you can open the stream by building a name with the namespace and location of the file inside the project folder. Path separators are converted from slashes into dots. Instead of concatenating the namespace prefix yourself, you can pass a type, in order to use its namespace as prefix.

Example:

  • Project Root
    • MyProject.csproj
    • Media
      • Picture.jpg

Assuming the default namespace of your project is MyDemo.Boomack you can use the following code to open a stream to embedded resources in the Media folder.

namespace MyDemo.Boomack
{
    internal static class ClientResources
    {
        public Stream OpenMediaStream(string name)
        {
            var assembly = System.Reflection.Assembly.GetExecutingAssembly();
            // looks up the manifest resource MyDemo.Boomack.Media.Picture.jpg
            return assembly.GetManifestResourceStream(
                typeof(ClientResources), "Media." + name)
                ?? throw new ArgumentException("Resource not found", nameof(name));
        }
    }
}

Basic style:

var request = new DisplayRequest()
{
    Stream = ClientResources.OpenMediaStream("Picture.jpg"),
    Type = "image/jpeg",
    Options = new DisplayOptions() {
        Scale = ScaleMode.ScaleDown,
    },
};
await client.Display(request);

Fluent style:

await client.Display(builder => builder
    .Stream(ClientResources.OpenMediaStream("Picture.jpg"), "image/jpeg")
    .Scale(ScaleMode.ScaleDown));

Or, because you know the stream contains an image:

await client.Display(builder => builder
    .Image(ClientResources.OpenMediaStream("Picture.jpg"), CommonImageType.Jpeg,
        scale: ScaleMode.ScaleDown));

Display Request Builder

The comfort of the fluent API comes from the interface IDisplayRequestBuilder and extension methods from DefaultDisplayRequestBuilderExtensions.

The builder comes with convenience methods for setting metadata and known display options, as well as methods for specifying the source of the content.

Metadata

  • Debug(bool debug = true)
    (De)activates the debug mode for the display request.
  • Target(string panel = null, string slot = null)
    Sets the target panel and/or slot.
  • WithTitle(string title)
    Sets the content title.
  • WithPresets(params string[] presetIds)
    Adds the given preset IDs to the request.
  • AsMediaType(string contentType)
    Sets the content type.
  • WithMediaTypeFromFilename(string filename)
    Maps the given filename through the media type mapping from the client configuration to a media type for the content.
  • WithMediaTypeFromUrlPath()
    Maps the path of the source URL through the media type mapping from the client configuration to a media type for the content. Expects an URL to be set earlier for the content.
  • ProbeUrlMediaType(TimeSpan? timeout = null)
    Performs an HTTP HEAD request to the source URL and takes the Content-Type header field from the response as media type for the content. Expects an URL to be set earlier for the content.

Display Options

You can learn more about display options here.

  • Known Display Options
    • Pipeline Control
      • WithTransformation(string transformation)
        Activates a text transformation by specifying a transformation ID. You can learn more about text transformations here.
      • WithRenderer(string renderer)
        Activates a renderer by specifying a renderer ID. You can learn more about renderers here.
    • Code Highlight
      • Highlight(string language)
        Sets the syntax display option. All PrismJS languages are supported.
    • Content Extensions
      You can learn more about content extensions here.
      • ExtendAt(ExtensionMode extensionMode)
        Sets the extend display option.
      • Prepend()
        Sets the extend display options to begin.
      • Append()
        Sets the extend display options to end.
    • Cache Control
      • WithCache(CacheMode cacheMode)
        Sets the cache display option.
      • Embed()
        Sets the cache display option to embed.
    • Visual Media Content
      • Scale(ScaleMode scaleMode)
        Sets the scale display option.
      • Align(Alignment alignment)
        Sets the align display option.
      • Background(string cssBackground)
        Sets the background display option.
    • HTML Content
      • InFrame(bool iFrame = true)
        Sets the iframe display option.
  • Generic Configuration
    Important: All property names in the display options — top level or nested — are converted to JavaScript naming conventions. Meaning the first character of all property names is converted to lower case in the resulting JSON request.
    • WithOption(string name, object value)
      Sets an arbitrary display option property.
    • WithOptions(IDictionary<string, object> options)
      Sets multiple display options from a dictionary.
    • Configure(Action<DisplayOptions> configurer)
      Takes a delegate which is called with a DisplayOptions object for further configuration.
    • ConfigureDynamic(Action<dynamic> configurer)
      Takes a delegate which is called with a dynamic object for further configuration.

Content

The following methods belong directly to the IDisplayRequestBuilder interface:

  • Text(string text, string contentType = "text/plain")
    Sets the given string as text content.
  • Blob(byte[] data, string contentType = "application/octet-stream")
    Sets the given BLOB as BASE64 encoded binary content.
  • Url(Uri url, string contentType = "application/octet-stream", bool? iFrame = null)
    Sets the given URL as source URL.
  • Stream(Stream stream, string contentType = "application/octet-stream")
    Sets the given stream as content source.

The following methods are implemented as extension methods:

  • Json<T>(T data)
    Serialize the given object as pretty printed JSON and set the media type to application/json.
  • LocalFile(string path, string contentType = null, CacheMode? cacheMode = null)
    Stream a local file and, by default, detect the media type from the filename.
  • ServerFile(string path, string contentType = null)
    Display a file from the filesystem of the server and, by default, detect the media type from the filename.
  • RemoteContent(string url, string contentType = null, bool? iFrame = null)
    Display content from an HTTP(S) URL and, by default, detect the media type from the path in the URL or, if that fails, with an HEAD request.
  • LocalTextFile(string path)
    Stream a local file and set the media type to text/plain.
  • ServerTextFile(string path)
    Display a file from the filesystem of the server and set the media type to text/plain.
  • Html(string html, bool? iFrame = null)
    Send a HTML fragment or a standalone HTML page.
  • LocalHtmlFile(string path, bool? iFrame = null)
    Stream a local file and set the media type to text/html.
  • ServerHtmlFile(string path, bool? iFrame = null)
    Display a file from the filesystem of the server and set the media type to text/html.
  • Code(string text, string language = null)
    Send the given string as text and activate syntax highlighting for the given language. All PrismJS languages are supported.
  • LocalCodeFile(string path, string language = null)
    Stream a local file as text and activate syntax highlighting for the given language. All PrismJS languages are supported.
  • ServerCodeFile(string path, string language = null)
    Display a file from the filesystem of the server as text and activate syntax highlighting for the given language. All PrismJS languages are supported.
  • Image(Stream stream, CommonImageType type, ...)
    Send an image from a Stream.
  • Image(byte[] data, CommonImageType type, ...)
    Send an image from a BLOB.
  • LocalImageFile(string path, string contentType = null, ...)
    Stream a local file as image and, by default, detect the image format from the filename.
  • ServerImageFile(string path, string contentType = null, ...)
    Display a file from the filesystem of the server as image and, by default, detect the image format from the filename.
  • RemoteImage(string url, CommonImageType? type = null, ...)
    Display an image from an HTTP(S) URL and, by default, detect the image format from the path in the URL or, if that fails, with an HEAD request.
  • Audio(Stream stream, CommonAudioType type, ...)
    Send audio content from a Stream.
  • Audio(byte[] data, CommonAudioType type, ...)
    Send audio content from a BLOB.
  • LocalAudioFile(string path, string contentType = null, ...)
    Stream a local file as audio and, by default, detect the audio format from the filename.
  • ServerAudioFile(string path, string contentType = null, ...)
    Display a file from the filesystem of the server as audio and, by default, detect the audio format from the filename.
  • RemoteAudio(string url, CommonAudioType? type = null, ...)
    Display an audio from an HTTP(S) URL and, by default, detect the audio format from the path in the URL or, if that fails, with an HEAD request.
  • Video(Stream stream, CommonVideoType type, ...)
    Send a video from a Stream.
  • Video(byte[] data, CommonVideoType type, ...)
    Send a video from a BLOB.
  • LocalVideoFile(string path, string contentType = null, ...)
    Stream a local file as video and, by default, detect the video format from the filename.
  • ServerVideoFile(string path, string contentType = null, ...)
    Display a file from the filesystem of the server as video and, by default, detect the video format from the filename.
  • RemoteVideo(string url, CommonVideoType? type = null, ...)
    Display a video from an HTTP(S) URL and, by default, detect the video format from the path in the URL or, if that fails, with an HEAD request.

Important: All convenience methods beginning with Server... are sending file:// URLs to the server. This approach can be very performant and efficient, because the content is not copied and not even read when processing the display request. And if a web client shows the content, the server directly streams from the file. But because displaying the content of arbitrary files from the filesystem of the server can be a severe security thread, it is deactivated by default. To allow for this approach, you need to start the server with the configuration option api.request.fileSrcRoots set to a list with allowed base paths.


Next: Clear Request

In This Article
Back to top
Boomack Homepage