I'm facing a very weird issue working with a duplex service and an asp.net 4.0 webforms application that consumes the service.
In my development machine the code works fine, no errors, but testing the same code in my application testing server I'm getting System.Runtime.FatalException Message: Object reference not set to an instance of an object when I send a callback to the client.
My development machine is: Windows 8.1, IIS 8.5.
Testing server is a Virtual Machine on Azure: Windows Server 2008 Datacenter, IIS 7.5
Both, service and client application are: .NET Framework 4.0
To take in count and very weird thing is I tried to debug remotely the application on the VM and with remote debugging enabled the service behavior is ok, but once de-attached the debugger the error appears again.
So, the code is:
Service
[ServiceContract(CallbackContract = typeof(IProcessCallback))]
public interface IProcess
{
[OperationContract(IsOneWay = true)]
void Process(ProcessRequest request);
}
public interface IProcessCallback
{
[OperationContract(IsOneWay = true)]
void NotifyOk(string id, string message);
[OperationContract(IsOneWay = true)]
void NotifyError(string id, string message);
}
Service Implementation
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class Processor : IProcess
{
public void Process(ProcessRequest request)
{
try
{
//Some logic here...
var callbackChannel = GetCallback();
callbackChannel.NotifyOk(id, msg);
}
catch (Exception ex)
{
//Some error handling logic here...
var callbackChannel = GetCallback();
callbackChannel.NotifyError(id, msg);
}
}
private static IProcessCallback GetCallback()
{
return OperationContext.Current.GetCallbackChannel<IProcessCallback>();
}
}
In the asp.net client project I added a reference to the service using the wizard.
Code behind from the aspx page that consumes the service:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false, AutomaticSessionShutdown = false)]
public partial class LoadPage : System.Web.UI.Page, IProcessCallback
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnProcess_OnClick(object sender, EventArgs e)
{
try
{
var instanceContext = new InstanceContext(this);
var proxyDuplex = new ProcessorClient(instanceContext);
proxyDuplex.Process(new ProcessRequest());
}
catch (Exception ex)
{
//Some exception handling code here...
}
}
public void NotifyOk(string id, string msg)
{
//Some logic...
}
public void NotifyError(string id, string msg)
{
//Some logic...
}
}
This code works fine on development machine and also on the testing server if remote debugging is enabled.
I enabled WCF Tracing in both web.config (WCF Project and ASP.NET Project) and checking the log files with the tool "SvcTraceViewer.exe" I found that the error is ocurring in the ASP.NET Project when it's trying to process the callback:
XML info from the activity marked as exception (on .svclog file)
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>131075</EventID>
<Type>3</Type>
<SubType Name="Error">0</SubType>
<Level>2</Level>
<TimeCreated SystemTime="2015-07-16T16:51:44.9708260Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{06c345d5-3374-4692-98c6-0256c236f70d}" />
<Execution ProcessName="w3wp" ProcessID="4432" ThreadID="39" />
<Channel />
<Computer>SERVERWS2008R2</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error">
<TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier>
<Description>Throwing an exception.</Description>
<AppDomain>/LM/W3SVC/1/ROOT/MyApplication.Web-1-130815389967873315</AppDomain>
<Exception>
<ExceptionType>System.Runtime.FatalException, System.Runtime.DurableInstancing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</ExceptionType>
<Message>Object reference not set to an instance of an object.</Message>
<StackTrace>
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.Diagnostics.TraceUtility.<>c__DisplayClass4.<CallbackGenerator>b__2(AsyncCallback callback, IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.Runtime.InputQueue`1.Dispatch()
at System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(WsrmMessageInfo info)
at System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(IAsyncResult result)
at System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.ServiceModel.Channels.ReliableChannelBinder`1.InputAsyncResult`1.OnInputComplete(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.ServiceModel.Diagnostics.TraceUtility.<>c__DisplayClass4.<CallbackGenerator>b__2(AsyncCallback callback, IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.Runtime.InputQueue`1.Dispatch()
at System.Runtime.ActionItem.DefaultActionItem.Invoke()
at System.Runtime.ActionItem.CallbackHelper.InvokeWithoutContext(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<ExceptionString>System.Runtime.FatalException: Object reference not set to an instance of an object. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.HttpApplication.ThreadContext.Enter(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
at System.Web.AspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
--- End of inner exception stack trace ---</ExceptionString>
<InnerException>
<ExceptionType>System.NullReferenceException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>Object reference not set to an instance of an object.</Message>
<StackTrace>
at System.Web.HttpApplication.ThreadContext.Enter(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
at System.Web.AspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
</StackTrace>
<ExceptionString>System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.HttpApplication.ThreadContext.Enter(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
at System.Web.AspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)</ExceptionString>
</InnerException>
</Exception>
</TraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
I will appreciate your help
If someone in the future face the same problem this was the solution.
The error in my code was that I was creating the InstanceContext like this:
var instanceContext = new InstanceContext(this);
var proxyDuplex = new ProcessorClient(instanceContext);
And for the InstanceContext constructor it is required to pass as a parameter an instance of the class that is initializing the context, in my case it was the aspx page, so I used the class name of the page (LoadPage.aspx):
var instanceContext = new InstanceContext(new LoadPage());
var proxyDuplex = new ProcessorClient(instanceContext);
And that's it!