Support Native AOT and full trimming in Blazor
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 15/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- csharp
- Domain
- backend, full-stack
Research direction
Start by reading the proposed solution and its acceptance scenarios; the issue does not identify implementation files or tests. The work spans Razor generation, serialization, discovery, component runtime, forms, and multiple hosts, with some API design still open. Done means supported scenarios publish and run with Native AOT and full trimming without warnings or reflection fallbacks, while the compatibility path remains intact.
Written by the indexing model from the issue text.
Description
Summary
This feature enables Blazor applications to publish and run with Native AOT and full trimming across the supported application model, without relying on reflection-based discovery or runtime code generation. It makes native deployment practical and creates opportunities to reduce startup, application size, memory use, and repeated runtime work.
The work introduces composable application and library metadata, build-time generation through Razor, and trim-safe contracts for serialization and form mapping. Component execution, routing, JavaScript interop, persistence, binding, and forms consume the resulting capabilities. Existing applications retain a supported compatibility path, while strict applications get explicit diagnostics rather than silent reflection fallbacks.
Goals
-
Make Native AOT and full trimming usable without removing supported functionality. Representative applications must publish with zero trimming and ILC warnings and exercise their claimed scenarios without framework reflection fallbacks, runtime code generation, broad warning suppressions, or substitutions that remove those scenarios.
-
Make application and library contributions composable. Applications, framework assemblies, and component libraries must supply the definitions their features need. Hosts and consumers must use the appropriate selected application without requiring HTTP endpoint mapping, repeated assembly scanning, or application-side reconstruction of library internals.
-
Make framework serialization and form mapping trim-safe. Generated contracts must support form-data reading, .NET-to-.NET state serialization, and .NET-to-JavaScript interop with the distinct behavior each boundary requires. Supported customization must work without reflection-based contract discovery or runtime code generation.
-
Preserve an undegraded upgrade experience. Existing applications and libraries must continue to work without additional warnings or required AOT-related changes when upgrading without enabling additional AOT features or checks. Applications choosing strict execution must receive actionable errors for missing definitions and unsupported shapes instead of discovering incomplete support after deployment.
Non-goals
-
Require every existing application to adopt Native AOT. Applications that do not enable additional AOT features or checks retain their existing supported experience without degradation. Upgrading alone must not introduce additional warnings or require AOT-related application changes.
-
Support unrestricted runtime discovery in strict execution. Types and behavior required at runtime must have AOT-compatible definitions. Missing definitions produce actionable diagnostics rather than reflection fallbacks.
Proposed solution
Provide generated definitions for Blazor features that currently depend on runtime discovery or dynamically constructed accessors. Framework consumers use those definitions to support Native AOT and full trimming while preserving supported application behavior.
Razor owns Blazor generation across .razor and .cs inputs. Libraries contribute their own definitions, which compose with application definitions into a host-neutral application model. Consumers retrieve the features they need without scanning assemblies or reconstructing library internals. Generic metadata templates allow consumers to obtain definitions for statically known constructed types.
The work covers four areas:
-
Serialization. Provide trim-safe contracts for form-data reading, component descriptors, persisted values, and JavaScript interop. Preserve the distinct conversion, customization, and error behavior of each boundary.
-
Discovery. Supply definitions for components, routes, root-component mappings, component-associated metadata, JS-invokable methods, and persistent-service members. Root-component descriptors resolve through known mappings; JS-invokable methods use generated invocation support, including asynchronous completion.
-
Component runtime. Provide generated support for component construction, injection, and ordinary and cascading parameter assignment. Integrate the query-string, form, persistent-state, session, and TempData suppliers while preserving their individual delivery and lifecycle semantics.
-
Forms and binding. Provide attribute-value conversion and binding-target metadata without runtime converter discovery or expression inspection. Preserve value delivery and callbacks, field identity, submitted field paths, display names, and integration with existing validation.
Runtime decisions remain supported when they select definitions available ahead of time. A root parameter declared as Person, for example, may carry an Employee. Applications must be able to declare additional concrete root-parameter types that generation cannot otherwise establish, so their serialization definitions and descriptor mappings are available. The declaration's final API remains to be designed.
Component types must be public for the strict generated experience. Supported internal-member access includes injection and cascading-parameter delivery. Missing definitions and unsupported shapes produce actionable diagnostics rather than silent reflection fallbacks.
Applications upgrading without enabling additional AOT features or checks retain their supported experience without additional warnings or required AOT-related changes. Generation and strict execution are introduced without degrading that compatibility path.
The following scenarios define the intended experience. Existing entry points are illustrative; unapproved new API signatures are deliberately not invented.
Publish an ordinary Blazor application with Native AOT
The application uses its normal component and host setup, then publishes for a supported native target:
dotnet publish -c Release -r linux-x64 -p:PublishAot=true
Its supported component, routing, interop, binding, persistence, and form scenarios execute correctly with the necessary generated definitions. Native publication produces no trimming or ILC warnings; removing functionality to satisfy that condition does not meet the requirement.
Compose a component library without reproducing its internals
An application references a Razor class library and uses its components through the normal Razor experience. Component types must be public for the strict generated experience; internal members remain supported for injection and cascading-value/parameter delivery. The library supplies its own definitions, and the application does not maintain a second description of those members or scan the library at runtime in strict execution.
Repeated references to the same contributing library do not duplicate it. Different contributions that conflict are handled by a documented, deterministic policy rather than accidental registration order.
Configure features and consume the same application in different hosts
An application continues to use host configuration such as:
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
The host extension can contribute or modify the relevant library features before finalization. Endpoint consumers, interactive routing, and non-HTTP rendering retrieve the features they need without introducing HTTP dependencies into Components core.
Separate mapped applications retain separate definitions. The selected application remains correct when work enters an Interactive Server circuit or a WebView page scope; an unrelated mapping or service provider must not replace it.
Persist and restore application values
An application persists component or service state using supported framework APIs. Generated definitions cover the application values, and the framework can serialize and restore them without runtime type discovery.
Using generated serialization preserves the supported persistence and restoration behavior, including compatibility requirements for data that outlives a deployment.
Use JavaScript interop with framework-owned values
Existing supported interop operations, including JavaScript-invokable methods and asynchronous results, execute without reflection-based method discovery or runtime generic construction. Element references, object references, streams, byte arrays, custom event values, and dynamic component parameters retain their supported behavior.
Generated contracts for an application object containing an ElementReference or JS object reference use the framework's handling of those values. Supported custom serialization must have an explicit AOT-compatible integration rather than depend on runtime member discovery.
Read a complex submitted form
An existing Minimal API retains its form-bound handler shape, and a static SSR component retains its named form and SupplyParameterFromForm receiver. After adoption of the new contracts, generated form reading supports the required object construction, nested values, collections, files, conversion, limits, and mapping errors without runtime code generation.
Generated form-data contracts preserve the supported customization, conversion, culture, file, and error behavior of the adopted form-data API.
Explicit C# form contexts and Razor-discovered form roots produce the same supported contracts. The existing C#-only prototype increment does not, by itself, complete actual Razor integration or whole-Blazor Native AOT support.
Diagnose an incomplete strict application
A required component definition, closed generic usage, interop method, or serialization/form contract is missing or unsupported. Statically knowable failures identify the affected type/member and corrective action during the build; unresolved runtime cases fail explicitly before an invalid operation can appear successful.
Strict execution never silently switches to reflection. Custom extensions are responsible for their own AOT compatibility; the framework does not promise to prove arbitrary developer code reflection-free.
Adopt the changes without breaking an existing application
An application that upgrades without enabling additional AOT features or checks retains its supported reflection-compatible experience without degradation, additional warnings, or required AOT-related code or configuration changes. Validation compares its build and publish diagnostics before and after the upgrade; warnings must not be added merely because the new framework contains AOT support.
Applications opting into additional AOT features or checks receive the corresponding diagnostics. Adoption documentation explains generated-contract requirements, supported customization, library compatibility, and any intentional behavior changes on that opt-in path.
Generated and compatibility execution preserve the supported semantics for the same adopted contracts. Shared behavior remains correct across applicable Server, WebAssembly, WebView, static SSR, and non-HTTP scenarios; the native deployment acceptance suite uses supported native hosts.
- Dominant language
- C#
- Stars
- 38.5k
- Forks
- 11.6k
- Avg merge
- 3d 1h
- Merged PRs (30d)
- 289
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from dotnet/aspnetcore
-
area-networking
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
dotnet/aspnetcore#70545 · 1 comment ·
Maintainers usually reply within 1 day
-
area-infrastructure
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
dotnet/aspnetcore#70524 · 1 comment ·
Maintainers usually reply within 1 day
-
[OpenTelemetry] Hosting replaces an Activity.DisplayName that the app set, when a route matchesOpenarea-hosting Regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
dotnet/aspnetcore#70516 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
-
[SSE] ServerSentEventsResult.WrapEvents is missing [EnumeratorCancellation], so RequestAborted never reaches the app's generator on the IAsyncEnumerable<T> overloadPossibly taken @bharatprajapati-coder claimed this 1 day ago. Openarea-minimal
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
dotnet/aspnetcore#70419 · 2 comments ·
Maintainers usually reply within 1 day
-
[Blazor] DefaultInMemoryCircuitPersistenceProvider never disposes the retention CancellationTokenSource when a persist is rejected at capacityPossibly taken @Vinoth2562000 claimed this 1 day ago. Openarea-blazor
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
dotnet/aspnetcore#70418 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
All issues in dotnet/aspnetcore
Similar issues
-
bug emitter:client:csharp
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
microsoft/typespec#12572 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
-
needs-area-label
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
-
AWS Lambda: KeyNotFoundException drops HTTP-triggered transactions when allowAllHeaders is disabledOpenbug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
newrelic/newrelic-dotnet-agent#3949 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 87/100
Maintainers usually reply within 1 day
-
priority:P2
Difficulty 2/5 1-3 hours Newbie friendliness 80/100