Skip to content

Migration Guide: .NET Application to .NET 8

1. Migrate .NET Application to .NET 8

Ensure you have the .NET SDK for version 8 installed

Update your project file(s) to reference .NET 8

  • Open your project file (.csproj) and change the TargetFramework attribute to net8.0:
xml
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>
</Project>

Remove global.json files

  • If there is a global.json file specifying a specific SDK version, either update it to the new version or remove it.

Verify that your existing code compiles and runs

  • Run dotnet build and dotnet run to ensure that the application compiles and works correctly with .NET 8.

2. Migrate Akka.NET

Install Akka.Hosting

  • Add the Akka.Hosting package to your project:
bash
dotnet add package Akka.Hosting

Remove references to Autofac DI bootstraps in HubtelActorASystem

  • Remove any code that uses Autofac for dependency injection in your Akka.NET setup.

Migrate contents of Top Level Actor to use Akka Hosting

  • Configure your actors using Akka.Hosting. Here is an example setup:
csharp
using Akka.Hosting;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

var actorSystemName = Regex.Replace(Assembly.GetExecutingAssembly().GetName().Name ?? "ActorSystemName", @"[^a-zA-Z\s]+", "", RegexOptions.None, TimeSpan.FromMilliseconds(100));
builder.Services.AddAkka(actorSystemName,(builder) =>
        {
            builder.WithActors(((system, registry, resolver) =>
            {
                var defaultStrategy= new OneForOneStrategy(
                    3, TimeSpan.FromSeconds(3), ex =>
                    {
                        if (ex is not ActorInitializationException)
                            return Directive.Resume;

                        system?.Terminate().Wait(1000);

                        return Directive.Stop;
                    });
                var mainActorProps = resolver
                    .Props<MainActor>()
                    .WithSupervisorStrategy(defaultStrategy);
                var mainActor = system.ActorOf(mainActorProps, nameof(MainActor));
                registry.Register<MainActor>(mainActor);

            }));

        });

var app = builder.Build();

app.Run();

Inject IRequiredActor into services

  • Inject the required actors into your services where necessary:
csharp
public class MyService
{
    private readonly IActorRef _myActor;

    public MyService(IRequiredActor<MyActor> myActor)
    {
        _myActor = myActor.ActorRef;
    }
    
    // Use _myActor in your service methods like this
    //_myActor.Tell(new ProcessEmailOtpRequest(otp, appConfig));
}

3. Migrate Kafka Consumers

Update appsettings to use multi-host configuration

  • Update your appsettings.json to include the Kafka broker:
json
"KafkaConsumerConfig": {
  "BootstrapServers": "localhost:9092",
  "GroupId": "defaultGroupId",
  "Topics": [
    "defaultKafkaTopic"
  ],
  "ExtraProperties": {
    "auto.offset.reset": "latest"
  }
},
  • Update Kafka-related packages to the latest versions using the NuGet Package Manager or the command line:
bash
dotnet add package Confluent.Kafka
dotnet add package Confluent.Kafka.Extensions.Diagnostics

Injecting Akka into Background Services/Consumers

c#
public class CallbackConsumer : KafkaConsumerBase
{
  private readonly IRequiredActor<CallbackReceiverActor> _callRequiredActor;
    public CallbackConsumer(IRequiredActor<CallbackReceiverActor> callRequiredActor)
    {
        _callRequiredActor = callRequiredActor;
    }

    public async Task HandleBulkMessage(List<CallbackModel> messages)
     {
    
       var callbackProcessorActor = await _callRequiredActor.GetAsync();
       callbackProcessorActor.Tell(message);
     } 
}

4. Migrate Kafka Producers

Add references to HubtelKafkaProducerSdk in Service Collection

  • Add the necessary references in your service registration:
csharp
builder.Services.AddHubtelKafkaProducerSdk(configuration);
json
"KafkaProducerConfig": {
  "Hosts": [
    {
      "Alias": "default",
      "BootstrapServers": "127.0.0.1:9092"
    },
     {
      "Alias": "other-broker-alias",
      "BootstrapServers": "127.0.0.1:9093"
    },
    ,
     {
      "Alias": "myProducerAlias",
      "BootstrapServers": "127.0.0.1:9094"
    }
  ]
}

Migrate direct references of IProducer to IProducerFactory

  • Update your code to use IProducerFactory to create producers:
csharp
public class KafkaService
{
    private readonly IProducer<string, string> _producer;

    public KafkaService(IProducerFactory producerFactory)
    {
       _producer = producerFactory.CreateProducer("myProducerAlias");
    }

    // Use _producer to send messages
}

Create Producer from IProducerFactory using specific alias

  • Use the alias specified in your appsettings.json to create the producer:
csharp
public class MyKafkaService
{
    private readonly IProducer<string, string> _producer;

    public MyKafkaService(IProducerFactory producerFactory)
    {
        _producer = producerFactory.CreateProducer("myProducerAlias");
    }

    public async Task SendMessageAsync(string key, string message)
    {
        await _producer.ProduceAsync("my-topic", new Message<string, string> { Key = key, Value = message });
    }
}

5. Migration Requirement

  • All projects MUST now include integration tests after migrating to dotnet 8.
  • Resources and trainings on the migration and integration testing are available on hubtel academy to help out developers in this regard
  • There is also a starter template available here: Integration Test Template

By following these steps, you should be able to migrate your .NET application to .NET 8, update Akka.NET to use Akka.Hosting, and migrate your Kafka consumers to use a more modern configuration and producer factory pattern.