Skip to the content.

Part 13: Migration to Fusion 6.1+

Upgrade packages

1. Upgrade all Fusion package references to v6.1+.

2. Replace all references to Stl.Fusion.Client to Stl.Fusion - there is no separate client assembly in v6.1+, Stl.Fusion.dll contains the client.

3. If you are using Fusion authentication (e.g. IAuth, User, etc. - in fact, almost everything related to Fusion authentication except Session), reference:

4. If you are using some projects declaring just IXxxClientDef types, remove these projects.

5. Any project that declares compute or command services must reference Stl.Generators.

6. Any project that declares [MemoryPackable] types must reference MemoryPack.Generator.

Update compute/command services, commands, and other “wired” data types

1. Any compute service should implement IComputeService, any command service should implement ICommandService.

These interfaces are just tagging ones, i.e. there are no any methods. Stl.Generators analyzers require them to generate proxies for such services.

Most likely you declare interfaces for any of such services to consume them on the client - and in this case the interface must be inherited from either IComputeService or ICommandService.

2. Decorate any non-primitive type which “travels” between the client & server with MemoryPack serialization attributes and make them partial. E.g. if you had:

// In pre-v6.1 such commands are typically nested into IXxxService
public record PostCommand(string Name, string Text) : ICommand<Unit>;

You should convert it to ~ this:

// 1. MemoryPack doesn't support nested types, so it has to be moved out of IXxxService; Rider/ReSharper has a refactoring for this, as for VS.NET, I am not sure.
// 2. All `[MemoryPackable]` types must be declared as `partial`
// 3. [MemoryPackable(GenerateType.VersionTolerant)] requires you to explicitly mark every serializable member with [MemoryPackOrder]
// 4. [DataContract] and [DataMember] are optional - you may want to have them if you end up using e.g. MessagePack serializer
[DataContract, MemoryPackable(GenerateType.VersionTolerant)]
public partial record Chat_Post(
    [property: DataMember, MemoryPackOrder(0)] string Name,
    [property: DataMember, MemoryPackOrder(1)] string Text
    ) : ICommand<Unit>;

Note that any assembly which declares such types should reference MemoryPack.Generator package.

More details on MemoryPack serializer: https://github.com/Cysharp/MemoryPack

Remove compute service controllers and IXxxClientDef-s

Search and replace

Replace the following complete words:

Server-side changes

1. Remove old Fusion server setup logic.

2. Add the new one:

var fusion = services.AddFusion(RpcServiceMode.Server, true);
var fusionServer = fusion.AddWebServer();

The first line tells that any FusionBuilder (including fusion) we’ll use further must publish any service registered via AddService call via Stl.Rpc - in other words, it “turns” any AddService call to AddServer call further.

The second call registers an RPC endpoint (/rpc/ws) and maps it to a WebSocket server from Stl.Rpc.Server package.

3. If you’re using Fusion authentication, configure its endpoints like this:

fusionServer.ConfigureAuthEndpoint(_ => new() {
    DefaultScheme = MicrosoftAccountDefaults.AuthenticationScheme,
    SignInPropertiesBuilder = (_, properties) => {
        properties.IsPersistent = true;
    }
});
fusionServer.ConfigureServerAuthHelper(_ => new() {
    NameClaimKeys = Array.Empty<string>(),
});

4. If you’re using ASP.NET Core Minimal API, map additional endpoints:

endpoints.MapRpcWebSocketServer(); // Absolutely necessary
endpoints.MapFusionAuth(); // Optional - maps /signIn & /signOut endpoints
endpoints.MapFusionBlazorMode(); // Optional - maps /fusion/blazorMode/{isBlazorServer}

And if you prefer to use controllers for Fusion authentication & Blazor mode switch, add this instead:

fusionServer.AddMvc().AddControllers();

For the note, these controllers now call the same services as endpoints, i.e. performance-wise endpoints are slightly better.

5. If you’re using DbAuthService, its server-side builder is now invoked differently.

It used to be called like this:

db.AddAuthentication<...>();

And now it has to be:

fusion.AddDbAuthService<AppDbContext, ...>();

6. If you’re using fusionAuth.js script to open sign-in/sign-out popup in Blazor, update its location:

As you might notice, this also means you need to reference Stl.Fusion.Blazor.Authentication package.

Client-side changes

1. You must remove the old RestEase client. Search for fusion.AddRestEaseClient( and remove this call + any uses of its output except the ones w/ AddReplicaService call.

E.g. if you had this code:

var fusionClient = fusion.AddRestEaseClient();
fusionClient.ConfigureHttpClient((c, name, options) => {
    options.HttpClientActions.Add(client => client.BaseAddress = apiBaseUri);
});
fusionClient.ConfigureWebSocketChannel(c => new () {
    BaseUri = baseUri,
});
// Registering replica service
fusionClient.AddReplicaService<ICounterService, ICounterClientDef>();

Leave just this (we’ll update it later):

fusionClient.AddReplicaService<ICounterService, ICounterClientDef>();

Finally, replace fusionClient.AddReplicaService<TInterface, TClientDef>() calls with fusion.AddClient<TInterface>().

You can do this in two steps:

  1. Replace fusionClient.AddReplicaService with fusion.AddClient
  2. Remove the extra argument.

2. Add new Stl.Rpc WebSocket client:

fusion.Rpc.AddWebSocketClient(builder.HostEnvironment.BaseAddress);

3. If you are using Fusion authentication, add IAuth service client:

fusion.AddAuthClient();

1. If you’re using Fusion authentication, reference Stl.Fusion.Blazor.Authentication package. The authentication components are optional now, so they’re extracted to dedicated assemblies.

2. To add Fusion’s Blazor components / integrations, run the following calls:

var fusionBlazor = fusion.AddBlazor(); 

// Optional calls:

// If you're going to use Fusion's AuthenticationStateProvider, add the following call:
fusionBlazor.AddAuthentication(); // Must go somewhere after services.AddServerSideBlazor() on the server side!

// If you'd like to automatically bump up SessionInfo.LastSeenAt while the client uses Session:
fusionBlazor.AddPresenceReporter();

These calls must be executed:

3. If you are using <CascadingAuthState>, you can make it to automatically start presence reporter like this now:

<CascadingAuthState UsePresenceReporter="true">
  ...
</CascadingAuthState>

Other changes

1. Authentication and other optional extensions were moved to Stl.Fusion.Ext.Contracts and Stl.Fusion.Ext.Services packages - with corresponding namespace changes. So most likely you’ll need to replace:

2. TaskSource<T> type is gone (its performance was arguable). Use TaskCompletionSource<T> instead. You can use TaskCompletionSourceExt.New instead of TaskSource.New - it behaves identically, but returns similarly configured TaskCompletionSource instead of TaskSource.

Next: Epilogue » | Tutorial Home