Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor Hybrid: Reuse Razor components topic #25675

Closed
guardrex opened this issue Apr 19, 2022 · 4 comments · Fixed by #25847
Closed

Blazor Hybrid: Reuse Razor components topic #25675

guardrex opened this issue Apr 19, 2022 · 4 comments · Fixed by #25847

Comments

@guardrex
Copy link
Collaborator

guardrex commented Apr 19, 2022

When content is provided in an issue comment here, please remove the PU member assignment and assign the issue to @guardrex 🦖. PU member will be pinged on the PR when it goes up.

aspnetcore/blazor/hybrid/reuse-razor-components.md

NOTE TO SELF:

This (referring to the Access native platform features topic topic) is covered by the section Platform specific code on Blazor Maui applications in this [PR].

@javiercn
Copy link
Member

Content is here

How to author Blazor components for the web and webview

Blazor runs in multiple environments or hosts; Webassembly, Server and Webview. Each host has unique capabilities in the framework and in the platform that components can leverage, but that can come at the cost of not working well in other hosts.

For example, Blazor webassembly supports synchronous interop which is not supported in other hosts like server or webview as the communication channel between JavaScript and .NET is strictly asynchronous. Another example can be how a component in Blazor Server can access services that are only available on the server, like entity framework DbContext. Much in the same way, a component in Blazor Webview can access funcionality on the device it is running like the geolocation or other native functionality offered by the platform that Blazor Server and Webassembly have to rely on the web interfaces to get access to.

Common patterns

In order to author components that can seamlessly work across different hosts we need to follow some design principles to make it easier for us to adapt those components to each specific host.

  • Shared UI code belongs in Razor Class Libraries: These are designed to be containers of reusable pieces of UI across different targets.
  • Platform specific functionality should not live in the Razor Class Library. Instead, the Razor Class Library should define abstractions (intefaces, base classes) that different target platforms (your web, native app, etc) should provide an implementation for.
  • Enhanced functionality should be opt-in. For example, it is ok to use IJsInProcessRuntime in a component as an optimization, but you should do so by doing a conditional cast and offering a fallback implementation that relies on the most basic and common IJSRuntime abstraction that all platforms support.
  • As a general rule, styling should be done via CSS. The most common case is for the look and feel of the application to be largely the same across different platforms. In places where it needs to be different it is best to use CSS if possible.
  • If some part of the UI needs to include additional or different content in a target platform the additional content can be encapsulated inside a component and rendered inside the class library using DynamicComponent.
  • Additional UI can also be provided to components via RenderFragment instances.

Code organization in projects

As much as possible the code and static content should be inside a Razor Class Library. Each target platform (Webassembly, Server, Webview) references the Razor Class Library and registers on the DI container implementations specific for that platform that a component might require.

Each target platform assembly should contain only the code that is specific to that platform and the code that helps boostrap the application.

flowchart LR
    Webassembly & Server & Webview -- ProjectReference --> RCL
Loading

Abstract platform speicific functionality

flowchart RL
   subgraph RCL
     A["MapComponent"] -.Injects.-> B
     B[ILocationService] 
   end
   subgraph Web ["App.Web (webassembly & Server)"]
      C["WebLocationService : ILocationService"] -- Implements --> B
   end
   subgraph Native ["App.Desktop (Maui, WPF, WindowsForms)"]
      D["DesktopLocationService : ILocationService"] -- Implements --> B
   end
Loading

Platform specific code on Blazor Maui applications

A very common pattern in Maui involves having different implementations for different platforms following several patterns like defining partial classes with platform specific implementations. For example:

flowchart TD
  subgraph CameraService.cs
    A[partial class CameraService]
  end
  subgraph CameraService.Android.cs
    B[partial class CameraService]
  end
  subgraph CameraService.iOS.cs
    C[partial class CameraService]
  end
  subgraph CameraService.Windows.cs
    D[partial class CameraService]
  end
Loading

In these cases, where you want to pack the functionality in a class library that can be consumed by other applications using Maui Blazor, we recommend you follow a similar approach to the one described above and create an abstraction for your component and put it in a Razor Class Library. Then on a Maui Class Library, reference the Razor Class Library and create your platform specific implementations. Finally, within the consuming application, reference the Maui Class Library.

flowchart
    subgraph RCL ["Razor Class Library"]
      A["ICameraService"]
      F["InputPhoto"] -- Injects --> A
    end
    subgraph MCL ["Maui Class Library"]
      B["partial CameraService.Android.cs"] -- Implements --> A
      D["partial CameraService.Windows.cs"] -- Implements --> A
      E["partial CameraService.IOS.cs"] -- Implements --> A
    end
    subgraph MBA ["Maui Blazor Application"]
        Main -- Uses --> F
    end
    MBA --> MCL
    MCL --> RCL
Loading

@javiercn
Copy link
Member

We should point out to the Podcasts sample

@guardrex guardrex assigned guardrex and unassigned javiercn May 11, 2022
@guardrex guardrex changed the title Blazor Hybrid: Reuse web components topic Blazor Hybrid: Reuse Razor components topic May 12, 2022
@guardrex
Copy link
Collaborator Author

guardrex commented May 12, 2022

@javiercn ... I need the link to the podcast that you mentioned ☝️ ... or to just the sample if that's what you want.

@javiercn
Copy link
Member

javiercn commented May 12, 2022

@guardrex it's not a podcast, it's a sample app that does web, maui and maui-blazor https://github.com/microsoft/dotnet-podcasts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants