Tengo una aplicación de API Web .NET MVC 4 estándar bastante pantanosa.¿Cómo habilito una API web .Net para aceptar publicaciones g-ziped?
public class LogsController : ApiController
{
public HttpResponseMessage PostLog(List<LogDto> logs)
{
if (logs != null && logs.Any())
{
var goodLogs = new List<Log>();
var badLogs = new List<LogBad>();
foreach (var logDto in logs)
{
if (logDto.IsValid())
{
goodLogs.Add(logDto.ToLog());
}
else
{
badLogs.Add(logDto.ToLogBad());
}
}
if (goodLogs.Any())
{
_logsRepo.Save(goodLogs);
}
if(badLogs.Any())
{
_logsBadRepo.Save(badLogs);
}
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
Todo funciona bien, tengo dispositivos que pueden enviarme sus registros y funciona bien. Sin embargo, ahora estamos empezando a preocuparnos por el tamaño de los datos que se transfieren, y queremos echar un vistazo a la aceptación de publicaciones que se han comprimido con GZIP.
¿Cómo podría hacer esto? ¿Está configurando IIS o podría usar filtros de acción?
EDIT 1
seguimiento de Filip de responder a mi pensamiento es que necesito para interceptar el procesamiento de la solicitud antes de que llegue al controlador. Si puedo capturar la solicitud antes de que el marco API web intente analizar el cuerpo de la solicitud en mi objeto comercial, que falla porque el cuerpo de la solicitud todavía está comprimido. Luego puedo descomprimir el cuerpo de la solicitud y luego volver a pasar la solicitud a la cadena de procesamiento, y con suerte el marco web API podrá analizar el cuerpo (descomprimido) en mis objetos comerciales.
Parece que usar DelagatingHandler es el camino a seguir. Me permite acceder a la solicitud durante el procesamiento, pero antes de mi controlador. ¿Entonces intenté lo siguiente?
public class gZipHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
string encodingType = request.Headers.AcceptEncoding.First().Value;
request.Content = new DeCompressedContent(request.Content, encodingType);
return base.SendAsync(request, cancellationToken);
}
}
public class DeCompressedContent : HttpContent
{
private HttpContent originalContent;
private string encodingType;
public DeCompressedContent(HttpContent content, string encodType)
{
originalContent = content;
encodingType = encodType;
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override Task<Stream> CreateContentReadStreamAsync()
{
return base.CreateContentReadStreamAsync();
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
Stream compressedStream = null;
if (encodingType == "gzip")
{
compressedStream = new GZipStream(stream, CompressionMode.Decompress, leaveOpen: true);
}
return originalContent.CopyToAsync(compressedStream).ContinueWith(tsk =>
{
if (compressedStream != null)
{
compressedStream.Dispose();
}
});
}
}
}
Esto parece estar funcionando bien. Se llama al método SendAsync antes de que se llame a mi controlador y al constructor para DecompressedContent. Sin embargo, nunca se llama a SerializeToStreamAsync, así que agregué el CreateContentReadStreamAsync para ver si es allí donde debería estar la descompresión, pero tampoco se está llamando.
Me siento como si estuviese cerca de la solución, pero solo necesito un poco más para poder pasar la línea.
¿Cómo comprimiste los datos JSON en el lado del cliente? Gracias. –