NRE when response has Content-Type but empty body
When a SOAP service returns no content but has a Content-Type set, WCF throws a NullReferenceException in HttpResponseMessageHelper. Leaving off Content-Type works fine.
Example HTTP response that reproduces the issue
HTTP/1.1 500
Content-Length: 0
Content-Type: text/xml; charset=UTF-8
Date: Thu, 05 Jul 2018 21:10:34 GMT
Connection: close
Expected Result
System.ServiceModel.CommunicationException : The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error."
Actual Result
System.NullReferenceException : Object reference not set to an instance of an object.
The NRE happens due to inputStream being null in HttpResponseMessageHelper.DecodeBufferedMessageAsync when it attempts to dispose it in the finally block.
The root cause however looks to be in ValidateContentTypeAsync. It doesn't properly handle this situation. It returns true (last line in the method) if the content type has a value and content length is 0, when it should be returning false. Its return value is saved in a hasContent variable in ParseIncomingResponse, so it definitely looks like it should be returning false if there's no content.
Thanks for reporting this @IGx89 we'll have someone take a look next week.
Would it be possible to fix this bug anytime soon? Since it is a very trivial fix and we'd like to avoid using our own custom build. The patch for the fix is below.
diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs
index 0c580539..f8407996 100644
--- a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs
+++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs
@@ -42,6 +42,7 @@ namespace System.ServiceModel.Channels
bool hasContent = await ValidateContentTypeAsync();
Message message = null;
+
if (!hasContent)
{
if (_encoder.MessageVersion == MessageVersion.None)
@@ -136,6 +137,11 @@ namespace System.ServiceModel.Channels
_contentLength = content.Headers.ContentLength.HasValue ? content.Headers.ContentLength.Value : -1;
}
+ if (content == null || _contentLength == 0)
+ {
+ return false;
+ }
+
if (string.IsNullOrEmpty(_contentType))
{
Stream contentStream = await GetStreamAsync();
@Lxiamail, when is this likely to be addressed? (I've just tested with the 4.7.0 version as I've seen the code has been changed and it seems to be working, so perhaps this one is not even an issue)
@mconnew did this issue get fixed as a side-effect of PR #3709?
@StephenBonikowsky, unfortunately no.
This looks like it would be a simple fix. We should consider it for 5.0.
Got a similar issue / identical exception in v4.8.1.
In my case, invoking an async operation, who's operation contract is marked as IsOneWay = true, but the server was returning Content-Type: application/soap+xml; charset=utf-8, with no body, which seems to be throwing things off.
System.NullReferenceException : Object reference not set to an instance of an object.
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass2_0.<CreateTask>b__0(IAsyncResult asyncResult)
--- End of stack trace from previous location ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Acme.Client.<Boom>d__2.MoveNext() in code\Client.cs:line 133
Got a similar issue / identical exception in v4.8.1.
In my case, invoking an async operation, who's operation contract is marked as
IsOneWay = true, but the server was returningContent-Type: application/soap+xml; charset=utf-8, with no body, which seems to be throwing things off.System.NullReferenceException : Object reference not set to an instance of an object. at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result) at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass2_0.<CreateTask>b__0(IAsyncResult asyncResult) --- End of stack trace from previous location --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Acme.Client.<Boom>d__2.MoveNext() in code\Client.cs:line 133
Getting the exact same issue here. Found a workaround?