GraphQL.Server.Ui.Playground 8.3.3

dotnet add package GraphQL.Server.Ui.Playground --version 8.3.3
                    
NuGet\Install-Package GraphQL.Server.Ui.Playground -Version 8.3.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GraphQL.Server.Ui.Playground" Version="8.3.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GraphQL.Server.Ui.Playground" Version="8.3.3" />
                    
Directory.Packages.props
<PackageReference Include="GraphQL.Server.Ui.Playground" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GraphQL.Server.Ui.Playground --version 8.3.3
                    
#r "nuget: GraphQL.Server.Ui.Playground, 8.3.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GraphQL.Server.Ui.Playground@8.3.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GraphQL.Server.Ui.Playground&version=8.3.3
                    
Install as a Cake Addin
#tool nuget:?package=GraphQL.Server.Ui.Playground&version=8.3.3
                    
Install as a Cake Tool

ASP.NET Core GraphQL Server driven by GraphQL.NET

License codecov Nuget Nuget GitHub Release Date GitHub commits since latest release (by date) GitHub contributors Size

GraphQL ASP.NET Core server on top of GraphQL.NET. HTTP transport compatible with the GraphQL over HTTP draft specification. WebSocket transport compatible with both subscriptions-transport-ws and graphql-ws subscription protocols. The transport format of all messages is supposed to be JSON.

Provides the following packages:

Package Downloads Version Description
GraphQL.Server.All Nuget Nuget Includes all the packages below, plus the GraphQL.DataLoader and GraphQL.MemoryCache packages
GraphQL.Server.Transports.AspNetCore Nuget Nuget Provides GraphQL over HTTP/WebSocket server support on top of ASP.NET Core, plus authorization rule support
GraphQL.Server.Ui.Altair Nuget Nuget Provides Altair UI middleware
GraphQL.Server.Ui.Playground ⚠️ Nuget Nuget Provides Playground UI middleware (deprecated)
GraphQL.Server.Ui.GraphiQL Nuget Nuget Provides GraphiQL UI middleware
GraphQL.Server.Ui.Voyager Nuget Nuget Provides Voyager UI middleware

You can install the latest stable versions via NuGet. Also you can get all preview versions from GitHub Packages. Note that GitHub requires authentication to consume the feed. See more information here.

⚠️ When upgrading from prior versions, please remove references to these old packages ⚠️
GraphQL.Server.Core
GraphQL.Server.Authentication.AspNetCore
GraphQL.Server.Transports.AspNetCore.NewtonsoftJson
GraphQL.Server.Transports.AspNetCore.SystemTextJson
GraphQL.Server.Transports.Subscriptions.Abstractions
GraphQL.Server.Transports.Subscriptions.WebSockets
GraphQL.Server.Transports.WebSocktes

Description

This package is designed for ASP.NET Core (2.1 through 9.0) to facilitate easy set-up of GraphQL requests over HTTP. The code is designed to be used as middleware within the ASP.NET Core pipeline, serving GET, POST or WebSocket requests. GET requests process requests from the query string. POST requests can be in the form of JSON requests, form submissions, or raw GraphQL strings. Form submissions either accepts query, operationName, variables and extensions parameters, or operations and map parameters along with file uploads as defined in the GraphQL multipart request spec. WebSocket requests can use the graphql-ws or graphql-transport-ws WebSocket sub-protocol, as defined in the apollographql/subscriptions-transport-ws and enisdenjo/graphql-ws repositories, respectively.

The middleware can be configured through the IApplicationBuilder or IEndpointRouteBuilder builder interfaces. Alternatively, route handlers (such as MapGet and MapPost) can return a GraphQLExecutionHttpResult for direct GraphQL execution, or ExecutionResultHttpResult for returning pre-executed GraphQL responses. Similarly, GraphQLExecutionActionResult and ExecutionResultActionResult classes can be used to return GraphQL responses from controller actions.

Authorization is also supported with the included AuthorizationValidationRule. It will scan GraphQL documents and validate that the schema and all referenced output graph types, fields of output graph types, and query arguments meet the specified policy and/or roles held by the authenticated user within the ASP.NET Core authorization framework. It does not validate any policies or roles specified for input graph types, fields of input graph types, or directives. It skips validations for fields or fragments that are marked with the @skip or @include directives.

Migration from older version

Configuration

Typical configuration with HTTP middleware

First add either the GraphQL.Server.All nuget package or the GraphQL.Server.Transports.AspNetCore nuget package to your application. Referencing the "all" package will include the UI middleware packages. These packages depend on GraphQL version 8.2.1 or later.

Then update your Program.cs or Startup.cs to configure GraphQL, registering the schema and the serialization engine as a minimum. Configure WebSockets and GraphQL in the HTTP pipeline by calling UseWebSockets and UseGraphQL at the appropriate point. Finally, you may also include some UI middleware for easy testing of your GraphQL endpoint by calling UseGraphQLGraphiQL or a similar method at the appropriate point.

Below is a complete sample of a .NET 6 console app that hosts a GraphQL endpoint at http://localhost:5000/graphql:

Project file
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="GraphQL.Server.All" Version="7.0.0" />
  </ItemGroup>

</Project>
Program.cs file
using GraphQL;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGraphQL(b => b
    .AddAutoSchema<Query>()  // schema
    .AddSystemTextJson());   // serializer

var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseWebSockets();
app.UseGraphQL("/graphql");            // url to host GraphQL endpoint
app.UseGraphQLGraphiQL(
    "/",                               // url to host GraphiQL at
    new GraphQL.Server.Ui.GraphiQL.GraphiQLOptions
    {
        GraphQLEndPoint = "/graphql",         // url of GraphQL endpoint
        SubscriptionsEndPoint = "/graphql",   // url of GraphQL endpoint
    });
await app.RunAsync();
Schema
public class Query
{
    public static string Hero() => "Luke Skywalker";
}
Sample request url
http://localhost:5000/graphql?query={hero}
Sample response
{"data":{"hero":"Luke Skywalker"}}

Basic options

By default, the middleware will be installed with these configurable options:

  • GET, POST, and WebSocket requests are all enabled
  • Form content types are disabled, and cross-site request forgery (CSRF) protection is enabled
  • There are no authentication or authorization requirements
  • The default response content type is application/graphql-response+json
  • The middleware will use the default schema instance

To configure these options, pass a confiuguration delegate to the UseGraphQL method as demonstrated below:

app.UseGraphQL("/graphql", opts => {
    opts.ReadFormOnPost = true;
});

Configuration of these options and more are further described below in this document.

Configuration with endpoint routing

To use endpoint routing, call MapGraphQL from inside the endpoint configuration builder rather than UseGraphQL on the application builder. See below for the sample of the application builder code:

var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseWebSockets();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapGraphQL("graphql");
    endpoints.MapGraphQLVoyager("ui/voyager");
});
await app.RunAsync();

Using endpoint routing is particularly useful when you want to select a specific CORS configuration for the GraphQL endpoint. See the CORS section below for a sample.

Please note that when using endpoint routing, you cannot use WebSocket connections while a UI package is also configured at the same URL. You will need to use a different URL for the UI package, or use UI middleware prior to endpoint routing. So long as different URLs are used, there are no issues. Below is a sample when the UI and GraphQL reside at the same URL:

var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseWebSockets();
app.UseRouting();
app.UseGraphQLVoyager("/graphql");
app.UseEndpoints(endpoints =>
{
    endpoints.MapGraphQL("/graphql");
});
await app.RunAsync();

Configuration with route handlers (.NET 6+)

Although not recommended, you may set up route handlers to execute GraphQL requests using MapGet and MapPost that return an IResult. You will not need UseGraphQL or MapGraphQL in the application startup. Note that GET must be mapped to support WebSocket connections, as WebSocket connections upgrade from HTTP GET requests.

Using GraphQLExecutionHttpResult
var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseWebSockets();

// configure the graphql endpoint at "/graphql", using GraphQLExecutionHttpResult
// map GET in order to support both GET and WebSocket requests
app.MapGet("/graphql", () => new GraphQLExecutionHttpResult());
// map POST to handle standard GraphQL POST requests
app.MapPost("/graphql", () => new GraphQLExecutionHttpResult());

await app.RunAsync();
Using ExecutionResultHttpResult
app.MapPost("/graphql", async (HttpContext context, IDocumentExecuter<ISchema> documentExecuter, IGraphQLSerializer serializer) =>
{
    var request = await serializer.ReadAsync<GraphQLRequest>(context.Request.Body, context.RequestAborted);
    var opts = new ExecutionOptions
    {
        Query = request?.Query,
        DocumentId = request?.DocumentId,
        Variables = request?.Variables,
        Extensions = request?.Extensions,
        CancellationToken = context.RequestAborted,
        RequestServices = context.RequestServices,
        User = context.User,
    };

    return new ExecutionResultHttpResult(await documentExecuter.ExecuteAsync(opts));
});

Configuration with a MVC controller

Although not recommended, you may set up a controller action to execute GraphQL requests. You will not need UseGraphQL or MapGraphQL in the application startup. You may use GraphQLExecutionActionResult to let the middleware handle the entire parsing and execution of the request, including subscription requests over WebSocket connections, or you can execute the request yourself, only using ExecutionResultActionResult to serialize the result.

You can also reference the UI projects to display a GraphQL user interface as shown below.

Using GraphQLExecutionActionResult
public class HomeController : Controller
{
    public IActionResult Index()
        => new GraphiQLActionResult(opts =>
        {
            opts.GraphQLEndPoint = "/Home/graphql";
            opts.SubscriptionsEndPoint = "/Home/graphql";
        });

    [HttpGet]
    [HttpPost]
    [ActionName("graphql")]
    public IActionResult GraphQL()
        => new GraphQLExecutionActionResult();
}
Using ExecutionResultActionResult

Note: this is very simplified; a much more complete sample can be found in the Samples.Controller project within this repository.

public class HomeController : Controller
{
    private readonly IDocumentExecuter _documentExecuter;

    public TestController(IDocumentExecuter<ISchema> documentExecuter)
    {
        _documentExecuter = documentExecuter;
    }

    [HttpGet]
    public async Task<IActionResult> GraphQL(string query)
    {
        var result = await _documentExecuter.ExecuteAsync(new()
        {
            Query = query,
            RequestServices = HttpContext.RequestServices,
            CancellationToken = HttpContext.RequestAborted,
        });
        return new ExecutionResultActionResult(result);
    }
}

Configuration with Azure Functions

This project also supports hosting GraphQL endpoints within Azure Functions. You will need to complete the following steps:

  1. Configure the Azure Function to use Dependency Injection: See https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection for details.

  2. Configure GraphQL via builder.Services.AddGraphQL() the same as you would in a typical ASP.NET Core application.

  3. Add an HTTP function that returns an appropriate ActionResult:

[FunctionName("GraphQL")]
public static IActionResult RunGraphQL(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post"] HttpRequest req)
{
    return new GraphQLExecutionActionResult();
}
  1. Optionally, add a UI package to the project and configure it:
[FunctionName("GraphiQL")]
public static IActionResult RunGraphiQL(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get"] HttpRequest req)
{
    return new GraphiQLActionResult(opts => opts.GraphQLEndPoint = "/api/graphql");
}

Middleware can be configured by passing a configuration delegate to new GraphQLExecutionActionResult(). Multiple schemas are supported by the use of GraphQLExecutionActionResult<TSchema>(). It is not possible to configure subscription support, as Azure Functions do not support WebSockets since it is a serverless environment.

See the Samples.AzureFunctions project for a complete sample based on the .NET template for Azure Functions.

Please note that the GraphQL schema needs to be initialized for every call through Azure Functions, since it is a serverless environment. This is done automatically but will come at a performance cost. If you are using a schema that is expensive to initialize, you may want to consider using a different hosting environment.

User context configuration

To set the user context to be used during the execution of GraphQL requests, call AddUserContextBuilder during the GraphQL service setup to set a delegate which will be called when the user context is built. Alternatively, you can register an IUserContextBuilder implementation to do the same.

Program.cs / Startup.cs
builder.Services.AddGraphQL(b => b
    .AddAutoSchema<Query>()
    .AddSystemTextJson()
    .AddUserContextBuilder(httpContext => new MyUserContext(httpContext));
MyUserContext.cs
public class MyUserContext : Dictionary<string, object?>
{
    public ClaimsPrincipal User { get; }

    public MyUserContext(HttpContext context)
    {
        User = context.User;
    }
}

Authorization configuration

You can configure authorization for all GraphQL requests, or for individual graphs, fields and query arguments within your schema. Both can be used if desired.

Be sure to call app.UseAuthentication() and app.UseAuthorization() prior to the call to app.UseGraphQL(). For example:

app.UseAuthentication();
app.UseAuthorization();
app.UseWebSockets();
app.UseGraphQL("/graphql");
Endpoint authorization (which would include introspection requests)

Endpoint authorization will check authorization requirements are met for the entire GraphQL endpoint, including introspection requests. These checks occur prior to parsing, validating or executing the document.

When calling UseGraphQL, specify options as necessary to configure authorization as required.

app.UseGraphQL("/graphql", config =>
{
    // require that the user be authenticated
    config.AuthorizationRequired = true;

    // require that the user be a member of at least one role listed
    config.AuthorizedRoles.Add("MyRole");
    config.AuthorizedRoles.Add("MyAlternateRole");

    // require that the user pass a specific authorization policy
    config.AuthorizedPolicy = "MyPolicy";
});
For individual graph types, fields and query arguments

To configure the ASP.NET Core authorization validation rule for GraphQL, add the corresponding validation rule during GraphQL configuration, typically by calling .AddAuthorizationRule() as shown below:

builder.Services.AddGraphQL(b => b
    .AddAutoSchema<Query>()
    .AddSystemTextJson()
    .AddAuthorizationRule());

Both roles and policies are supported for output graph types, fields on output graph types, and query arguments. If multiple policies are specified, all must match; if multiple roles are specified, any one role must match. You may also use .Authorize() and/or the [Authorize] attribute to validate that the user has authenticated. You may also use .AllowAnonymous() and/or [AllowAnonymous] to allow fields to bypass authorization requirements defined on the type that contains the field.

Please note that authorization rules do not apply to values returned within introspection requests, potentially leaking information about protected areas of the schema to unauthenticated users. You may use the ISchemaFilter to restrict what information is returned from introspection requests, but it will apply to both authenticated and unauthenticated users alike.

Introspection requests are allowed unless the schema has an authorization requirement set on it. The @skip and @include directives are honored, skipping authorization checks for fields or fragments skipped by @skip or @include.

Please note that if you use interfaces, validation might be executed against the graph field or the interface field, depending on the structure of the query. For instance:

{
  cat {
    # validates against Cat.Name
    name

    # validates against Animal.Name
    ... on Animal {
      name
    }
  }
}

Similarly for unions, validation occurs on the exact type that is queried. Be sure to carefully consider placement of authorization rules when using interfaces and unions, especially when some fields are marked with AllowAnonymous.

⚠️ Note that authorization rules are ignored for input types and fields of input types ⚠️
Custom authentication configuration for GET/POST requests

To provide custom authentication code, bypassing ASP.NET Core's authentication, derive from the GraphQLHttpMiddleware<T> class and override HandleAuthorizeAsync, setting HttpContext.User to an appropriate ClaimsPrincipal instance.

See 'Customizing middleware behavior' below for an example of deriving from GraphQLHttpMiddleware.

Authentication for WebSocket requests

Since WebSocket requests from browsers cannot typically carry a HTTP Authorization header, you will need to authorize requests via the ConnectionInit WebSocket message or carry the authorization token within the URL. Below is a sample of the former:

builder.Services.AddGraphQL(b => b
    .AddAutoSchema<Query>()
    .AddSystemTextJson()
    .AddAuthorizationRule()  // not required for endpoint authorization
    .AddWebSocketAuthentication<MyAuthService>());

app.UseGraphQL("/graphql", config =>
{
    // require that the user be authenticated
    config.AuthorizationRequired = true;
});

class MyAuthService : IWebSocketAuthenticationService
{
    private readonly IGraphQLSerializer _serializer;

    public MyAuthService(IGraphQLSerializer serializer)
    {
        _serializer = serializer;
    }

    public async ValueTask<bool> AuthenticateAsync(IWebSocketConnection connection, OperationMessage operationMessage)
    {
        // read payload of ConnectionInit message and look for an "Authorization" entry that starts with "Bearer "
        var payload = _serializer.ReadNode<Inputs>(operationMessage.Payload);
        if ((payload?.TryGetValue("Authorization", out var value) ?? false) && value is string valueString)
        {
            var user = ParseToken(valueString);
            if (user != null)
            {
                // set user and indicate authentication was successful
                connection.HttpContext.User = user;
                return true;
            }
        }
        return false; // authentication failed
    }

    private ClaimsPrincipal? ParseToken(string authorizationHeaderValue)
    {
        // parse header value and return user, or null if unable
    }
}

To authorize based on information within the query string, it is recommended to derive from GraphQLHttpMiddleware<T> and override InvokeAsync, setting HttpContext.User based on the query string parameters, and then calling base.InvokeAsync. Alternatively you may override HandleAuthorizeAsync which will execute for GET/POST requests, and HandleAuthorizeWebSocketConnectionAsync for WebSocket requests. Note that InvokeAsync will execute even if the protocol is disabled in the options via disabling HandleGet or similar; HandleAuthorizeAsync and HandleAuthorizeWebSocketConnectionAsync will not.

Authentication schemes

By default the role and policy requirements are validated against the current user as defined by HttpContext.User. This is typically set by ASP.NET Core's authentication middleware and is based on the default authentication scheme set during the call to AddAuthentication in Startup.cs. You may override this behavior by specifying a different authentication scheme via the AuthenticationSchemes option. For instance, if you wish to authenticate using JWT authentication when Cookie authentication is the default, you may specify the scheme as follows:

app.UseGraphQL("/graphql", config =>
{
    // specify a specific authentication scheme to use
    config.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
});

This will overwrite the HttpContext.User property when handling GraphQL requests, which will in turn set the IResolveFieldContext.User property to the same value (unless being overridden via an IWebSocketAuthenticationService implementation as shown above). So both endpoint authorization and field authorization will perform role and policy checks against the same authentication scheme.

UI configuration

There are four UI middleware projects included; Altair, GraphiQL, Playground and Voyager. Playground has not been updated since 2019 and is deprecated in favor of GraphiQL. See review the following methods for configuration options within each of the 4 respective NuGet packages:

app.UseGraphQLAltair();
app.UseGraphQLGraphiQL();
app.UseGraphQLPlayground();  // deprecated
app.UseGraphQLVoyager();

// or

endpoints.MapGraphQLAltair();
endpoints.MapGraphQLGraphiQL();
endpoints.MapGraphQLPlayground();  // deprecated
endpoints.MapGraphQLVoyager();

CORS configuration

ASP.NET Core supports CORS requests independently of GraphQL, including CORS pre-flight requests. To configure your application for CORS requests, add AddCors() and UseCors() into the application pipeline.

builder.Services.AddCors();

app.UseCors(policy => {
    // configure default policy here
});

To configure GraphQL to use a named CORS policy, configure the application to use endpoint routing and call RequireCors() on the endpoint configuration builder.

// ...
builder.Services.AddRouting();
builder.Services.AddCors(builder =>
{
    // configure named and/or default policies here
});

var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseWebSockets();
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
    // configure the graphql endpoint with the specified CORS policy
    endpoints.MapGraphQL()
        .RequireCors("MyCorsPolicy");
});
await app.RunAsync();

In order to ensure that all requests trigger CORS preflight requests, by default the server will reject requests that do not meet one of the following criteria:

  • The request is a POST request that includes a Content-Type header that is not application/x-www-form-urlencoded, multipart/form-data, or text/plain.
  • The request includes a non-empty GraphQL-Require-Preflight header.

To disable this behavior, set the CsrfProtectionEnabled option to false.

app.UseGraphQL("/graphql", config =>
{
    config.CsrfProtectionEnabled = false;
});

You may also change the allowed headers by modifying the CsrfProtectionHeaders option.

app.UseGraphQL("/graphql", config =>
{
    config.CsrfProtectionHeaders = ["MyCustomHeader"];
});

Response compression

ASP.NET Core supports response compression independently of GraphQL, with brotli and gzip support automatically based on the compression formats listed as supported in the request headers. To configure your application for response compression, configure your Program/Startup file as follows:

// add and configure the service
builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true; // may lead to CRIME and BREACH attacks
    options.MimeTypes = new[] { "application/json", "application/graphql-response+json" };
})

// place this first/early in the pipeline
app.UseResponseCompression();

In order to compress GraphQL responses, the application/graphql-response+json content type must be added to the MimeTypes option. You may choose to enable other content types as well.

Please note that enabling response compression over HTTPS can lead to CRIME and BREACH attacks. These side-channel attacks typically affects sites that rely on cookies for authentication. Please read this and this for more details.

ASP.NET Core 2.1 / .NET Framework 4.8

You may choose to use the .NET Core 2.1 runtime or the .NET Framework 4.8 runtime. This library has been tested with .NET Core 2.1 and .NET Framework 4.8.

The only additional requirement is that you must add this code in your Startup.cs file:

services.AddHostApplicationLifetime();

Besides that requirement, all features are supported in exactly the same manner as when using ASP.NET Core 3.1+. You may find differences in the ASP.NET Core runtime, such as CORS implementation differences, which are outside the scope of this project.

Please note that a serializer reference is not included for these projects within GraphQL.Server.Transports.AspNetCore; you will need to reference either GraphQL.NewtonsoftJson or GraphQL.SystemTextJson, or reference GraphQL.Server.All which includes GraphQL.NewtonsoftJson for ASP.NET Core 2.1 projects. This is because Newtonsoft.Json is the default serializer for ASP.NET Core 2.1 rather System.Text.Json. When using GraphQL.NewtonsoftJson, you will need to call AddNewtonsoftJson() rather than AddSystemTextJson() while configuring GraphQL.NET.

<details><summary>Microsoft support policy</summary><p>

Please note that .NET Core 2.1 is currently out of support by Microsoft. .NET Framework 4.8 is supported, and ASP.NET Core 2.1 is supported when run on .NET Framework 4.8. Please see these links for more information:

</p></details>

Advanced configuration

For more advanced configurations, see the overloads and configuration options available for the various builder methods, listed below. Methods and properties contain XML comments to provide assistance while coding with your IDE.

Builder interface Method Description
IGraphQLBuilder AddUserContextBuilder Sets up a delegate to create the UserContext for each GraphQL request.
IApplicationBuilder UseGraphQL Adds the GraphQL middleware to the HTTP request pipeline.
IEndpointRouteBuilder MapGraphQL Adds the GraphQL middleware to the HTTP request pipeline.

A number of the methods contain optional parameters or configuration delegates to allow further customization. Please review the overloads of each method to determine which options are available. In addition, many methods have more descriptive XML comments than shown above.

Configuration options

Below are descriptions of the options available when registering the HTTP middleware. Note that the HTTP middleware options are configured via the UseGraphQL or MapGraphQL methods allowing for different options for each configured endpoint.

GraphQLHttpMiddlewareOptions
Property Description Default value
AuthorizationRequired Requires HttpContext.User to represent an authenticated user. False
AuthorizedPolicy If set, requires HttpContext.User to pass authorization of the specified policy.
AuthorizedRoles If set, requires HttpContext.User to be a member of any one of a list of roles.
CsrfProtectionEnabled Enables cross-site request forgery (CSRF) protection for both GET and POST requests. True
CsrfProtectionHeaders Sets the headers used for CSRF protection when necessary. GraphQL-Require-Preflight
DefaultResponseContentType Sets the default response content type used within responses. application/graphql-response+json; charset=utf-8
EnableBatchedRequests Enables handling of batched GraphQL requests for POST requests when formatted as JSON. True
ExecuteBatchedRequestsInParallel Enables parallel execution of batched GraphQL requests. True
HandleGet Enables handling of GET requests. True
HandlePost Enables handling of POST requests. True
HandleWebSockets Enables handling of WebSockets requests. True
MaximumFileSize Sets the maximum file size allowed for GraphQL multipart requests. unlimited
MaximumFileCount Sets the maximum number of files allowed for GraphQL multipart requests. unlimited
ReadExtensionsFromQueryString Enables reading extensions from the query string. True
ReadFormOnPost Enables parsing of form data for POST requests (may have security implications). False
ReadQueryStringOnPost Enables parsing the query string on POST requests. True
ReadVariablesFromQueryString Enables reading variables from the query string. True
ValidationErrorsReturnBadRequest When enabled, GraphQL requests with validation errors have the HTTP status code set to 400 Bad Request. Automatic[^1]
WebSockets Returns a set of configuration properties for WebSocket connections.

[^1]: Automatic mode will return a 200 OK status code when the returned content type is application/json; otherwise 400 or as defined by the error.

GraphQLWebSocketOptions
Property Description Default value
ConnectionInitWaitTimeout The amount of time to wait for a GraphQL initialization packet before the connection is closed. 10 seconds
DisconnectionTimeout The amount of time to wait to attempt a graceful teardown of the WebSockets protocol. 10 seconds
DisconnectAfterErrorEvent Disconnects a subscription from the client if the subscription source dispatches an OnError event. True
DisconnectAfterAnyError Disconnects a subscription from the client if there are any GraphQL errors during a subscription. False
KeepAliveMode The mode to use for sending keep-alive packets. protocol-dependent
KeepAliveTimeout The amount of time to wait between sending keep-alive packets. disabled
SupportedWebSocketSubProtocols A list of supported WebSocket sub-protocols. graphql-ws, graphql-transport-ws

Multi-schema configuration

You may use the generic versions of the various builder methods to map a URL to a particular schema.

var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseGraphQL<DogSchema>("/dogs/graphql");
app.UseGraphQL<CatSchema>("/cats/graphql");
await app.RunAsync();

Different global authorization settings for different transports (GET/POST/WebSockets)

You may register the same endpoint multiple times if necessary to configure GET connections with certain authorization options, and POST connections with other authorization options.

var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseGraphQL("/graphql", options =>
{
    options.HandleGet = true;
    options.HandlePost = false;
    options.HandleWebSockets = false;
    options.AuthorizationRequired = false;
});
app.UseGraphQL("/graphql", options =>
{
    options.HandleGet = false;
    options.HandlePost = true;
    options.HandleWebSockets = true;
    options.AuthorizationRequired = true;   // require authentication for POST/WebSocket connections
});
await app.RunAsync();

Since POST and WebSockets can be used for query requests, it is recommended not to do the above, but instead add the authorization validation rule and add authorization metadata on the Mutation and Subscription portions of your schema, as shown below:

builder.Services.AddGraphQL(b => b
    .AddSchema<MySchema>()
    .AddSystemTextJson()
    .AddAuthorizationRule()); // add authorization validation rule

var app = builder.Build();
app.UseDeveloperExceptionPage();
app.UseGraphQL();
await app.RunAsync();

// demonstration of code-first schema; also possible with schema-first or type-first schemas
public class MySchema : Schema
{
    public MySchema(IServiceProvider provider, MyQuery query, MyMutation mutation) : base(provider)
    {
        Query = query;
        Mutation = mutation;

        mutation.Authorize(); // require authorization for any mutation request
    }
}

Keep-alive configuration

By default, the middleware will not send keep-alive packets to the client. As the underlying operating system may not detect a disconnected client until a message is sent, you may wish to enable keep-alive packets to be sent periodically. The default mode for keep-alive packets differs depending on whether the client connected with the graphql-ws or graphql-transport-ws sub-protocol. The graphql-ws sub-protocol will send a unidirectional keep-alive packet to the client on a fixed schedule, while the