
Skill
maui-blazor-hybrid
build and debug MAUI Blazor Hybrid apps
Description
Build and debug .NET MAUI Blazor Hybrid features with BlazorWebView, HybridWebView, Razor components, static assets, JS/.NET interop, trimming/NativeAOT concerns, and DevFlow CDP route inspection. USE FOR: MAUI apps hosting Razor UI, embedded HTML/JS, choosing BlazorWebView vs HybridWebView, AddMauiBlazorWebView, RootComponent, SendRawMessage/RawMessageReceived, JSON DTO contracts, JsonSerializerContext, wwwroot assets, hybrid auth/data handoff, stale DOM/Razor route debugging, and maui_cdp_webviews/source/evaluate/screenshot/logs. DO NOT USE FOR: pure XAML UI or browser-only apps.
SKILL.md
MAUI Blazor Hybrid
Use this skill when a MAUI app hosts Razor components or an embedded web surface inside a native app.
Workflow
- Inspect
MauiProgram.cs,.razorfiles,wwwroot, and XAML pages that hostBlazorWebVieworHybridWebView. - Choose the right host:
BlazorWebViewfor Razor components rendered inside MAUI.HybridWebViewfor HTML/JavaScript content that exchanges messages with .NET without using the Blazor component model.
- Register Blazor Hybrid services in
MauiProgram.cs. - Keep native services in MAUI DI and consume them from Razor through DI.
- Put static web assets under
wwwrootor referenced Razor class libraries. - Use JS/.NET interop through documented APIs, not platform WebView internals.
For
HybridWebViewraw messaging, always showSendRawMessage,RawMessageReceived, a JSON DTO contract, and a source-generatedJsonSerializerContext/System.Text.Jsonpath when trimming, NativeAOT, Release trimming, or trimming-safe messaging is part of the request. Do not answer with only raw strings orDynamicDependency. - Review trimming and NativeAOT risks for reflection, serialization, and JS interop payloads.
- Use DevFlow CDP tools to inspect WebView DOM, console logs, CDP screenshots,
and route state when debugging. For Blazor Hybrid stale route/DOM answers,
explicitly name
maui_cdp_webviews,maui_cdp_sourceormaui_cdp_evaluate, and at least one evidence tool:maui_cdp_screenshotormaui_logs.
BlazorWebView Pattern
builder.Services.AddMauiBlazorWebView();
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Routes}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
Razor components can inject MAUI services registered in the same DI container.
Keep platform work behind interfaces so components remain testable. The root
component type depends on the template; newer templates often use Routes,
while older templates may use Main.
HybridWebView Pattern
Use HybridWebView when the app owns an HTML/JS surface and needs message
exchange. For raw JS/.NET messaging answers, include both the raw message APIs
and a typed JSON DTO/source-generated serialization boundary:
hybridWebView.SendRawMessage("refresh");
hybridWebView.RawMessageReceived += OnRawMessageReceived;
For non-trivial or trimming-sensitive payloads, keep messages typed at the .NET
boundary instead of switching on ad-hoc strings. Use a DTO plus System.Text.Json
source generation ([JsonSerializable] and JsonSerializerContext) so
serialization stays trimming/NativeAOT friendly:
public sealed record HybridMessage(string Action, string? Id);
[JsonSerializable(typeof(HybridMessage))]
internal sealed partial class HybridJsonContext : JsonSerializerContext
{
}
void OnRawMessageReceived(object? sender, HybridWebViewRawMessageReceivedEventArgs e)
{
var message = JsonSerializer.Deserialize(
e.Message,
HybridJsonContext.Default.HybridMessage);
if (message is null)
throw new JsonException("Malformed HybridWebView message.");
// Dispatch only known actions after validating authorization/state.
}
hybridWebView.SendRawMessage(JsonSerializer.Serialize(
new HybridMessage("refresh", null),
HybridJsonContext.Default.HybridMessage));
window.HybridWebView.SendRawMessage(JSON.stringify({
action: "save",
id: "42"
}));
Static Assets
- Put app-owned web files under
wwwroot. - Use
_content/{PackageId}/...for static web assets from Razor class libraries. - Avoid file-system paths that only work on one platform.
- Ensure CSP, local scripts, and asset paths work from the packaged app origin, not just from a development server.
Interop and State
- Use
IJSRuntimefrom Razor components for Blazor JS interop. - Use
HybridWebViewmessaging APIs for non-Blazor HTML/JS content. - Dispose
DotNetObjectReferenceinstances when Razor components are disposed to avoid leaking component instances through JavaScript references. - Keep auth/session/data services native-side and expose only the minimal state needed by Razor or JavaScript.
- Do not put long-lived secrets in browser local storage.
- Validate
RawMessageReceivedpayloads against an expected schema before dispatching to .NET logic. Do not let raw messages trigger sensitive operations without authorization checks at the .NET receiver.
Trimming and NativeAOT Guardrails
- Prefer
System.Text.Jsonsource-generated contexts for interop DTOs. - Avoid reflection-based component discovery or dynamic serialization unless annotations/preservation are added.
- Test release builds because debug WebView behavior can hide trimming issues.
- Check third-party JS/.NET interop packages for trimming support.
DevFlow CDP Debugging
When DevFlow is enabled, use WebView CDP tools to debug cross-route behavior:
maui devflow mcp
Blazor WebView developer tools and platform WebView debugging must be enabled only in debug builds:
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
#endif
Relevant MCP tools include maui_cdp_webviews, maui_cdp_source,
maui_cdp_evaluate, maui_cdp_screenshot, and maui_logs. Inspect the active
WebView before evaluating route-specific DOM or JavaScript. When the issue is
stale Blazor route state or DOM, include maui_cdp_screenshot for WebView
visual evidence and/or maui_logs for Blazor rendering or WebView console
errors; do not substitute only the generic app-level maui_screenshot for CDP
WebView evidence. Do not ship release builds with WebView devtools or CDP access
enabled.
Validation Checklist
AddMauiBlazorWebViewis registered for Blazor Hybrid apps.- Static assets resolve from packaged
wwwrootor RCL_contentpaths. - JS/.NET interop uses Blazor or HybridWebView APIs intentionally.
- HybridWebView raw messages use JSON DTOs plus
JsonSerializerContextor another explicitSystem.Text.Jsonsource-generated path when trimming-safe serialization matters. - Release/trimming-sensitive code avoids unpreserved reflection.
- DevFlow CDP inspection targets the correct WebView and route, and route/DOM
debugging guidance names
maui_cdp_screenshotormaui_logsfor evidence.
More skills from the maui-labs repository
View all 32 skillsandroid-slim-bindings
create Android slim bindings for .NET
Jul 12.NETAndroidJavaKotlin +1devflow-automation
automate .NET MAUI app state
Jul 12.NETAutomationMAUIMobiledevflow-connect
diagnose DevFlow agent connectivity issues
Jul 12DebuggingMAUINetworkingdotnet-workload-info
discover MAUI workload metadata
Jul 12C#CLIEngineeringMAUIios-slim-bindings
create iOS slim bindings for MAUI
Jul 12.NETiOSMAUISwift +1maui-accessibility
implement accessibility in .NET MAUI apps
Jul 12.NETAccessibilityMAUIMobile +1
More from .NET (Microsoft)
View publishermultithreaded-task-migration
migrate MSBuild tasks to multithreaded mode
msbuild
Jul 22.NETEngineeringPerformanceanalyzing-dotnet-performance
analyze .NET code for performance anti-patterns
skills
Jul 12.NETCode AnalysisDebuggingPerformanceandroid-tombstone-symbolication
symbolicate .NET runtime frames in Android tombstones
skills
Jul 12.NETAndroidDebuggingMicrosoftapple-crash-symbolication
symbolicate .NET runtime frames in crash logs
skills
Jul 12.NETDebuggingiOSmacOS +1assertion-quality
evaluate assertion quality in test suites
skills
Jul 12Code AnalysisQATestingauthor-component
create and review Blazor components
skills
Jul 15.NETBlazorC#UI Components +1