Display Request
Display requests send hyper media content to the Boomack Server for display.
Content can be send in four different ways:
- As string (DisplayRequest.Text)
- As BAS64 encoded BLOB (DisplayRequest.Data)
- As source URL (DisplayRequest.Src)
- 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 theContent-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
- Code Highlight
Highlight(string language)
Sets thesyntax
display option. All PrismJS languages are supported.
- Content Extensions
You can learn more about content extensions here.ExtendAt(ExtensionMode extensionMode)
Sets theextend
display option.Prepend()
Sets theextend
display options tobegin
.Append()
Sets theextend
display options toend
.
- Cache Control
WithCache(CacheMode cacheMode)
Sets thecache
display option.Embed()
Sets thecache
display option toembed
.
- Visual Media Content
Scale(ScaleMode scaleMode)
Sets thescale
display option.Align(Alignment alignment)
Sets thealign
display option.Background(string cssBackground)
Sets thebackground
display option.
- HTML Content
InFrame(bool iFrame = true)
Sets theiframe
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 aDisplayOptions
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 toapplication/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 totext/plain
.ServerTextFile(string path)
Display a file from the filesystem of the server and set the media type totext/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 totext/html
.ServerHtmlFile(string path, bool? iFrame = null)
Display a file from the filesystem of the server and set the media type totext/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 aStream
.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 aStream
.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 aStream
.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