Author & run actors

    The :

    • Is a required constructor parameter of all actors
    • Is provided by the runtime
    • Must be passed to the base class constructor
    • Contains all of the state that allows that actor instance to communicate with the runtime

    Since the ActorHost contains state unique to the actor, you don’t need to pass the instance into other parts of your code. It’s recommended only create your own instances of ActorHost in tests.

    Dependency injection

    Actors support of additional parameters into the constructor. Any other parameters you define will have their values satisfied from the dependency injection container.

    1. internal class MyActor : Actor, IMyActor, IRemindable
    2. {
    3. public MyActor(ActorHost host, BankService bank) // Accept BankService in the constructor
    4. : base(host)
    5. {
    6. ...
    7. }
    8. }

    An actor type should have a single public constructor. The actor infrastructure uses the ActivatorUtilities pattern for constructing actor instances.

    You can register types with dependency injection in Startup.cs to make them available. Read more about .

    1. // In Startup.cs
    2. public void ConfigureServices(IServiceCollection services)
    3. ...
    4. // Register additional types with dependency injection.
    5. services.AddSingleton<BankService>();
    6. }

    Each actor instance has its own dependency injection scope and remains in memory for some time after performing an operation. During that time, the dependency injection scope associated with the actor is also considered live. The scope will be released when the actor is deactivated.

    If an actor injects an IServiceProvider in the constructor, the actor will receive a reference to the IServiceProvider associated with its scope. The IServiceProvider can be used to resolve services dynamically in the future.

    When using this pattern, avoid creating many instances of transient services which implement IDisposable. Since the scope associated with an actor could be considered valid for a long time, you can accumulate many services in memory. See the dependency injection guidelines for more information.

    IDisposable and actors

    Inside an actor class, you have access to an ILogger instance through a property on the base class. This instance is connected to the ASP.NET Core logging system and should be used for all logging inside an actor. Read more about . You can configure a variety of different logging formats and output sinks.

    Use structured logging with named placeholders like the example below:

    1. public Task<MyData> GetDataAsync()
    2. {
    3. this.Logger.LogInformation("Getting state at {CurrentTime}", DateTime.UtcNow);
    4. return this.StateManager.GetStateAsync<MyData>("my_data");
    5. }

    When logging, avoid using format strings like: $"Getting state at {DateTime.UtcNow}"

    Logging should use the named placeholder syntax which offers better performance and integration with logging systems.

    Using an explicit actor type name

    By default, the type of the actor, as seen by clients, is derived from the name of the actor implementation class. The default name will be the class name (without namespace).

    If desired, you can specify an explicit type name by attaching an ActorAttribute attribute to the actor implementation class.

    1. [Actor(TypeName = "MyCustomActorTypeName")]
    2. internal class MyActor : Actor, IMyActor
    3. {
    4. // ...
    5. }

    In the example above, the name will be MyCustomActorTypeName.

    No change is needed to the code that registers the actor type with the runtime, providing the value via the attribute is all that is required.

    Registering actors

    Inside ConfigureServices you can:

    • Register the actor runtime (AddActors)
    • Register actor types (options.Actors.RegisterActor<>)
    • Configure actor runtime settings options
    • Register additional service types for dependency injection into actors (services)

    The actor runtime uses for:

    • Serializing data to the state store
    • Handling requests from the weakly-typed client

    By default, the actor runtime uses settings based on JsonSerializerDefaults.Web.

    You can configure the JsonSerializerOptions as part of ConfigureServices:

    1. // In Startup.cs
    2. public void ConfigureServices(IServiceCollection services)
    3. {
    4. services.AddActors(options =>
    5. // Customize JSON options
    6. options.JsonSerializerOptions = ...
    7. });
    8. }

    Actors and routing

    The ASP.NET Core hosting support for actors uses the endpoint routing system. The .NET SDK provides no support hosting actors with the legacy routing system from early ASP.NET Core releases.

    Since actors uses endpoint routing, the actors HTTP handler is part of the middleware pipeline. The following is a minimal example of a Configure method setting up the middleware pipeline with actors.

    1. // in Startup.cs
    2. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    3. {
    4. if (env.IsDevelopment())
    5. {
    6. app.UseDeveloperExceptionPage();
    7. }
    8. app.UseRouting();
    9. app.UseEndpoints(endpoints =>
    10. {
    11. // Register actors handlers that interface with the Dapr runtime.
    12. endpoints.MapActorsHandlers();
    13. });
    14. }

    The UseRouting and UseEndpoints calls are necessary to configure routing. Configure actors as part of the pipeline by adding MapActorsHandlers inside the endpoint middleware.

    This is a minimal example, it’s valid for Actors functionality to existing alongside:

    • Controllers
    • Razor Pages
    • Blazor
    • gRPC Services
    • Dapr pub/sub handler

    Problematic middleware

    Try the .