Skip to content

Instantly share code, notes, and snippets.

@cobysy
Last active September 11, 2020 13:31
Show Gist options
  • Save cobysy/578302d0f4f5b895f459 to your computer and use it in GitHub Desktop.
Save cobysy/578302d0f4f5b895f459 to your computer and use it in GitHub Desktop.
Fix of JsonMediaTypeFormatter (ASP.net WebAPI) that does not convert JSON to object when Request is in Chunked Transfer Encoding.
/// <summary>
/// Fix of JsonMediaTypeFormatter that does not convert JSON to object when Request is in Chunked Transfer Encoding.
/// </summary>
public class XJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
/// <summary>
/// Replaces web api default JsonMediaTypeFormatter with this instance.
/// Usage:
/// protected void Application_Start()
/// {
/// ...
/// XJsonMediaTypeFormatter.FixConfiguration(GlobalConfiguration.Configuration);
/// ...
/// </summary>
/// <param name="configuration"></param>
public static void FixConfiguration(HttpConfiguration configuration)
{
var formatter = new XJsonMediaTypeFormatter
{
SerializerSettings =
{
NullValueHandling = NullValueHandling.Ignore
}
};
configuration.Formatters.Remove(configuration.Formatters.JsonFormatter);
configuration.Formatters.Add(formatter);
}
// From BaseJsonMediaTypeFormatter in Microsoft.AspNet.WebApi.Client.5.1.2\lib\net45\System.Net.Http.Formatting.dll
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
if (content.Headers.ContentLength.HasValue && content.Headers.ContentLength == 0)
// "Messages MUST NOT include both a Content-Length header field and a non-identity transfer-coding.
// If the message does include a non-identity transfer-coding, the Content-Length MUST be ignored."
// (RFC 2616, Section 4.4)
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html
// Fix for that the base-implementation defaults to 'default' value if Content-Length is 0.
content.Headers.ContentLength = new long?();
return base.ReadFromStreamAsync(type, readStream, content, formatterLogger);
}
}
/*
* "Long" version
*
/// <summary>
/// Fix of JsonMediaTypeFormatter that does not convert JSON to object when Request is in Chunked Transfer Encoding.
/// </summary>
public class XJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
/// <summary>
/// Replaces web api default JsonMediaTypeFormatter with this instance.
/// Usage:
/// protected void Application_Start()
/// {
/// ...
/// XJsonMediaTypeFormatter.FixConfiguration(GlobalConfiguration.Configuration);
/// ...
/// </summary>
/// <param name="configuration"></param>
public static void FixConfiguration(HttpConfiguration configuration)
{
var formatter = new XJsonMediaTypeFormatter
{
SerializerSettings =
{
NullValueHandling = NullValueHandling.Ignore
}
};
configuration.Formatters.Remove(configuration.Formatters.JsonFormatter);
configuration.Formatters.Add(formatter);
}
// From BaseJsonMediaTypeFormatter in Microsoft.AspNet.WebApi.Client.5.1.2\lib\net45\System.Net.Http.Formatting.dll
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
try
{
return Task.FromResult(ReadFromStream(type, readStream, content, formatterLogger));
}
catch (Exception ex)
{
//return TaskHelpers.FromError<object>(ex);
return FromError<object>(ex);
}
}
// From System.Threading.Tasks.TaskHelpers in Microsoft.AspNet.WebApi.Client.5.1.2\lib\net45\System.Net.Http.Formatting.dll
private static Task<TResult> FromError<TResult>(Exception exception)
{
TaskCompletionSource<TResult> completionSource = new TaskCompletionSource<TResult>();
completionSource.SetException(exception);
return completionSource.Task;
}
// From BaseJsonMediaTypeFormatter in Microsoft.AspNet.WebApi.Client.5.1.2\lib\net45\System.Net.Http.Formatting.dll
private object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var contentHeaders = content == null ? null : content.Headers;
var effectiveEncoding = SelectCharacterEncoding(contentHeaders);
try
{
var res = ReadFromStream(type, readStream, effectiveEncoding, formatterLogger);
return res;
}
catch (Exception ex)
{
if (formatterLogger == null)
throw;
formatterLogger.LogError(string.Empty, ex);
return GetDefaultValueForType(type);
}
}
/*
* BaseJsonMediaTypeFormatter.ReadFromStream implementation here only for reference
*
private object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
HttpContentHeaders contentHeaders = content == null ? (HttpContentHeaders)null : content.Headers;
if (contentHeaders != null)
{
long? contentLength = contentHeaders.ContentLength;
if ((contentLength.GetValueOrDefault() != 0L ? 0 : (contentLength.HasValue ? 1 : 0)) != 0)
return MediaTypeFormatter.GetDefaultValueForType(type);
}
Encoding effectiveEncoding = this.SelectCharacterEncoding(contentHeaders);
try
{
return this.ReadFromStream(type, readStream, effectiveEncoding, formatterLogger);
}
catch (Exception ex)
{
if (formatterLogger == null)
{
throw;
}
else
{
formatterLogger.LogError(string.Empty, ex);
return MediaTypeFormatter.GetDefaultValueForType(type);
}
}
}
*/
}
*/
@amd989
Copy link

amd989 commented Sep 27, 2019

This saved me!! Thanks for sharing this! Two days hunting down the issue, and it turned out to be this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment