Skip to content

Replaced ByteArrayType with Base64StringType and deprecated the former#9105

Merged
glen-84 merged 3 commits intomainfrom
gai/base64-string-type
Feb 10, 2026
Merged

Replaced ByteArrayType with Base64StringType and deprecated the former#9105
glen-84 merged 3 commits intomainfrom
gai/base64-string-type

Conversation

@glen-84
Copy link
Copy Markdown
Member

@glen-84 glen-84 commented Feb 10, 2026

Summary of the changes (Less than 80 chars)

  • Replaced ByteArrayType with Base64StringType and deprecated the former.

Copilot AI review requested due to automatic review settings February 10, 2026 10:23
@github-actions github-actions Bot added 📚 documentation This issue is about working on our documentation. 🌶️ hot chocolate 🌶️ strawberry shake labels Feb 10, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the Base64String scalar as the preferred GraphQL representation for .NET byte[], updates default runtime mapping accordingly, and deprecates the legacy ByteArray scalar/type across Hot Chocolate + Strawberry Shake, along with updating docs and test snapshots.

Changes:

  • Added Base64StringType and mapped byte[] to Base64String by default; marked ByteArrayType obsolete.
  • Updated Strawberry Shake code generation to treat Base64String as a built-in scalar.
  • Updated documentation, tests, and snapshots across Hot Chocolate/Adapters/Strawberry Shake to reflect the new scalar name.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
website/src/docs/strawberryshake/v16/scalars.md Updates Strawberry Shake scalar docs to list Base64String (and adjusts note formatting).
website/src/docs/hotchocolate/v16/migrating/migrate-from-15-to-16.md Adds migration guidance + deprecation note for ByteArrayBase64String.
website/src/docs/hotchocolate/v16/defining-a-schema/scalars.md Updates Hot Chocolate scalar docs and runtime binding example to Base64StringType.
src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/snapshots/ScalarGeneratorTests.Base64String_ScalarType.snap Adds snapshot for generated client code using Base64String.
src/StrawberryShake/CodeGeneration/test/CodeGeneration.CSharp.Tests/ScalarGeneratorTests.cs Adds a new codegen test for the Base64String scalar.
src/StrawberryShake/CodeGeneration/src/CodeGeneration/Utilities/SchemaHelper.cs Registers Base64String as a default scalar mapping (byte[]).
src/StrawberryShake/CodeGeneration/src/CodeGeneration/BuiltInScalarNames.cs Adds Base64String to Strawberry Shake codegen built-in scalar name set.
src/StrawberryShake/Client/src/Core/Serialization/BuiltInScalarNames.cs Adds Base64String constant and reorders built-in scalar name constants.
src/HotChocolate/Core/test/Types.Tests/Types/Scalars/ByteArrayTypeTests.cs Suppresses obsolete warnings for ByteArrayType tests.
src/HotChocolate/Core/test/Types.Tests/Types/Scalars/Base64StringTypeTests.cs Adds test coverage for the new Base64StringType.
src/HotChocolate/Core/test/Types.Tests/Configuration/SchemaTypeDiscoveryTests.cs Updates scalar discovery test expectations to Base64String.
src/HotChocolate/Core/test/Types.Json.Tests/snapshots/FromJsonDirectiveTests.MapField_AutomaticScalars.snap Updates snapshot to include base64String field output.
src/HotChocolate/Core/test/Types.Json.Tests/FromJsonDirectiveTests.cs Updates test schema/query/data to include Base64String.
src/HotChocolate/Core/src/Types/Types/Scalars/Scalars.cs Changes default CLR byte[] mapping to Base64StringType and registers scalar name mapping.
src/HotChocolate/Core/src/Types/Types/Scalars/ScalarNames.cs Adds Base64String scalar name constant and reorders constants.
src/HotChocolate/Core/src/Types/Types/Scalars/ByteArrayType.cs Marks ByteArrayType as obsolete.
src/HotChocolate/Core/src/Types/Types/Scalars/Base64StringType.cs Introduces the new scalar implementation for base64-encoded byte arrays.
src/HotChocolate/Core/src/Types/Configuration/TypeLookup.cs Updates comment examples to reference Base64String.
src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs Updates JSON inference to treat both Base64String and ByteArray similarly.
src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/TestSchema.cs Updates OpenAPI adapter test schema types/fields to Base64StringType.
src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApiTestBase.cs Updates OpenAPI adapter test query selections to include base64String.
src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApi/snapshots/OpenApiIntegrationTestBase.OpenApi_Includes_Initial_Routes_NET10_0_Fusion.json Updates OpenAPI snapshot output to include base64String schema.
src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/OpenApi/snapshots/OpenApiIntegrationTestBase.OpenApi_Includes_Initial_Routes_NET10_0.json Updates OpenAPI snapshot output to include base64String schema/pattern.
src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/snapshots/HttpEndpointIntegrationTestBase.Http_Post_Complex_Object.snap Updates endpoint response snapshot to include base64String field.
src/HotChocolate/Adapters/test/Adapters.OpenApi.Tests/Endpoints/HttpEndpointIntegrationTestBase.cs Updates endpoint request payload used in tests to include base64String.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/OperationToolFactoryTests.CreateTool_WithNullableVariables_CreatesCorrectSchema_Output.json Updates MCP schema snapshot to include base64String (nullable).
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/OperationToolFactoryTests.CreateTool_WithNullableVariables_CreatesCorrectSchema_Input.json Updates MCP schema snapshot inputs to include base64String (nullable).
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/OperationToolFactoryTests.CreateTool_WithNonNullableVariables_CreatesCorrectSchema_Output.json Updates MCP schema snapshot to include base64String (non-null).
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/OperationToolFactoryTests.CreateTool_WithNonNullableVariables_CreatesCorrectSchema_Input.json Updates MCP schema snapshot inputs to include base64String (non-null).
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/OperationToolFactoryTests.CreateTool_WithDefaultedVariables_CreatesCorrectSchema_Output.json Updates MCP schema snapshot to include base64String (defaulted).
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/OperationToolFactoryTests.CreateTool_WithDefaultedVariables_CreatesCorrectSchema_Input.json Updates MCP schema snapshot inputs to include base64String (defaulted).
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/IntegrationTestBase.CallTool_GetWithNullableVariables_ReturnsExpectedResult.json Updates integration result snapshot to include base64String.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/IntegrationTestBase.CallTool_GetWithNonNullableVariables_ReturnsExpectedResult.json Updates integration result snapshot to include base64String.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/IntegrationTestBase.CallTool_GetWithDefaultedVariables_ReturnsExpectedResult.json Updates integration result snapshot to include base64String.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/resources/GetWithNullableVariables.graphql Updates MCP resource query to use Base64String variable/field.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/resources/GetWithNonNullableVariables.graphql Updates MCP resource query to use Base64String variable/field.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/resources/GetWithDefaultedVariables.graphql Updates MCP resource query defaults to use Base64String.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/TestSchema.cs Updates MCP test schema runtime types/records to use Base64StringType.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/IntegrationTestBase.cs Updates tool invocation variable dictionaries to use base64String.
src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/Extensions/TypeExtensionsTests.cs Updates JSON-schema pattern tests to use Base64StringType.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/HotChocolate/Core/src/Types/Types/Scalars/Base64StringType.cs
Comment thread website/src/docs/strawberryshake/v16/scalars.md
Comment thread website/src/docs/strawberryshake/v16/scalars.md Outdated
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Fusion Gateway Performance Results

Simple Composite Query

Constant Load (50 VUs)

Requests/sec Error Rate
24966.54 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 1.63ms 43.12ms 1.96ms 3.68ms 4.54ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
19586.37 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 8.67ms 96.04ms 10.75ms 22.38ms 26.99ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
      }
    }
  }
}

Deep Recursion Query

Constant Load (50 VUs)

Requests/sec Error Rate
24332.16 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 1.66ms 45.72ms 2.01ms 3.80ms 4.67ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
19141.94 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 8.75ms 101.49ms 10.97ms 22.96ms 27.87ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  users {
    ...User
    reviews {
      ...Review
      product {
        ...Product
        reviews {
          ...Review
          author {
            ...User
            reviews {
              ...Review
              product {
                ...Product
              }
            }
          }
        }
      }
    }
  }
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
        reviews {
          ...Review
          product {
            ...Product
          }
        }
      }
    }
  }
}

Variable Batching Throughput

Constant Load (50 VUs)

Requests/sec Error Rate
27803.94 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 1.44ms 34.75ms 1.75ms 3.29ms 4.07ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
21772.32 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 7.17ms 106.95ms 9.40ms 19.96ms 24.21ms

Executed Query

query TestQuery_8f7a46ce_2(
  $__fusion_1_upc: ID!
  $__fusion_2_price: Long!
  $__fusion_2_weight: Long!
) {
  productByUpc(upc: $__fusion_1_upc) {
    inStock
    shippingEstimate(weight: $__fusion_2_weight, price: $__fusion_2_price)
  }
}

Variables (5 sets batched in single request)

[
  { "__fusion_1_upc": "1", "__fusion_2_price": 899, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "2", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 },
  { "__fusion_1_upc": "3", "__fusion_2_price": 15, "__fusion_2_weight": 20 },
  { "__fusion_1_upc": "4", "__fusion_2_price": 499, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "5", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 }
]

No baseline data available for comparison.


Run 21861037883 • Commit c518b76 • Tue, 10 Feb 2026 10:41:41 GMT

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 40 out of 40 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +308 to +315
private readonly global::StrawberryShake.Serialization.ILeafValueParser<global::System.Byte[], global::System.Byte[]> _base64StringParser;
public GetAttachmentBuilder(global::StrawberryShake.IEntityStore entityStore, global::StrawberryShake.IEntityIdSerializer idSerializer, global::StrawberryShake.IOperationResultDataFactory<global::Foo.Bar.IGetAttachmentResult> resultDataFactory, global::StrawberryShake.Serialization.ISerializerResolver serializerResolver)
{
_entityStore = entityStore ?? throw new global::System.ArgumentNullException(nameof(entityStore));
_idSerializer = idSerializer ?? throw new global::System.ArgumentNullException(nameof(idSerializer));
ResultDataFactory = resultDataFactory ?? throw new global::System.ArgumentNullException(nameof(resultDataFactory));
_base64StringParser = serializerResolver.GetLeafValueParser<global::System.Byte[], global::System.Byte[]>("Base64String") ?? throw new global::System.ArgumentException("No serializer for type `Base64String` found.");
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this generated snapshot, the result builder resolves a leaf value parser for type name "Base64String", but the DI setup later only registers ByteArraySerializer with its default type name ("ByteArray"). Unless ByteArraySerializer is also registered with type name "Base64String" (or a dedicated serializer exists), this client will throw at runtime when constructing the builder.

Copilot uses AI. Check for mistakes.
Comment on lines +229 to +233
TryAddLeafType(
leafTypes,
typeName: ScalarNames.Base64String,
runtimeType: TypeNames.ByteArray,
serializationType: TypeNames.ByteArray);
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base64String is now added as a default scalar mapping to byte[], but StrawberryShake’s built-in ByteArraySerializer registers under the ByteArray type name by default. The generated client code will request a leaf value parser for type name "Base64String" and can throw at runtime ("No serializer for type Base64String found.") unless a serializer is registered for that name. Consider adding a dedicated Base64StringSerializer (or registering ByteArraySerializer with typeName Base64String) in the DI/codegen path so both scalar names resolve correctly.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Fusion Gateway Performance Results

Simple Composite Query

Constant Load (50 VUs)

Requests/sec Error Rate
24995.16 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 1.62ms 42.38ms 1.96ms 3.67ms 4.55ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
19554.04 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 8.48ms 106.21ms 10.72ms 22.42ms 27.18ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
      }
    }
  }
}

Deep Recursion Query

Constant Load (50 VUs)

Requests/sec Error Rate
24344.74 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 1.66ms 44.38ms 2.01ms 3.76ms 4.67ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
19452.16 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 8.51ms 106.52ms 10.75ms 22.55ms 27.44ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  users {
    ...User
    reviews {
      ...Review
      product {
        ...Product
        reviews {
          ...Review
          author {
            ...User
            reviews {
              ...Review
              product {
                ...Product
              }
            }
          }
        }
      }
    }
  }
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
        reviews {
          ...Review
          product {
            ...Product
          }
        }
      }
    }
  }
}

Variable Batching Throughput

Constant Load (50 VUs)

Requests/sec Error Rate
27575.29 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 1.46ms 34.77ms 1.77ms 3.34ms 4.09ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
21901.74 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 7.24ms 103.96ms 9.47ms 20.02ms 24.66ms

Executed Query

query TestQuery_8f7a46ce_2(
  $__fusion_1_upc: ID!
  $__fusion_2_price: Long!
  $__fusion_2_weight: Long!
) {
  productByUpc(upc: $__fusion_1_upc) {
    inStock
    shippingEstimate(weight: $__fusion_2_weight, price: $__fusion_2_price)
  }
}

Variables (5 sets batched in single request)

[
  { "__fusion_1_upc": "1", "__fusion_2_price": 899, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "2", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 },
  { "__fusion_1_upc": "3", "__fusion_2_price": 15, "__fusion_2_weight": 20 },
  { "__fusion_1_upc": "4", "__fusion_2_price": 499, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "5", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 }
]

No baseline data available for comparison.


Run 21861931922 • Commit 7d10f68 • Tue, 10 Feb 2026 11:09:24 GMT

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 145 out of 176 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/HotChocolate/Core/src/Types/Types/Scalars/Base64StringType.cs
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Fusion Gateway Performance Results

Simple Composite Query

Constant Load (50 VUs)

Requests/sec Error Rate
24672.97 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 1.64ms 47.25ms 1.98ms 3.73ms 4.59ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
19355.51 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 8.66ms 108.77ms 10.88ms 22.78ms 27.60ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
      }
    }
  }
}

Deep Recursion Query

Constant Load (50 VUs)

Requests/sec Error Rate
24665.17 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 1.64ms 42.75ms 1.98ms 3.68ms 4.63ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
19233.33 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.09ms 8.70ms 114.01ms 10.87ms 22.66ms 27.64ms

Executed Query

fragment User on User {
  id
  username
  name
}

fragment Review on Review {
  id
  body
}

fragment Product on Product {
  inStock
  name
  price
  shippingEstimate
  upc
  weight
}

query TestQuery {
  users {
    ...User
    reviews {
      ...Review
      product {
        ...Product
        reviews {
          ...Review
          author {
            ...User
            reviews {
              ...Review
              product {
                ...Product
              }
            }
          }
        }
      }
    }
  }
  topProducts(first: 5) {
    ...Product
    reviews {
      ...Review
      author {
        ...User
        reviews {
          ...Review
          product {
            ...Product
          }
        }
      }
    }
  }
}

Variable Batching Throughput

Constant Load (50 VUs)

Requests/sec Error Rate
27800.58 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 1.45ms 42.71ms 1.75ms 3.30ms 4.08ms

Ramping Load (0→50→500→50 VUs)

Requests/sec Error Rate
21853.45 req/s 0.00%
📊 Response Time Metrics
Min Med Max Avg P90 P95
0.08ms 7.12ms 88.47ms 9.38ms 19.95ms 24.47ms

Executed Query

query TestQuery_8f7a46ce_2(
  $__fusion_1_upc: ID!
  $__fusion_2_price: Long!
  $__fusion_2_weight: Long!
) {
  productByUpc(upc: $__fusion_1_upc) {
    inStock
    shippingEstimate(weight: $__fusion_2_weight, price: $__fusion_2_price)
  }
}

Variables (5 sets batched in single request)

[
  { "__fusion_1_upc": "1", "__fusion_2_price": 899, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "2", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 },
  { "__fusion_1_upc": "3", "__fusion_2_price": 15, "__fusion_2_weight": 20 },
  { "__fusion_1_upc": "4", "__fusion_2_price": 499, "__fusion_2_weight": 100 },
  { "__fusion_1_upc": "5", "__fusion_2_price": 1299, "__fusion_2_weight": 1000 }
]

No baseline data available for comparison.


Run 21865584831 • Commit 4a28b8b • Tue, 10 Feb 2026 13:08:35 GMT

@glen-84 glen-84 merged commit 0a2b0a9 into main Feb 10, 2026
99 of 122 checks passed
@glen-84 glen-84 deleted the gai/base64-string-type branch February 10, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📚 documentation This issue is about working on our documentation. 🌶️ hot chocolate 🌶️ strawberry shake

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants