Back to Graphql Platform

Global State

website/src/docs/hotchocolate/v16/server/global-state.md

16.1.0-p.1.103.3 KB
Original Source

Global State lets you define properties on a per-request basis and makes them available to all resolvers and middleware.

Initializing Global State

Add Global State using the SetProperty method on the OperationRequestBuilder. This method takes a key and a value as arguments. The key must be a string, and the value can be of any type.

Using an interceptor lets you initialize Global State before the request is executed.

csharp
public class HttpRequestInterceptor : DefaultHttpRequestInterceptor
{
    public override ValueTask OnCreateAsync(HttpContext context,
        IRequestExecutor requestExecutor, OperationRequestBuilder requestBuilder,
        CancellationToken cancellationToken)
    {
        string userId =
            context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;

        requestBuilder.SetProperty("UserId", userId);
        // requestBuilder.SetProperty("IntegerValue", int.Parse(userId));
        // requestBuilder.SetProperty("ObjectValue", new User { Id = userId });

        return base.OnCreateAsync(context, requestExecutor, requestBuilder,
            cancellationToken);
    }
}

Learn more about interceptors

Accessing Global State

Access Global State in your resolvers as follows.

<ExampleTabs> <Implementation>
csharp
public class Query
{
    public string Example1([GlobalState("UserId")] string userId)
    {
        // Omitted code for brevity
    }

    public string Example2([GlobalState("ObjectValue")] User user)
    {
        // Omitted code for brevity
    }
}

The GlobalStateAttribute accepts the key of the Global State value as an argument. An exception is thrown if no Global State value exists for the specified key or if the value cannot be coerced to the type of the argument.

Creating a custom attribute that inherits from GlobalStateAttribute is a good practice:

csharp
public class UserIdAttribute : GlobalStateAttribute
{
    public UserIdAttribute() : base("UserId")
    {

    }
}

public class Query
{
    public string Example([UserId] string userId)
    {
        // Omitted code for brevity
    }
}
</Implementation> <Code>
csharp
public class QueryType : ObjectType
{
    protected override void Configure(IObjectTypeDescriptor descriptor)
    {
        descriptor
            .Field("example")
            .Resolve(context =>
            {
                var userId = context.GetGlobalValue<string>("UserId");

                // Omitted code for brevity
            });
    }
}

Warning: If no value exists for the specified key, a default value is returned and no exception is thrown.

You can also access Global State through the ContextData dictionary on the IResolverContext:

csharp
descriptor
    .Field("example")
    .Resolve(context =>
    {
        if (!context.ContextData.TryGetValue("UserId", out var value)
            || value is not string userId)
        {
            // handle failed assertion
        }

        // Omitted code for brevity
    });
</Code> <Schema>

Take a look at the implementation-first or code-first example.

</Schema> </ExampleTabs>

Next Steps