简体   繁体   English

WCF双工:FatalException在ASP.NET 4.0 Webforms客户端中接收回调

[英]WCF Duplex: FatalException receiving callback in ASP.NET 4.0 Webforms client

I'm facing a very weird issue working with a duplex service and an asp.net 4.0 webforms application that consumes the service. 我在使用双工服务和使用该服务的asp.net 4.0 Webforms应用程序时遇到一个非常奇怪的问题。

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. 在我的开发机器中,代码工作正常,没有错误,但是在我的应用程序测试服务器中测试了相同的代码,我得到了System.Runtime.FatalException消息:当我向回调函数发送回调时, 对象引用未设置为对象的实例客户。

My development machine is: Windows 8.1, IIS 8.5. 我的开发机器是:Windows 8.1,IIS 8.5。

Testing server is a Virtual Machine on Azure: Windows Server 2008 Datacenter, IIS 7.5 测试服务器是Azure上的虚拟机:Windows Server 2008数据中心,IIS 7.5

Both, service and client application are: .NET Framework 4.0 服务和客户端应用程序都是:.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. 算是一件很奇怪的事情,我试图在VM上远程调试应用程序,并且启用了远程调试,服务行为还可以,但是一旦断开调试器的连接,错误就会再次出现。

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. 在asp.net客户端项目中,我使用向导添加了对服务的引用。

Code behind from the aspx page that consumes the service: 使用该服务的aspx页面后面的代码:

[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: 我在web.config(WCF项目和ASP.NET项目)中都启用了WCF跟踪,并使用工具“ SvcTraceViewer.exe”检查了日志文件,我发现在尝试处理ASP.NET项目时,该错误发生在ASP.NET项目中打回来:

XML info from the activity marked as exception (on .svclog file) 来自活动的XML信息标记为异常(在.svclog文件上)

<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&amp; rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; 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.&lt;&gt;c__DisplayClass4.&lt;CallbackGenerator&gt;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.&lt;&gt;c__DisplayClass4.&lt;CallbackGenerator&gt;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. ---&gt; 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&amp; 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&amp; 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&amp; 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: 我代码中的错误是我正在创建InstanceContext,如下所示:

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): 对于InstanceContext构造函数,需要将初始化上下文的类的实例作为参数传递,在我的情况下是aspx页面,因此我使用了该页面的类名(LoadPage.aspx):

var instanceContext = new InstanceContext(new LoadPage());
var proxyDuplex = new ProcessorClient(instanceContext);

And that's it! 就是这样!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM