AyCode.Core/AyCode.Services/Mvc/AcBinaryInputFormatter.cs

85 lines
3.3 KiB
C#

// TEMPORARILY DISABLED: this file references Microsoft.AspNetCore.Mvc.* which collides with the
// downstream Hybrid client (FruitBankHybrid.Web.Client targets net10.0 and breaks on the
// AspNetCore.Mvc namespace). Re-enable when the binary serializer + MVC formatter is moved to
// its own solution / NuGet package. The FrameworkReference Microsoft.AspNetCore.App in
// AyCode.Services.csproj is also disabled in tandem.
/*
using System.IO.Pipelines;
using AyCode.Core.Serializers.Binaries;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Logging;
namespace AyCode.Services.Mvc;
/// <summary>
/// ASP.NET Core MVC InputFormatter for AcBinary wire format. Reads request body via PipeReader,
/// drains chunks into AsyncPipeReaderInput on the calling thread while a background task
/// deserializes incrementally, then returns the result. Standard ProblemDetails error flow on
/// failure (ModelState.AddModelError → 400 + application/problem+json).
/// </summary>
public class AcBinaryInputFormatter : InputFormatter
{
/// <summary>Vendor media type. <c>application/vnd.acbinary</c> by default.</summary>
public const string DefaultMediaType = "application/vnd.acbinary";
private readonly AcBinarySerializerOptions _options;
private readonly ILogger<AcBinaryInputFormatter>? _logger;
public AcBinaryInputFormatter(AcBinarySerializerOptions? options = null, ILogger<AcBinaryInputFormatter>? logger = null)
{
_options = options ?? AcBinarySerializerOptions.Default;
_logger = logger;
SupportedMediaTypes.Add(DefaultMediaType);
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
if (context is null) throw new ArgumentNullException(nameof(context));
var ct = context.HttpContext.RequestAborted;
var reader = PipeReader.Create(context.HttpContext.Request.Body);
try
{
using var input = new AsyncPipeReaderInput(_options.BufferWriterChunkSize * 2);
var deserTask = Task.Run(() => AcBinaryDeserializer.Deserialize(input, context.ModelType, _options), ct);
try
{
while (true)
{
var result = await reader.ReadAsync(ct).ConfigureAwait(false);
foreach (var segment in result.Buffer) input.Feed(segment.Span);
reader.AdvanceTo(result.Buffer.End);
if (result.IsCompleted) break;
}
}
finally
{
input.Complete();
}
var model = await deserTask.ConfigureAwait(false);
return await InputFormatterResult.SuccessAsync(model).ConfigureAwait(false);
}
catch (OperationCanceledException) when (ct.IsCancellationRequested)
{
throw;
}
catch (Exception ex)
{
_logger?.LogWarning(ex, "AcBinary deserialization failed for type {ModelType}", context.ModelType);
context.ModelState.TryAddModelError(context.ModelName ?? string.Empty, ex.Message);
return await InputFormatterResult.FailureAsync().ConfigureAwait(false);
}
finally
{
await reader.CompleteAsync().ConfigureAwait(false);
}
}
protected override bool CanReadType(Type type) => true;
}
*/