Class ApiClient
Client for the Virtufin API Gateway: dynamic per-service RPC dispatch (service names as
dynamic members, e.g. client.workmanager.SomeMethod()), plus direct methods for
state, pub/sub, triggers and config.
public class ApiClient : DynamicObject, IDynamicMetaObjectProvider, IDisposable
- Inheritance
-
ApiClient
- Implements
- Inherited Members
Examples
using var client = new ApiClient();
var workers = await client.workmanager.ListWorkers();
// Equivalent to:
var workers = await client.InvokeAsync("workmanager", "ListWorkers");
Remarks
Before 0.7.0 this was two classes: a narrow ApiClient (host/port only, no TLS or
API key) whose .Gateway property returned the real, full-featured
GatewayClient. They are merged here — one class, matching this SDK's Python and
TypeScript counterparts more closely than either the two-class or the auth-less shape did
alone. .Gateway is kept, returning this, purely so existing
client.Gateway.<service>.<Method>(...) call sites keep compiling.
client.workmanager triggers TryGetMember(GetMemberBinder, out object?), which creates or returns a
cached ServiceClient for "workmanager". service.ListWorkers() triggers
TryGetMember(GetMemberBinder, out object?), which returns a callable that invokes via the
Gateway's InvokeJson RPC.
Constructors
ApiClient(GrpcChannel)
Creates a new ApiClient from a pre-built gRPC channel -- the escape hatch for anything the host/port/tls/apiKey constructor can't express (a custom Interceptor, a non-default HttpMessageHandler, etc.). Host and HttpPort are not meaningful from a raw channel and are left at their defaults ("localhost", 0).
public ApiClient(GrpcChannel channel)
Parameters
channelGrpcChannelThe gRPC channel to use for communication.
ApiClient(string, int?, bool, string?)
Creates a new ApiClient.
public ApiClient(string host = "localhost", int? grpcPort = null, bool tls = false, string? apiKey = null)
Parameters
hoststringThe host address (default: "localhost").
grpcPortint?The gRPC port (default: DefaultGrpcPort). Previously named
httpPortand, when omitted, defaulted to DefaultHttpPort -- the wrong constant for a channel this class only ever builds as gRPC. No known caller relied on the default (every one passes a port explicitly), but fixed here regardless.tlsboolUse an HTTPS channel, verified against system CA roots.
apiKeystringSent as
x-api-keyon every call, via a default header on the channel's underlying HttpClient. Null sends no key.
Properties
Gateway
Returns this same client. Kept only so client.Gateway.<service>.<Method>(...)
-- the pattern used throughout this org's C# workers and examples before 0.7.0 -- keeps
compiling unmodified. New code should call directly on the client, e.g.
client.workmanager.ListWorkers() instead of client.Gateway.workmanager.ListWorkers().
[Obsolete("ApiClient now exposes gateway methods directly; this property is kept only for source compatibility.")]
public ApiClient Gateway { get; }
Property Value
Host
The host address of the gateway.
public string Host { get; }
Property Value
HttpPort
The gRPC port of the gateway.
public int HttpPort { get; }
Property Value
InvokeTimeout
Default gRPC deadline for InvokeAsync(string, string, Dictionary<string, object?>?)
and dynamic calls (client.workmanager.CreateWorker(...)). Null (the
default) sends no deadline, and the gateway applies its own 30s default to
the call it forwards. Set it longer for an operation that legitimately
takes more time, e.g. a cold CreateWorker. The gateway honors it up to
its 300s cap.
public TimeSpan? InvokeTimeout { get; set; }
Property Value
Methods
Close()
Closes the client synchronously.
public void Close()
CloseAsync()
Closes the client asynchronously.
public Task CloseAsync()
Returns
DeleteBulkStateAsync(string, IEnumerable<string>, bool, ChangeNotification?, CancellationToken)
Deletes multiple state entries for a service.
public Task<DeleteBulkStateResponse> DeleteBulkStateAsync(string service, IEnumerable<string> keys, bool publishChange = false, ChangeNotification? change = null, CancellationToken cancellationToken = default)
Parameters
servicestringkeysIEnumerable<string>publishChangeboolIf true, a single state change event is published (sys.api.state.deleted) for the whole bulk. Default false.
changeChangeNotificationOptional. See SaveStateAsync(string, string, string, string?, bool, bool, ChangeNotification?, CancellationToken) for what this selects.
cancellationTokenCancellationToken
Returns
- Task<DeleteBulkStateResponse>
DeleteStateAsync(string, string, bool, bool, ChangeNotification?, CancellationToken)
Deletes a state entry and broadcasts a delete event to subscribers asynchronously.
public Task<DeleteStateResponse> DeleteStateAsync(string service, string key, bool publishChange = false, bool includeValue = false, ChangeNotification? change = null, CancellationToken cancellationToken = default)
Parameters
servicestringThe service name.
keystringThe state key.
publishChangeboolIf true, a state change event is published (sys.api.state.saved/deleted). Default false.
includeValueboolIf true, the last value is included in the state change event payload. Only relevant when publishChange=true.
changeChangeNotificationOptional. See SaveStateAsync(string, string, string, string?, bool, bool, ChangeNotification?, CancellationToken) for what this selects.
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<DeleteStateResponse>
DeleteStateResponse with success status.
DeleteTriggerAsync(string, CancellationToken)
Deletes a scheduled trigger.
public Task<DeleteTriggerResponse> DeleteTriggerAsync(string name, CancellationToken cancellationToken = default)
Parameters
namestringcancellationTokenCancellationToken
Returns
- Task<DeleteTriggerResponse>
Dispose()
Disposes of the client resources.
public void Dispose()
DisposeAsync()
Disposes of the client resources asynchronously.
public ValueTask DisposeAsync()
Returns
GetBulkStateAsync(string, IEnumerable<string>, CancellationToken)
Gets multiple state values for a service and list of keys.
public Task<List<StateItemDto>> GetBulkStateAsync(string service, IEnumerable<string> keys, CancellationToken cancellationToken = default)
Parameters
servicestringkeysIEnumerable<string>cancellationTokenCancellationToken
Returns
GetConfigServiceAsync(string, CancellationToken)
Gets one service's configuration. Throws RpcException with
NotFound if the name is not registered.
public Task<GetConfigServiceResponse> GetConfigServiceAsync(string name, CancellationToken cancellationToken = default)
Parameters
namestringcancellationTokenCancellationToken
Returns
- Task<GetConfigServiceResponse>
GetService(string)
Gets a client for a specific service.
public ServiceClient GetService(string name)
Parameters
namestringThe service name.
Returns
- ServiceClient
A ServiceClient for the service.
Remarks
ServiceClients are cached internally. Calling this method multiple times with the same service name returns the same cached instance.
GetStateAsync(string, string, CancellationToken)
Gets a single state value asynchronously by service and key.
public Task<(string Value, string Etag)> GetStateAsync(string service, string key, CancellationToken cancellationToken = default)
Parameters
servicestringThe service name.
keystringThe state key.
cancellationTokenCancellationTokenCancellation token.
Returns
GetTriggerAsync(string, CancellationToken)
Retrieves a scheduled trigger's details.
public Task<GetTriggerResponse> GetTriggerAsync(string name, CancellationToken cancellationToken = default)
Parameters
namestringcancellationTokenCancellationToken
Returns
- Task<GetTriggerResponse>
InvokeAsync(string, string, Dictionary<string, object?>?)
Invokes a method on a service asynchronously.
public Task<Dictionary<string, object?>> InvokeAsync(string service, string method, Dictionary<string, object?>? requestData = null)
Parameters
servicestringThe service name.
methodstringThe method name.
requestDataDictionary<string, object>Optional request data as dictionary.
Returns
- Task<Dictionary<string, object>>
The response as a dictionary.
Remarks
The polymorphic Dictionary<string, object?>
payload is (de)serialized via Virtufin.Api.Client.ApiClient.JsonOptions,
which sets an explicit DefaultJsonTypeInfoResolver
so reflection-based dispatch works regardless of the
process-wide IsReflectionEnabledByDefault flag.
See Virtufin.Api.Client.ApiClient.JsonOptions for the AOT caveat.
Exceptions
- InvalidOperationException
Thrown when the invocation fails.
InvokeAsync(string, string, Dictionary<string, object?>?, TimeSpan?)
InvokeAsync(string, string, Dictionary<string, object?>?) with an explicit gRPC deadline for this call (null: no deadline). A separate overload rather than a new optional parameter, so code already compiled against the three-argument signature keeps binding to it.
public Task<Dictionary<string, object?>> InvokeAsync(string service, string method, Dictionary<string, object?>? requestData, TimeSpan? timeout)
Parameters
Returns
ListConfigServicesAsync(CancellationToken)
Lists every registered service, including non-dialable entries (those that exist only to resolve Dapr component names).
public Task<ListConfigServicesResponse> ListConfigServicesAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationToken
Returns
- Task<ListConfigServicesResponse>
Remarks
Contrast ListServicesAsync(), which returns only the backends the gateway can actually invoke.
ListMethodsAsync(string)
Lists all methods for a given service asynchronously.
public Task<List<Dictionary<string, object?>>> ListMethodsAsync(string service)
Parameters
servicestringThe service name.
Returns
- Task<List<Dictionary<string, object>>>
List of method information dictionaries.
ListServicesAsync()
Lists all available services asynchronously.
public Task<List<string>> ListServicesAsync()
Returns
ListTriggersAsync(CancellationToken)
Lists all scheduled triggers.
public Task<ListTriggersResponse> ListTriggersAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationToken
Returns
- Task<ListTriggersResponse>
PublishEventAsync(string, CloudEvent, CancellationToken)
Publishes a CloudEvent to a topic asynchronously.
public Task<PublishResponse> PublishEventAsync(string topic, CloudEvent cloudevent, CancellationToken cancellationToken = default)
Parameters
topicstringThe topic name.
cloudeventCloudEventThe CloudEvent proto to publish.
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<PublishResponse>
PublishResponse with success status.
PublishWithResultAsync(string, CloudEvent, string, TimeSpan?, string?, CancellationToken)
Publishes to a topic and waits for a correlated response on a reply topic.
Implements the request-reply pattern over pub/sub using correlation IDs.
Sets correlationid and replytopic as CloudEvent attributes
before publishing.
public Task<SubscribeResponse> PublishWithResultAsync(string topic, CloudEvent cloudevent, string replyTopic, TimeSpan? timeout = null, string? correlationId = null, CancellationToken cancellationToken = default)
Parameters
topicstringThe topic to publish the request to.
cloudeventCloudEventThe CloudEvent proto to publish.
replyTopicstringThe topic to listen for responses on.
timeoutTimeSpan?Maximum time to wait for a response (default: 30s).
correlationIdstringOptional correlation ID (auto-generated if null).
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<SubscribeResponse>
The correlated SubscribeResponse.
Exceptions
- TimeoutException
Thrown if no response arrives within the timeout.
QueryStateAsync(string, string, int, CancellationToken)
Gets all state key-value pairs asynchronously for a service.
public Task<List<StateItemDto>> QueryStateAsync(string service, string query, int limit = 0, CancellationToken cancellationToken = default)
Parameters
servicestringThe service name.
querystringThe Dapr JSON query string.
limitintMax results (0 = no limit).
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<List<StateItemDto>>
List of state items with key, value, etag.
SaveStateAsync(string, string, string, string?, bool, bool, ChangeNotification?, CancellationToken)
Saves state and broadcasts a change event to subscribers asynchronously.
public Task<SaveStateResponse> SaveStateAsync(string service, string key, string value, string? etag = null, bool publishChange = false, bool includeValue = false, ChangeNotification? change = null, CancellationToken cancellationToken = default)
Parameters
servicestringThe service name.
keystringThe state key.
valuestringThe state value.
etagstringOptional etag for concurrency.
publishChangeboolIf true, a state change event is published (sys.api.state.saved/deleted). Default false.
includeValueboolIf true, the value is included in the state change event payload. Only relevant when publishChange=true.
changeChangeNotificationOptional. With
publishChange, selects where the notification goes. Unset means the Tier 0sys.api.state.saved/deletedtopic, correct for infra state. For domain state (positions, portfolios, orders) supply aChangeNotificationcarrying both a topic and a CloudEvent: the API publishes that event verbatim after the write and skips the Tier 0 topic. It cannot build the event itself -- it has the key and the bytes but not the scenario, world markers, clock type, or your service identity. Tier 0 events carry no version, so consuming the value without a read-back assumes writes to that key are serialized; carry a monotonic token in your own event if you need ordering. Publication is at-most-once and not atomic with the write.cancellationTokenCancellationTokenCancellation token.
Returns
- Task<SaveStateResponse>
SaveStateResponse with success status.
ScheduleTriggerAsync(string, string, string?, string?, int, string?, CancellationToken)
Schedules a recurring trigger. When it fires, the API publishes an empty
CloudEvent to targetTopic.
public Task<ScheduleTriggerResponse> ScheduleTriggerAsync(string name, string targetTopic, string? schedule = null, string? dueTime = null, int repeats = 0, string? ttl = null, CancellationToken cancellationToken = default)
Parameters
namestringTrigger name, unique per deployment.
targetTopicstringTopic the fired trigger publishes to.
schedulestringA 6-field cron expression or an
@everyduration.dueTimestringOptional first-fire time.
repeatsintOptional repeat count; 0 means unlimited.
ttlstringOptional time-to-live.
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<ScheduleTriggerResponse>
Remarks
Errors are in-band: the gRPC status is OK and failure is signalled by
status.success == false. Check it.
Subscribe(IEnumerable<string>?, CancellationToken)
Subscribes to one or more pub/sub topics.
public AsyncServerStreamingCall<SubscribeResponse> Subscribe(IEnumerable<string>? topics = null, CancellationToken cancellationToken = default)
Parameters
topicsIEnumerable<string>Topics to subscribe to. Filtering is by topic only --
SubscribeRequestcarries no service or event-type filter, so discriminate further oncloudevent.type. An empty list is not "all topics": the server defaults it to the state-change topics (sys.api.state.saved,sys.api.state.deleted), so name your topics explicitly. (servicesandeventTypesparameters were removed -- they were accepted, documented as filters, and silently discarded.)cancellationTokenCancellationTokenCancellation token.
Returns
- AsyncServerStreamingCall<SubscribeResponse>
The async call handle. Dispose to cancel subscription.
SubscribeAsync(IStreamEventHandler, IEnumerable<string>?, CancellationToken)
Subscribes to events with a handler callback.
public Task SubscribeAsync(IStreamEventHandler handler, IEnumerable<string>? topics = null, CancellationToken cancellationToken = default)
Parameters
handlerIStreamEventHandlerHandler to receive events.
topicsIEnumerable<string>Topics to subscribe to. Filtering is by topic only --
SubscribeRequestcarries no service or event-type filter, so discriminate further oncloudevent.type. An empty list is not "all topics": the server defaults it to the state-change topics (sys.api.state.saved,sys.api.state.deleted), so name your topics explicitly. (servicesandeventTypesparameters were removed -- they were accepted, documented as filters, and silently discarded.)cancellationTokenCancellationTokenCancellation token.
Returns
- Task
Task that completes when subscription is cancelled.
SubscribeToTopic(string, CancellationToken)
Subscribes to a pub/sub topic and streams events.
public AsyncServerStreamingCall<SubscribeResponse> SubscribeToTopic(string topic, CancellationToken cancellationToken = default)
Parameters
topicstringThe topic name.
cancellationTokenCancellationTokenCancellation token.
Returns
- AsyncServerStreamingCall<SubscribeResponse>
Async streaming call for SubscribeResponse. Dispose to cancel.
TryGetMember(GetMemberBinder, out object?)
Dynamic property access returns a ServiceClient for the named service.
public override bool TryGetMember(GetMemberBinder binder, out object? result)
Parameters
binderGetMemberBinderresultobject
Returns
UnsubscribeFromTopicAsync(string, CancellationToken)
Unsubscribes from a pub/sub topic.
public Task<UnsubscribeResponse> UnsubscribeFromTopicAsync(string subscriptionId, CancellationToken cancellationToken = default)
Parameters
subscriptionIdstringThe subscription ID to cancel.
cancellationTokenCancellationTokenCancellation token.
Returns
- Task<UnsubscribeResponse>
UnsubscribeResponse with success status.