AyCode.Core/AyCode.Services/docs/MVC
Loretta 651e2a0b9f [LOADED_DOCS: 3 files, no new loads]
SIMD UTF-8 upgrades, i18n test data, MVC disabled

- Switch all test/benchmark data to Hungarian UTF-8 strings for i18n coverage
- Add AVX-512BW, Vector256, and Vector128 SIMD paths for UTF-8/UTF-16 encode/decode (ASCII and multi-byte) in binary serializer/deserializer
- Update WireMode docs for encoding guidance per workload/host
- Block-comment and disable MVC formatters and Microsoft.AspNetCore.App reference due to .NET 10 Hybrid client conflict; update docs to reflect temporary state
- Update appsettings: replace WaitForFlush with FlushPolicy
- Revise BINARY_TODO.md for SIMD transcoder progress and next steps
2026-05-05 15:06:11 +02:00
..
README.md [LOADED_DOCS: 3 files, no new loads] 2026-05-05 15:06:11 +02:00

README.md

MVC — AcBinary formatters

⚠️ TEMPORARILY DISABLED — formatter sources block-commented (/* ... */) and Microsoft.AspNetCore.App FrameworkReference removed from AyCode.Services.csproj (downstream net10.0 Hybrid client conflict on Microsoft.AspNetCore.Mvc namespace). Re-enable when split into a separate NuGet package / solution. Description below documents the intended state.

ASP.NET Core MVC InputFormatter / OutputFormatter pair for the AcBinary wire format. Works in controller-based MVC and Minimal API on .NET 9+. The wire payload is the raw byte[] produced by AcBinarySerializer.Serialize(value, opts) — bit-compatible with the single-shot byte[] API; no MVC-specific envelope.

Code: AyCode.Services/Mvc/ (AcBinaryInputFormatter, AcBinaryOutputFormatter, AcBinaryMvcBuilderExtensions) Binary serializer: ../../../AyCode.Core/AyCode.Core/docs/BINARY/README.md

Registration

// Program.cs
builder.Services.AddControllers()
    .AddAcBinaryFormatters(opts => {
        opts.UseGeneratedCode = true;
    });

AddAcBinaryFormatters inserts both formatters at index 0 of MvcOptions.InputFormatters / OutputFormatters — AcBinary wins content-negotiation when the client's Accept header allows.

Media Type

application/vnd.acbinary (vendor tree, registered with the IANA pattern but not yet IANA-listed). The same media type is sent on both request (Content-Type) and response.

Override via SupportedMediaTypes.Add(...) on a custom formatter instance if a project-specific type is needed.

Request flow (InputFormatter)

HttpContext.Request.Body                          (Stream)
  → PipeReader.Create(Body)                       (PipeReader)
  → drain-loop on calling thread:
       while (true) {
           result = await reader.ReadAsync(ct);
           foreach (segment in result.Buffer) input.Feed(segment.Span);
           reader.AdvanceTo(result.Buffer.End);
           if (result.IsCompleted) break;
       }
       input.Complete();
  ↑ background Task.Run feeds AcBinaryDeserializer.Deserialize(input, ModelType, opts)
  → ModelType instance → InputFormatterResult.Success

The drain-loop is inline in the formatter — the serializer surface ends at AsyncPipeReaderInput. Any I/O-specific draining (PipeReader, NamedPipe, FileStream, custom transport) is the consumer's responsibility.

Response flow (OutputFormatter)

HttpContext.Response.Body                         (Stream)
  → PipeWriter.Create(Body)                       (PipeWriter)
  → AcBinarySerializer.SerializeChunked(value, ObjectType, writer, opts)
       (raw mode — pure AcBinary bytes, no [201][UINT16] framing)
  → await pipeWriter.CompleteAsync()

SerializeChunked (not SerializeChunkedFramed) — the wire is a single self-contained AcBinary blob, identical to Serialize(value, opts) → byte[]. No multiplexed framing on the HTTP body.

Error model

Deserialization failure → ModelState.TryAddModelError(ModelName, ex.Message)InputFormatterResult.Failure(). ASP.NET pipeline emits 400 Bad Request with application/problem+json (RFC 7807) — not an AcBinary-encoded error. The client reads the error body as JSON.

OperationCanceledException (when RequestAborted is signalled) is rethrown so the pipeline aborts the response cleanly.

Cancellation

HttpContext.RequestAborted flows into both formatters. The InputFormatter passes it to PipeReader.ReadAsync and Task.Run; the OutputFormatter calls cancellationToken.ThrowIfCancellationRequested() after CompleteAsync. Mid-request abort releases all pooled resources via the using and finally blocks.

What the formatter does NOT include

  • No Stream-async API in the binary coreAcBinarySerializer has no SerializeAsync(Stream, T) method. The formatter is the wrapper. (See BINARY_TODO.md#accore-bin-t-t8k3 — parked.)
  • No options thread-safety guardAcBinarySerializerOptions is currently mutable; if registered as a DI singleton with Configure<> it is fine because Configure is read-only at runtime, but raw-shared mutable instances across concurrent requests are unsafe. (See BINARY_ISSUES.md#accore-bin-i-l8n5 and BINARY_TODO.md#accore-bin-t-b7h4.)
  • No OpenAPI metadata helpersMicrosoft.AspNetCore.OpenApi / Swashbuckle.AspNetCore pick up SupportedMediaTypes automatically; no extra integration needed.

Future work

The formatter currently lives in AyCode.Services (alongside the SignalR transport). The intent is to extract it into its own NuGet package — AyCode.AspNetCore.Mvc.Formatters.AcBinary — when the binary serializer is moved to a dedicated solution. No code change required at extraction time; only project-file split.