Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Progressive Web Apps mit Blazor: So bringen Sie Ihre .NET-App ins Web!

Progressive Web Apps mit Blazor: So bringen Sie Ihre .NET-App ins Web!

Stellen Sie sich vor, Sie schreiben Ihre moderne Businessanwendung genau einmal – und sie läuft auf Windows, macOS, Linux, Android, iOS und im Browser. Diese Anwendungen werden per Fingertippen aus dem Browser auf dem Gerät installiert und funktionieren auch dann, wenn das WiFi im Zug gerade mal wieder nicht funktioniert. Das klingt fantastisch? Dank Progressive Web Apps (PWA) wird all das Wirklichkeit. Mit Hilfe moderner Webtechnologien wird aus einer Webanwendung eine App, die einer nativen App in nichts nachsteht.

In diesem Workshop zeigen wir anhand eines durchgängigen Beispiels die Grundlagen der PWA-Entwicklung mit Microsofts Single Page App Framework Blazor, bei denen Sie aktiv mitentwickeln können. Jede(r) geht mit einer PWA nach Hause!

Christian Liebel

November 27, 2023
Tweet

More Decks by Christian Liebel

Other Decks in Programming

Transcript

  1. Christian Liebel Patrick Jahr
    @christianliebel @jahr_patrick
    Consultant Developer Consultant
    Progressive Web Apps mit Blazor: So
    bringen Sie Ihre .NET-App ins Web!

    View full-size slide

  2. Feel free to ask questions anytime!
    Your instructors
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor
    Patrick Jahr Christian Liebel

    View full-size slide

  3. 09:00–10:30 Block 1
    10:30–11:00 Break
    11:00–12:30 Block 2
    12:30–13:30 Break
    13:30–15:00 Block 3
    15:00–15:30 Break
    15:30–17:00 Block 4
    Timetable
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  4. Things NOT to expect
    - Blueprint for PWA
    development
    - No AuthN/AuthZ
    - No 1:1 support
    Things To Expect
    - Extensive/up-to-date insights
    into PWA and Project Fugu
    - A productivity app use case
    that works on your desktop &
    smartphone
    - Lots of fun
    - Hands-on-exercises
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  5. https://paint.js.org
    – Productivity app
    – Draw images
    – Lots of actions & tools
    – Installable
    – Read/save files
    – Copy/paste images
    from/to clipboard
    – Share files to other apps
    – Register for file extensions
    Demo Use Case
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  6. (Workshop Edition)
    – Productivity app
    – Draw images
    – Lots of actions & tools
    – Installable
    – Read/save files
    – Copy/paste images
    from/to clipboard
    – Share files to other apps
    – Register for file extensions
    Demo Use Case
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  7. Setup complete?
    (.NET 8 SDK, Visual Studio 2022, Chrome or Edge, Git)
    Setup (1/2)
    EX #0
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  8. git clone https://github.com/thinktecture-labs/ddc-
    2023-blazor-project-fugu.git
    Setup (2/2)
    EX #0
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  9. Paint PWA
    Capabilitie
    s
    Progressive
    Enhanceme
    nt
    Agenda
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  10. Paint PWA
    Capabilitie
    s
    Progressive
    Enhanceme
    nt
    Agenda
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  11. Canvas
    – Plain bitmap for the web
    – Cross-platform, hardware-
    accelerated graphics
    operations
    – Supports different contexts
    (2D, 3D: WebGL, WebGL 2.0)
    – Supported on all evergreen
    browsers and on IE 9+
    Paint
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  12. Canvas
    Add a canvas element to Index.razor:
    height="480">
    Query the canvas element in Index.razor.cs:
    private Canvas? _canvas;
    Paint
    EX #1
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  13. Canvas 2D Context
    fillRect(x, y, width, height)
    strokeRect(x, y, width, height)
    beginPath()
    moveTo(x, y)
    lineTo(x, y)
    fill()
    stroke()
    Paint
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  14. Canvas 2D Context
    Get the 2D context and prepare the canvas in Index.razor.cs in the
    method OnAfterRenderAsync(bool firstRender):
    await using var context = await _canvas!.GetContext2DAsync();
    await context.FillStyleAsync("white");
    await context.FillRectAsync(0, 0, 600, 480);
    await context.FillStyleAsync("black");
    Paint
    EX #2
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  15. Low-latency Rendering
    Paint
    Web pages need to synchronize
    with the DOM on graphics updates
    causing latencies that can make
    drawing difficult
    Low-latency rendering skips
    syncing with the DOM with can lead
    to a more natural experience
    Supported on Chrome (Chrome OS
    and Windows only)
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  16. Low-latency Rendering
    Opt-in to low-latency rendering (Index.razor.cs):
    await using var context = await
    _canvas!.GetContext2DAsync(desynchronized: true);
    Paint
    EX #3
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  17. Pointer Events
    Paint
    Users nowadays use different
    input methods, cross-platform
    apps should cover all of them
    Pointer Events offer an
    abstract interface to catch all
    input methods (pointerdown,
    pointermove, pointerup)
    event.offsetX/event.offsetY
    contain the pointer’s position
    relative to the listener
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  18. Pointer Events
    Add event listeners (Index.razor):
    @onpointerdown="OnPointerDown"
    @onpointerup="InternalPointerUp"
    @onpointermove="OnPointerMove">

    Paint
    EX #4
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  19. Pointer Events
    Add event listeners methods (Index.razor.cs):
    private async void OnPointerMove(PointerEventArgs args)
    {
    var currentPoint = new Point
    {
    X = (int)Math.Floor(args.OffsetX),
    Y = (int)Math.Floor(args.OffsetY)
    };
    await using var context = await _canvas!.GetContext2DAsync(desynchronized:
    true);
    await context.FillRectAsync(currentPoint.X, currentPoint.Y, 2, 2);
    }
    Paint
    EX #4
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  20. Pointer Events
    Add event listeners methods (Index.razor.cs):
    private async void OnPointerDown(PointerEventArgs args)
    {
    _previousPoint = new Point
    {
    X = (int)Math.Floor(args.OffsetX),
    Y = (int)Math.Floor(args.OffsetY)
    };
    }
    Paint
    EX #4
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  21. Bresenham Line Algorithm
    The user may move faster than
    the input can be processed
    For this case, we need to
    remember the previous point
    and interpolate the points in
    between
    The Bresenham line algorithm
    calculates the missing pixels
    between two given points
    Paint
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  22. Bresenham Line Algorithm
    Update the method OnPointerMove() in Index.razor.cs:
    if (_previousPoint != null)
    {
    var currentPoint = new Point
    {
    X = (int)Math.Floor(args.OffsetX),
    Y = (int)Math.Floor(args.OffsetY)
    };
    var points = _paintService.BrensenhamLine(_previousPoint.Value, currentPoint);
    await using var context = await _canvas.GetContext2DAsync();
    foreach (var point in points)
    {
    await context.FillRectAsync(point.X, point.Y, 2, 2);
    }
    _previousPoint = currentPoint;
    }
    Paint
    EX #5
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  23. Color Selection
    For this demo, we will only
    implement the brush tool. However,
    we want to bring in some color.
    A simple method to implement a
    color selection is to use the HTML
    color-type input element that
    shows the native color picker:

    Paint
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  24. Color Selection
    1. In Index.razor, add the following input to the node:

    2. In Index.razor.cs, add the following code in the method
    OnColorChange():
    await using var context = await _canvas!.GetContext2DAsync();
    await context.FillStyleAsync(args.Value?.ToString());
    Paint
    EX #6
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  25. Paint PWA
    Capabilitie
    s
    Progressive
    Enhanceme
    nt
    Agenda
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  26. Responsive Linkable Discoverable Installable App-like
    Connectivity
    Independent
    Fresh Safe Re-engageable Progressive
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  27. Web App
    Manifest
    Service
    Worker
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  28. Web App Manifest
    Distinguishes Web Apps from
    Websites
    JSON-based file containing
    metadata for apps only
    Apps can be identified by search
    engines, app store providers, etc.
    PWA
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  29. manifest.webmanifest
    {
    "short_name": "Paint",
    "name": "Paint Workshop",
    "theme_color": "white",
    "icons": [{
    "src": "icon.png",
    "sizes": "512x512"
    }],
    "start_url": "./",
    "display": "standalone",
    "shortcuts": [/* … */]
    }
    PWA
    Names
    Icons
    Display Mode
    Shortcuts
    Start URL
    Theme color (status bar/window bar)
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  30. Manifest Display Modes
    PWA
    browser minimal-ui standalone fullscreen
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  31. Manifest Icon Purposes
    (any)
    any context (e.g. app icon)
    monochrome
    different color requirements
    maskable
    user agent masks icon as required
    PWA
    Safe Zone
    Windows iOS Android
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  32. Blazor Support
    The Blazor PWA template adds
    a web app manifest and
    service worker support
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    PWA

    View full-size slide

  33. Web App Manifest
    1. Update the file wwwroot/manifest.json and set:
    a) name and short_name to values of your choice
    b) theme_color to #000080 and background_color to #808080
    2. In index.html, set theme_color to #000080 as well.
    3. Run dotnet run
    4. Test manifest in DevTools: F12 > Application > Manifest
    PWA
    EX #7
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  34. Manifest Shortcuts
    PWA
    Secondary entrypoints for your
    application (e.g., home screen
    quick actions, jump lists, …)
    Static definition in Web App
    Manifest (dynamic API may
    follow in the future)
    Supported by Google Chrome
    for Android, macOS and
    Windows
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  35. Web App Manifest
    1. In wwwroot/manifest.json, add (at least) the following shortcut:
    "shortcuts": [{
    "name": "About Paint",
    "short_name": "About",
    "description": "Show information about Paint",
    "url": "./",
    "icons": [{ "src": "icon-512.png", "sizes": "512x512" }]
    }],
    2. Test in DevTools: F12 > Application > Manifest
    PWA
    EX #8
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  36. Web App Manifest – Installability Criteria
    1. Web App is not already installed
    2. User clicked the page at least once and had it open for at least 30
    seconds (at any time)
    3. Includes a Web App Manifest that has short_name or name, at least a
    192px and 512px icon, a start_url and a display mode of fullscreen,
    standalone or minimal-ui
    4. Served over HTTPS
    5. Has a registered service worker with a fetch event handler
    https://web.dev/install-criteria/#criteria
    PWA
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  37. Service Worker
    JavaScript snippet executed in an
    own thread, registered by the website
    Acts as a controller, proxy, or
    interceptor
    Has a cache to store responses (for
    offline availability and performance)
    Can wake up even when the website
    is closed and perform background
    tasks (e.g., push notifications or sync)
    PWA
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  38. Service Worker
    PWA
    Service
    Worker
    Internet
    Website
    HTML/JS
    Cache
    fetch
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  39. Blazor Service Worker
    The Blazor PWA template
    includes a custom service
    worker implementation
    All Blazor assets are precached
    by default
    Service Worker behavior can
    be modified (e.g., for push)
    à maximum flexibility
    PWA
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  40. Service Worker
    1. Start application with dotnet run or with Visual Studio
    2. Test in DevTools: F12 > Application > Service Worker
    3. Install the app: Address Bar > Install
    PWA
    EX #9
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  41. Push Notifications
    Just as native apps, PWAs can
    receive push notifications
    Combination of two technologies:
    Web Notifications and Push API
    Supported by Chrome, Edge,
    Firefox, Safari
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    PWA

    View full-size slide

  42. Service Worker Debugging
    More information on installed
    service workers can be found on
    • about://serviceworker-
    internals (Google Chrome)
    • about:serviceworkers
    (Mozilla Firefox)
    PWA
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  43. Service Worker Debugging
    PWA
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  44. Lighthouse
    PWA
    Auditing tool by Google,
    integrated in Chrome DevTools
    Automatically checks
    performance metrics, PWA
    support, accessibility, SEO and
    other best practices and gives
    tips on how to improve
    Can simulate mobile devices
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  45. Lighthouse
    1. Make sure only one tab/window of your PWA is open
    2. Open DevTools: F12 > Lighthouse
    3. Make sure to select at least the “Progressive Web App” category
    4. Click “Analyze page load”
    PWA
    EX #10
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  46. Paint PWA
    Capabilitie
    s
    Progressive
    Enhanceme
    nt
    Agenda
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  47. So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  48. Project Fugu
    Capabilities
    »Let’s bring the web
    back – API by API«
    Thomas Steiner, Google
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  49. Capabilities
    Contacts
    Picker
    Screen Wake
    Lock API
    File System
    Access API
    Shape
    Detection API
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  50. Capabilities
    https://goo.gle/fugu-api-tracker
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  51. Browser
    Capabilities
    navigator.share({ url: 'http://example.com' });
    ShareIntent DataTransferManager

    NSSharingServicePicker
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  52. File System Access API
    Some applications heavily rely
    on working with files (e.g.
    Visual Studio Code, Adobe
    Photoshop, …)
    File System Access API allows
    you to open, save and override
    files and directories
    Supported by Chrome, Edge
    Capabilities
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  53. File System Access API
    1. Add the following buttons to the bar in Index.razor (before the color input):
    Open
    Save
    Copy
    Paste
    Share
    Capabilities
    EX #11
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  54. File System Access API
    2. Add the following lines at the top of Index.razor.cs:
    private static FilePickerAcceptType[] _acceptTypes = new
    FilePickerAcceptType[]
    {
    new FilePickerAcceptType
    {
    Accept = new Dictionary {
    { "image/png", new[] {".png" } }
    },
    Description = "PNG files"
    }
    };
    Capabilities
    EX #11
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  55. File System Access API
    3. Add the following lines at the top of Index.razor.cs:
    private SaveFilePickerOptionsStartInWellKnownDirectory _savePickerOptions =
    new SaveFilePickerOptionsStartInWellKnownDirectory
    {
    StartIn = WellKnownDirectory.Pictures,
    Types = _acceptTypes
    };
    Capabilities
    EX #11
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  56. File System Access API
    4. Add the following lines in the method SaveLocalFile() of Index.razor.cs:
    [Inject] private IFileSystemAccessService _fileSystemAccessService
    { get; set; } = default!;
    if (_fileHandle == null)
    {
    _fileHandle = await _fileSystemAccessService
    .ShowSaveFilePickerAsync(_savePickerOptions);
    }
    Capabilities
    EX #11
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  57. File System Access API
    5. Add the following lines in the method SaveLocalFile() of Index.razor.cs:
    var writeable = await _fileHandle.CreateWritableAsync();
    var image = await _imageService.GetImageDataAsync(_PAINT_CANVAS);
    await writeable.WriteAsync(image);
    await writeable.CloseAsync();
    await _fileHandle.JSReference.DisposeAsync();
    _fileHandle = null;
    Capabilities
    EX #11
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  58. File System Access API
    1. Add the following lines at the top of Index.razor.cs:
    private readonly OpenFilePickerOptionsStartInWellKnownDirectory
    _filePickerOptions = new OpenFilePickerOptionsStartInWellKnownDirectory
    {
    Multiple = false,
    StartIn = WellKnownDirectory.Pictures,
    Types = _acceptTypes
    };
    Capabilities
    EX #12
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  59. File System Access API
    2. Add the following code int the method OpenLocalFile() of Index.razor.cs:
    try
    {
    var fileHandles = await
    _fileSystemAccessService.ShowOpenFilePickerAsync(_filePickerOptions);
    _fileHandle = fileHandles.Single();
    }
    catch (JSException ex)
    {
    Console.WriteLine(ex);
    }
    Capabilities
    EX #12
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  60. File System Access API
    3. Add the following code int the method OpenLocalFile() of Index.razor.cs:
    finally
    {
    if (_fileHandle is not null)
    {
    var file = await _fileHandle.GetFileAsync();
    await _imageService.OpenFileAccessAsync(file.JSReference);
    await using var context = await _canvas!.GetContext2DAsync();
    await context.DrawImageAsync("image", 0, 0);
    }
    }
    Capabilities
    EX #12
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  61. Async Clipboard API
    Allows reading from/writing to
    the clipboard in an
    asynchronous manner (UI won’t
    freeze during long-running
    operations)
    Reading from the clipboard
    requires user consent first
    (privacy!)
    Supported by Chrome, Edge,
    Safari and Firefox (plain-text
    only)
    Capabilities
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  62. Async Clipboard API
    Add the following code in the method Copy() of Index.razor.cs:
    var imagePromise = _asyncClipboardService.GetObjectReference(
    _module!, "getCanvasBlob", _PAINT_CANVAS);
    var clipboardItem = new ClipboardItem(
    new Dictionary
    {
    {_IMAGE_TYPE, imagePromise }
    });
    await _asyncClipboardService.WriteAsync(
    new[] { clipboardItem }
    );
    Capabilities
    EX #13
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  63. Async Clipboard API
    Add the following code in the method Paste() of Index.razor.cs:
    var clipboardItems = await _asyncClipboardService.ReadAsync();
    var pngItem = clipboardItems
    .FirstOrDefault(c => c.Types.Contains(_IMAGE_TYPE));
    if (pngItem is not null)
    {
    var blob = await pngItem.GetTypeAsync(_IMAGE_TYPE);
    await _imageService.OpenFileAccessAsync(blob);
    await using var context = await _canvas!.GetContext2DAsync();
    await context.DrawImageAsync(_IMAGE_ID, 0, 0);
    }
    Capabilities
    EX #14
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  64. Web Share API
    Allows sharing a title, URL, text, or
    files
    API can only be invoked as a
    result of a user action (i.e. a click
    or keypress)
    Supported by Chrome, Edge,
    Safari and Firefox (Android only)
    Capabilities
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  65. Web Share API
    Add the following code in the share() method in the Index.razor.cs:
    var fileReference = await _imageService.GenerateFileReferenceAsync(
    await _canvas!.ToDataURLAsync());
    await _shareService.ShareAsync(
    new WebShareDataModel
    {
    Files = new[] { fileReference }
    });
    Capabilities
    EX #15
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  66. File System Handling API
    Register your PWA as a
    handler for file extensions
    Requires installing the
    application first
    Declare supported extensions
    in Web App Manifest and add
    imperative code to your
    application logic
    Capabilities
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  67. File System Handling API
    1. Add the following property to your manifest (wwwroot/manifest.json):
    "file_handlers": [{
    "action": "./",
    "accept": {
    "image/png": [".png"]
    }
    }]
    Capabilities
    EX #16
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  68. File System Handling API
    2. Add the following code to the Index.razor.js file at row 23:
    export function initializeLaunchQueue(component) {
    if ('launchQueue' in window) {
    window.launchQueue.setConsumer(async params => {
    const [handle] = params.files;
    if (handle) {
    const file = await handle.getFile();
    await createImageElement(file);
    component.invokeMethodAsync('DrawImageAsync');
    }
    });
    }
    }
    Capabilities
    EX #16
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  69. File System Handling API
    3. Add the following code to method OnAfterRenderAsync in the Index.razor.cs file:
    _selfReference = DotNetObjectReference.Create(this);
    if (_module == null)
    {
    _module = await JS.InvokeAsync("import", "./Pages/Index.razor.js");
    }
    await _module.InvokeVoidAsync("initializeLaunchQueue", _selfReference);
    Capabilities
    EX #16
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  70. File System Handling API
    4. Add the following code to the method DrawImageAsync in the Index.razor.cs file:
    [JSInvokable]
    public async Task DrawImageAsync()
    {
    await using var context = await _canvas!.GetContext2DAsync();
    await context.DrawImageAsync("image", 0, 0);
    }
    Capabilities
    EX #16
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  71. Paint PWA
    Capabilitie
    s
    Progressive
    Enhanceme
    nt
    Agenda
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  72. Overview
    Use available interfaces and functions of
    a system (opposite of Graceful
    Degradation)
    Users with modern, feature-rich
    browsers get a better experience
    Apps are available on older browsers, but
    with limited functionality
    Concept: Browser feature support should
    grow over time—thereby more users can
    enjoy an increasing number of features
    Progressive Enhancement
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  73. Overview
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register(…)
    .then(() => /* … */);
    }
    In JavaScript: check whether an API/feature is available. If yes—use it!
    Otherwise:
    1. Disable the functionality
    2. Fall back to an alternative API (if available)
    Progressive Enhancement
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  74. Disabling unsupported features
    In Index.razor.cs, hide the buttons in case the respective API does not exist, e.g.:
    _fileSystemAccessSupported = await _fileSystemAccessService.IsSupportedAsync();
    And hide the buttons which are not supported in the Index.razor, e.g.:
    @if(_fileSystemAccessSupported) {
    Open
    Save
    } else {

    Download
    }
    Progressive Enhancement
    EX #17
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  75. Disabling unsupported features
    1. Copy: await _asyncClipboardService.IsSupportedAsync();
    2. Paste: await _asyncClipboardService.IsSupportedAsync();
    3. Share: await _shareService.IsSupportedAsync();
    Progressive Enhancement
    EX #17
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  76. Disabling unsupported features
    Add the following code to the method OnInitializedAsync in the Index.razor.cs file:
    _fileSystemAccessSupported = await _fileSystemAccessService.IsSupportedAsync();
    _clipboardApiSupported = await _asyncClipboardService.IsSupportedAsync();
    _shareApiSupported = await _shareService.IsSupportedAsync();
    Progressive Enhancement
    EX #17
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  77. Disabling unsupported features
    Replace the following code to the Index.razor file:
    Copy
    Paste
    Share
    Progressive Enhancement
    EX #17
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  78. Providing an alternative implementation
    If the feature are not supported, fall back to the following code for the DownloadFile()
    Method:
    await _imageService.DownloadAsync(await _canvas!.ToDataURLAsync());
    Progressive Enhancement
    EX #18
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  79. Providing an alternative implementation
    If the feature are not supported, fall back to the following code for the OpenFile()
    Method:
    await using var context = await _canvas!.GetContext2DAsync();
    await _imageService.OpenAsync(args.File.OpenReadStream(1024 * 15 * 1000));
    await context.DrawImageAsync("image", 0, 0);
    Progressive Enhancement
    EX #19
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  80. – Productivity apps
    – IDEs, code editors
    – Video editors
    – Image editors
    – Office applications
    – Document editors
    – Presentation apps
    – Enterprise applications
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    Use Cases

    View full-size slide

  81. Spotify
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    Use Cases
    https://open.spotify.com/

    View full-size slide

  82. VS Code
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    Use Cases
    https://vscode.dev/

    View full-size slide

  83. Photoshop
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    Use Cases
    https://photoshop.adobe.com/

    View full-size slide

  84. PWA
    – Installation may not be obvious
    – Only web platform APIs can be called
    – Antivirus software or cloud sync agents can’t be implemented
    – Some APIs may not be available on all browsers and OS’s
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    Limitations

    View full-size slide

  85. Blazor
    – C#, but knowledge of HTML, CSS and JS will still be required
    – Rider support is not great
    – Caching can lead to confusion while testing
    – Very large bundles = high initial loading time (mobile users!)
    – Blazor WebAssembly: 2 MB (without culture info)
    – Angular: 50 kB
    – Firewalls may block the transfer of DLL files
    – Summary: Maybe not the best solution for B2C apps where the
    environment cannot be controlled
    Progressive Web Apps mit Blazor
    So bringen Sie Ihre .NET-App ins Web!
    Limitations

    View full-size slide

  86. Blazor: Reuse your existing C# and .NET knowledge and implement great
    applications that run just fine in the browser and all relevant OS’s
    PWA: Improve the experience by allowing users to install your app and
    run it offline
    Fugu: Add capabilities for an even deeper integration with the OS using
    C#-based NuGet packages
    Progressive Enhancement: Ensure that users of older or less powerful
    browsers can still use the app
    Let’s build great apps for the web!
    Summary
    So bringen Sie Ihre .NET-App ins Web!
    Progressive Web Apps mit Blazor

    View full-size slide

  87. Thank you
    for your kind attention!
    Christian Liebel
    @christianliebel
    [email protected]
    https://www.thinktecture.com/ueber-uns/karriere/
    Patrick Jahr
    @jahr_patrick
    [email protected]

    View full-size slide