# graphql-dotnet/server: an ASP.NET Core GraphQL transport layer

> graphql-dotnet/server packages GraphQL.NET behind ASP.NET Core middleware for HTTP and WebSocket GraphQL, with UI packages and a set of hosting samples. It is a thin transport concern, not a full schema framework, and it carries a package rename history that costs time on upgrade.

**graphql-dotnet/server** — ASP.NET Core GraphQL Server

- Repository: https://github.com/graphql-dotnet/server
- Stars: 601 · Forks: 165
- Language: C#
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/graphql-dotnet-server

## What graphql-dotnet/server adds on top of GraphQL.NET

The project describes itself simply as an ASP.NET Core GraphQL Server, and its README is explicit about the layering: the server sits on top of GraphQL.NET, the separate GraphQL.NET execution engine. That distinction matters for adoption. Schema definition, execution, data loaders and query complexity rules live in GraphQL.NET, while this repository supplies the hosting shell, the wire formats and the developer tooling around them.

The target audience is ASP.NET Core developers who have already decided to use GraphQL.NET and now need a way to expose an endpoint. The README states the package is designed for ASP.NET Core 2.1 through 9.0 and that the code is intended to be used as middleware within the ASP.NET Core pipeline. There is no standalone host, no CLI and no configuration file format of its own; the project is a library you reference and register in your own application.

Two protocol commitments shape the design. The HTTP transport is described as compatible with the GraphQL over HTTP draft specification, and the WebSocket transport is compatible with both the subscriptions-transport-ws and graphql-ws subscription protocols. The message transport format for all messages is expected to be JSON. Those two statements define what a client library written against either subscription protocol can expect from this server.

The repository layout is small and conventional: a solution file, a src directory for the packages, a tests directory, a docs directory and a samples directory. The MIT licence covers the code, and the licence file sits at the repository root, so there is no separate licensing question for each of the shipped NuGet packages.

## HTTP transport behaviour: GET, POST, form fields and raw queries

The mechanism is middleware, and the request handling rules are spelled out directly in the README. A GET request is processed from the query string. A POST request can arrive in three shapes: a JSON request, a form submission, or a raw GraphQL string.

The form submission shape has two accepted parameter sets. One form posts `query`, `operationName`, `variables` and `extensions`. The other posts `operations` and `map`, which is the batching convention that clients use to send several operations in a single HTTP call. In practice this means an existing GraphQL client that already speaks one of these two conventions can be pointed at the endpoint without a translation layer written by hand.

That breadth of accepted input shapes is the main reason to prefer this transport over a hand-rolled controller. The cost is that the request surface is wide, and the README does not document how the server distinguishes a JSON body from a raw GraphQL body when the content type is ambiguous, nor does it publish a request logging or tracing hook for the middleware.

One detail worth planning for is the batching parameter names. Because form posts use `operations` and `map`, a body parsing rule in an existing ASP.NET Core pipeline that assumes a single `query` field will reject batched requests. There is also no mention anywhere in the README of a maximum query depth setting, a persisted query feature or a request size limit, so those would have to be configured elsewhere in the pipeline.

## WebSocket transport and choosing between the two subscription protocols

Subscription support is handled over WebSocket, and the project is careful to support two different client protocols rather than picking one. The README states the WebSocket transport is compatible with both subscriptions-transport-ws and graphql-ws.

The two protocols are distinct client-side message conventions. A server that speaks both means a client library can be swapped without changing the server side. The trade-off is that the server carries two sets of message handlers, and the README does not document a configuration switch for enabling one and disabling the other, so both are presumably active by default.

The release history shows steady narrow releases through late 2025 (8.3.1 in September, 8.3.2 in October, 8.3.3 in November), which points at the transport code being maintained rather than frozen.

Because the message format for all messages is supposed to be JSON, a subscriber can parse frames without a binary decoder. The README does not describe what happens on reconnect, whether a missed subscription resumes, or how backpressure is handled when a subscriber cannot keep up with the event rate.

## Package layout, where the packages come from and the deprecated Playground UI

The project ships as a small set of NuGet packages so that you only reference the parts you need. The core transport package is GraphQL.Server.Transports.AspNetCore, which the README describes as providing GraphQL over HTTP and WebSocket server support on top of ASP.NET Core, plus authorization rule support. The GraphQL.Server.All package bundles all of the packages below it together with the GraphQL.DataLoader and GraphQL.MemoryCache packages, which is the convenient choice if you want one reference.

The remaining packages are UI middleware, one per browser-based GraphQL IDE:


```bash
GraphQL.Server.All
GraphQL.Server.Transports.AspNetCore
GraphQL.Server.Ui.Altair
GraphQL.Server.Ui.GraphiQL
GraphQL.Server.Ui.Voyager
```


Stable versions are published to NuGet. Preview builds are published to GitHub Packages, and the README states plainly that GitHub requires authentication to consume that feed. That authentication step is a real operational detail: a continuous integration pipeline that pulls a preview build needs a GitHub credential configured for the package feed, which is one more secret to manage than a plain NuGet restore.

The GraphQL.Server.Ui.Playground package carries a deprecation warning in the README table. The Altair, GraphiQL and Voyager packages do not. Anyone who adopted the older Apollo Playground era should plan a UI swap rather than carrying a deprecated package reference forward, since no further releases for it are indicated by the project.

## Upgrading from the 7.x-era package split

The README carries an explicit upgrade warning with a list of packages that should be removed when moving from prior versions. Leaving them in place risks ambiguous type resolution between the old and new assemblies, which is the kind of problem that shows up as a confusing runtime error rather than a compile error.


```bash
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
```


Two entries deserve attention. GraphQL.Server.Transports.AspNetCore.NewtonsoftJson and GraphQL.Server.Transports.AspNetCore.SystemTextJson were the split serialisation packages; a single transport package now covers the HTTP and WebSocket concerns, so which serialiser it uses internally is a decision made by the package rather than by you. The final entry, GraphQL.Server.Transports.WebSocktes, is misspelled in the upstream repository. That typo is preserved in the removal list, which is a useful sanity check: if you search your project file for the correctly spelled name you will find nothing, and you need the misspelling to locate the reference you must remove.

GraphQL.Server.Core and GraphQL.Server.Authentication.AspNetCore were the other two entries that fold into the current transport package. Anyone upgrading should diff their project references against this list before restoring, because a leftover reference is the most likely cause of an upgrade that compiles but misbehaves at run time.

## The samples tree as a map of supported hosting styles

The samples directory is the clearest signal of the range of hosting approaches the project supports, and it is worth reading before choosing an integration style. Each entry is a self-contained project:


```bash
samples/
src/
tests/
docs/
```


The names describe the decision space directly. Samples.Basic is the minimal case. Samples.Controller and Samples.EndpointRouting cover the two common ways to expose GraphQL inside an ASP.NET Core application: as an MVC controller action and as a mapped endpoint. Samples.Cors covers browser origins. Samples.Jwt and Samples.Authorization cover token handling and authorization rules, which matches the README statement that the transport package includes authorization rule support.

Several samples point at hosting decisions that are not obvious from the package list. Samples.MultipleSchemas and Samples.Schemas.Chat cover schema organisation. Samples.Pages covers a Razor Pages host. Samples.AzureFunctions covers running the GraphQL endpoint inside Azure Functions rather than a Kestrel-hosted application. Samples.NativeAot covers the ahead-of-time compiled deployment path, and Samples.Net48 covers the older .NET Framework target rather than modern .NET.

Samples.HttpResult and Samples.Upload cover specific request and response shapes: returning an HttpResult type from the GraphQL layer, and handling file uploads through the endpoint. This breadth is genuinely useful as a design reference, but it also shows that a single transport package now has to work across Kestrel, Azure Functions, Razor Pages, native ahead-of-time compilation and .NET Framework 4.8. That variety is a strength for reuse and a risk for surprises in any single one of those environments.

## Where the trade-offs sit, and the alternative integration path

The honest limitation is scope. This repository is a transport and hosting layer for GraphQL.NET, and it does not attempt to be a schema-first development framework, a code-first generator or a subscription event source. If your requirement is a single endpoint backed by a generated strongly typed client, or a query builder with persisted queries and depth limits, you will not find those here. The absence of documented depth limits, persisted queries and a query cost analyser in the README is the clearest boundary of what this package covers.

The main integration alternative is to host GraphQL.NET yourself behind an MVC controller or a minimal API endpoint. The difference in approach is direct: a hand-written controller gives you total control over routing, model binding and response headers, but you must implement the transport details yourself, including the batched `operations` and `map` form convention, the raw GraphQL body form and the WebSocket handshake for subscriptions. Using this middleware means those details are already handled and matched to the GraphQL over HTTP draft, at the cost of an extra layer between your application and the request, and the package rename work described above.

A second axis of choice is the subscription protocol. A client library written for subscriptions-transport-ws and one written for graphql-ws differ in handshake and message naming, and this project supports both on the server side, so the client side can be decided independently of the server.

On maintenance, the repository is not archived and the last push was on 2026-10-15. The three most recent releases are 8.3.3 on 2025-11-17, 8.3.2 on 2025-10-25 and 8.3.1 on 2025-09-28, and all three are narrow fixes rather than feature additions, which suggests a maintenance mode rather than an expansion phase.

## Conclusion

Teams already running GraphQL.NET on ASP.NET Core and needing GET, POST, form, and WebSocket transports with an included IDE will find this a low-friction fit, while teams wanting a full schema-first stack or a unified GraphQL endpoint should look elsewhere. Check the removal of the seven legacy packages first, then confirm your target framework sits inside the supported 2.1 through 9.0 range.

## FAQ

### Which ASP.NET Core versions does graphql-dotnet/server support?

The README states the package is designed for ASP.NET Core 2.1 through 9.0, and the samples directory includes a .NET Framework 4.8 sample in addition to the modern .NET targets.

### Does graphql-dotnet/server support GraphQL subscriptions over WebSocket?

Yes. The WebSocket transport is described as compatible with both the subscriptions-transport-ws and graphql-ws subscription protocols, with JSON as the message transport format.

### Which packages should I remove when upgrading from an older graphql-dotnet/server version?

The README lists seven packages to remove: 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 and GraphQL.Server.Transports.WebSocktes.

### Can I get preview builds of graphql-dotnet/server?

Yes. Stable versions are published to NuGet, while preview versions are published to GitHub Packages, and the README notes that GitHub requires authentication to consume that feed.

### Which browser GraphQL IDE does graphql-dotnet/server include?

Separate UI middleware packages are provided for Altair, GraphiQL and Voyager, plus a Playground UI package that the README marks as deprecated.

## Sources

- [graphql-dotnet/server on GitHub](https://github.com/graphql-dotnet/server)
- [Issues](https://github.com/graphql-dotnet/server/issues)
- [License: MIT](https://github.com/graphql-dotnet/server/blob/master/LICENSE)
- [README](https://github.com/graphql-dotnet/server/blob/master/README.md)
- [Releases](https://github.com/graphql-dotnet/server/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/graphql-dotnet-server
