| layout | default |
|---|---|
| title | v0.17.0 |
| description | Release notes for Neatoo RemoteFactory v0.17.0 |
| parent | Release Notes |
| nav_order | 2 |
Release Date: 2026-03-06 NuGet: Neatoo.RemoteFactory 0.17.0
Adds internal factory method visibility as the signal for client/server separation and IL trimming. Factory methods marked internal get IsServerRuntime guards (trimmable, server-only), while public methods run locally without guards. This keeps business logic off the client, reduces bundle size, and hides child entity factories from client code.
Use public vs internal on factory methods to control where they execute:
| Pattern | Meaning | Generator behavior |
|---|---|---|
[Remote] public |
Client calls it, routes to server | Remote/Local delegate fork (existing) |
public (no Remote) |
Client calls it, runs locally | No IsServerRuntime guard |
internal (no Remote) |
Server-only, within aggregate | Gets IsServerRuntime guard, trimmable |
The generated factory interface visibility is now determined by the methods:
- All methods internal -- factory interface is
internal(child entity factories hidden from client) - Any public method -- factory interface is
public(internal methods included withinternalmodifier)
Entity classes are recommended as internal with a matched public interface:
public interface IOrder : IFactorySaveMeta { /* public surface */ }
[Factory]
internal partial class Order : IOrder
{
[Create] [Remote]
public void Create() { } // Client-callable, routes to server
[Fetch] [Remote]
public void Fetch(int id, [Service] IOrderRepository repo) { }
}The generator detects matching interfaces by naming convention (Order -> IOrder) and uses the interface type in factory signatures.
NeatooRuntime.IsServerRuntime is now a [FeatureSwitchDefinition] feature switch. When set to false on the client:
internalfactory methods are guarded and removed by the IL trimmerpublicfactory methods survive trimming and work locally- Server-only dependencies (Entity Framework, etc.) are trimmed from the client bundle
[Remote] internal is a contradiction (remote = client entry point, internal = server-only) and now emits diagnostic error NF0105.
Minimum supported framework is now .NET 9. Remove net8.0 from TargetFrameworks if present.
Previously, ALL Local* methods had IsServerRuntime guards. Now only internal and [Remote] methods get guards. public non-[Remote] methods (like Can* and Create) no longer have guards and execute locally on the client.
This is only breaking if you relied on IsServerRuntime=false to block ALL local method execution. The new behavior is correct: public methods should work on the client.
None
This is opt-in. Existing public classes continue to work.
-
Add a public interface matching the class name:
public interface IOrder : IFactorySaveMeta { /* properties/methods clients need */ }
-
Make the class internal and implement the interface:
[Factory] internal partial class Order : IOrder { }
-
Update references from
OrdertoIOrderin client code and DI registration:// Program.cs builder.Services.AddNeatoo(typeof(IOrder).Assembly);
Child entity factory methods (called within aggregate operations, not from the client) should be internal:
[Factory]
internal partial class OrderLine : IOrderLine
{
[Create]
internal void Create() { } // Server-only, within aggregate
}This makes IOrderLineFactory internal (hidden from client DI) and enables IL trimming.
a277ff5- feat: add IL trimming support for Blazor WASMf1ed63e- feat!: drop .NET 8 support, minimum is now .NET 9ea3efd7- feat!: add IL trimming support via feature switch guards5dbdd67- docs: add exploration todo for IL trimming feature switchesd45556b- chore: upgrade all NuGet packages to latest versions