IClientChannel antipattern - c#

I've just spend 4 hours (it's 3am in the UK) trying to debug ASP.NET application which caused an exception in a thread managed by Framework (i.e. not my thread). I've just found out that a result from the static method ChannelFactory.CreateChannel can be cast to IClientChannel and explicitly Disposed. I mean that's all fine and nice but why:
1) ChannelFactory.CreateChannel does not return IClientChannel as an out parameter?
2) .Net documentation for CreateChannel does not mention it?
3) .Net documentation does not show a proper usage pattern in examples (no dispose code)?
Don't get me wrong - I love .Net framework. Microsoft (and Krzysztof Cwalina: see Designing Framework Guidelines) has done a really great job. That's why I didn't expect a such disaster. I mean how the hell I should know that my IMyService variable also supports IClientChannel and I should explicitly dispose it?
Here is an ASP.NET log if someone is interested.
Event Type: Error
Event Source: ASP.NET 2.0.50727.0
Event Category: None
Event ID: 1334
Date: 12/08/2009
Time: 01:55:47
User: N/A
Computer: WLGH3GIS
Description:
An unhandled exception occurred and the process was terminated.
Application ID: /LM/W3SVC/1/Root/Maps
Process ID: 3044
Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
StackTrace: at System.Threading.Overlapped.Free(NativeOverlapped* nativeOverlappedPtr)
at System.ServiceModel.Channels.OverlappedContext.Free()
at System.ServiceModel.Channels.PipeConnection.CloseHandle(Boolean abort, String timeoutErrorString, TransferOperation transferOperation)
at System.ServiceModel.Channels.PipeConnection.Close(TimeSpan timeout)
at System.ServiceModel.Channels.BufferedConnection.Close(TimeSpan timeout)
at System.ServiceModel.Channels.ConnectionPool.CloseItem(IConnection item, TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationPool`2.EndpointConnectionPool.CloseItem(TItem item, TimeSpan timeout)
at System.ServiceModel.Channels.IdlingCommunicationPool`2.IdleTimeoutEndpointConnectionPool.CloseItem(TItem item, TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationPool`2.EndpointConnectionPool.CloseIdleConnection(TItem connection, TimeSpan timeout)
at System.ServiceModel.Channels.IdlingCommunicationPool`2.IdleTimeoutEndpointConnectionPool.IdleTimeoutIdleConnectionPool.OnIdle()
at System.ServiceModel.Channels.IdlingCommunicationPool`2.IdleTimeoutEndpointConnectionPool.IdleTimeoutIdleConnectionPool.OnIdle(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2()
at System.Security.SecurityContext.Run(SecurityContext securityContext, ContextCallback callback, Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke()
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks()
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state)
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

Karol, I know this is a bit old, but I wanted to say thank you. Your post really helped me out.
The symptom I had was that when I tried to Close a ChannelFactory on the Server, it would always give a Timeout, regardless of the length of timespan I set for OpenTimeout, ReceiveTimeout, SendTimeout, InactivityTimeout, or CloseTimeout.
The solution was actually on the client, to cast the IMyServiceInterface that was returned by ChannelFactory.CreateChannel to ICommunicationObject. Then, it can be passed nicely to the Util.SafeCloseAndDispose(ICommunicationObject) method that you see copy and pasted all over the web.
After I did that on my client, then the Server's ChannelFactory can be closed in only a second or two, with no more timeout.
As far as I know, this insight from Karol's post is one of the only places online where this problem is spelled out.
Thanks again, Karol! :)

Related

ERROR NServiceBus.Transports.Msmq.MsmqDequeueStrategy - Error in receiving messages

Event Viewer on my workstation have the following error log:
ERROR NServiceBus.Transports.Msmq.MsmqDequeueStrategy [(null)] - Error in receiving messages.
System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.Transactions.TransactionManagerCommunicationException: Communication with the underlying transaction manager has failed. ---> System.Runtime.InteropServices.COMException: The Transaction Manager is not available. (Exception from HRESULT: 0x8004D01B)
at System.Transactions.Oletx.IDtcProxyShimFactory.ConnectToProxy(String nodeName, Guid resourceManagerIdentifier, IntPtr managedIdentifier, Boolean& nodeNameMatches, UInt32& whereaboutsSize, CoTaskMemHandle& whereaboutsBuffer, IResourceManagerShim& resourceManagerShim)
at System.Transactions.Oletx.DtcTransactionManager.Initialize()
--- End of inner exception stack trace ---
at System.Transactions.Oletx.OletxTransactionManager.ProxyException(COMException comException)
at System.Transactions.Oletx.DtcTransactionManager.Initialize()
at System.Transactions.Oletx.DtcTransactionManager.get_ProxyShimFactory()
at System.Transactions.Oletx.OletxTransactionManager.CreateTransaction(TransactionOptions properties)
at System.Transactions.TransactionStatePromoted.EnterState(InternalTransaction tx)
--- End of inner exception stack trace ---
at System.Transactions.TransactionStateAborted.CheckForFinishedTransaction(InternalTransaction tx)
at System.Transactions.Transaction.Promote()
at System.Transactions.TransactionInterop.ConvertToOletxTransaction(Transaction transaction)
at System.Transactions.TransactionInterop.GetDtcTransaction(Transaction transaction)
at System.Messaging.MessageQueue.StaleSafeReceiveMessage(UInt32 timeout, Int32 action, MQPROPS properties, NativeOverlapped* overlapped, ReceiveCallback receiveCallback, CursorHandle cursorHandle, IntPtr transaction)
at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
at System.Messaging.MessageQueue.Receive(TimeSpan timeout, MessageQueueTransactionType transactionType)
at NServiceBus.Transports.Msmq.MsmqDequeueStrategy.TryReceiveMessage(Func`1 receive, Message& message) in C:\BuildAgent\work\3206e2123f54fce4\src\NServiceBus.Core\Transports\Msmq\MsmqDequeueStrategy.cs:line 332
Facts:
Distributed Transaction Coordinator (DTC) Component Service ==> DTC Enabled
Distributed Transaction Coordinator (DTC) Service ==> Running (referenced to Answered Stack Oveflow Question)
Realtek Audio Universal Service ==> Disabled (as per reference in Fix for 0x8004d01b)
Can anyone recommend a direction on how to check/troubleshoot the cause of the issue?
After long ardous hours, the issue I encountered boils down to permission issue. The services involved in DTC which uses credentials of LocalSystem do not have enough permission and blocked by company-imposed policy implemented on the server.
Unfortunately, I only managed to find an alternative or workaround by using account that have enough permissions to operate and manage the services involved (including custom services).
#gnud - Thanks a lot for your inputs giving me a direction for investigation and that help me continue move forward on my investigation. I appreciate the help. Thanks.

Azure Service Bus timeout exception with NancyFX

I have a NancyFX API, and when one of the endpoints is hit, I need to kick of a longer running asynchonous task that's decoupled from the endpoint itself. So I'm trying to use a Azure Service Bus queue.
I'm successfully writing a message to the queue when the NancyFX endpoint is hit. I can also successfully subscribe and read from the queue from something other than NancyFX (I tested from Linqpad).
However, if I try to subscribe from the NancyFX app, I get a timeout exception within a second or two from starting the app. I'm doing this in another thread which is kicked off from the NancyFX Bootstrapper.ApplicationStartup override.
I'm unsure why this would be different than doing it not in the NancyFX app. I can't see anything of relevance in the web.config file.
Below is the code I'm using to subscribe to the queue ...
var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("Main", AccessKey);
var factory = await MessagingFactory.CreateAsync("sb://myapp.servicebus.windows.net", tokenProvider);
var receiver = await factory.CreateMessageReceiverAsync("MyQueue");
receiver.OnMessage(bm =>
{
// Do something here
}, new OnMessageOptions
{
MaxConcurrentCalls = 1,
});
Below is the exception ...
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: A timeout has occurred during the operation. b6b8e25a-714f-4f55-8a79-91e390f47a96_G25 (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.TimeoutException: A timeout has occurred during the operation.
).
And here is the callstack when I caught it in the debugger ...
Microsoft.ServiceBus.dll!Microsoft.ServiceBus.Messaging.Sbmp.DuplexRequestBindingElement.DuplexRequestSessionChannel.ThrowIfFaultMessage(System.ServiceModel.Channels.Message wcfMessage) Line 463 C#
Microsoft.ServiceBus.dll!Microsoft.ServiceBus.Messaging.Sbmp.DuplexRequestBindingElement.DuplexRequestSessionChannel.HandleMessageReceived(System.IAsyncResult result) Line 313 C#
Microsoft.ServiceBus.dll!Microsoft.ServiceBus.Messaging.Sbmp.DuplexRequestBindingElement.DuplexRequestSessionChannel.OnMessageReceived(System.IAsyncResult result) Line 381 C#
System.ServiceModel.Internals.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) Unknown
System.ServiceModel.dll!System.ServiceModel.Channels.TransportDuplexSessionChannel.TryReceiveAsyncResult.OnReceive(System.IAsyncResult result) Unknown
System.ServiceModel.Internals.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) Unknown
System.ServiceModel.Internals.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) Unknown
System.ServiceModel.dll!System.ServiceModel.Channels.SynchronizedMessageSource.ReceiveAsyncResult.OnReceiveComplete(object state) Unknown
System.ServiceModel.dll!System.ServiceModel.Channels.SessionConnectionReader.OnAsyncReadComplete(object state) Unknown
System.ServiceModel.Internals.dll!System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult result) Unknown
System.dll!System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) Unknown
System.dll!System.Net.LazyAsyncResult.ProtectedInvokeCallback(object result, System.IntPtr userToken) Unknown
System.dll!System.Net.Security._SslStream.ProcessFrameBody(int readBytes, byte[] buffer, int offset, int count, System.Net.AsyncProtocolRequest asyncRequest) Unknown
System.dll!System.Net.Security._SslStream.ReadFrameCallback(System.Net.AsyncProtocolRequest asyncRequest) Unknown
System.dll!System.Net.AsyncProtocolRequest.CompleteRequest(int result) Unknown
System.dll!System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(int bytes) Unknown
System.dll!System.Net.FixedSizeReader.ReadCallback(System.IAsyncResult transportResult) Unknown
System.ServiceModel.Internals.dll!System.Runtime.AsyncResult.Complete(bool completedSynchronously) Unknown
System.ServiceModel.dll!System.ServiceModel.Channels.ConnectionStream.IOAsyncResult.OnAsyncIOComplete(object state) Unknown
System.dll!System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(System.Net.Sockets.SocketAsyncEventArgs e) Unknown
System.dll!System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(System.Net.Sockets.SocketError socketError, int bytesTransferred, System.Net.Sockets.SocketFlags flags) Unknown
System.dll!System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) Unknown
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) Unknown
[Native to Managed Transition]
The exception you got is an indication of the client not being able to go past ASB gateway to talk to the backend. You could use the provided tracking ID (b6b8e25a-714f-4f55-8a79-91e390f47a96_G25) to open a support case. In case that exception persists, try a different namespace to see if that rules it out.

Entity Framework Model With Children in WCF Service works only once

To start off explaining, I have a model called VitalSign and one called VitalSignValues.
In my VitalSign model I have this code:
[ForeignKey("IdVitalSign")]
public virtual ICollection<VitalSignValue> VitalSignValues { get; set; }
In my VitalSignValue model:
public Guid IdVitalSign { get; set; }
And I got a default manager with basic functions like getAll(), ...
The project contains multiple web services and they all work fine, except for this one (VitalSignService). When I run the service, even with the WCF Test Client and I test the getAll function, it works.
The problem is that the getAll function only works like once, when I try to call the function again I suddenly get this error:
An error occurred while receiving the HTTP response to http://localhost/webservice/VitalSignService.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
I tried to check the trace logs, but for some reason the only information it gives me is:
ASP.Net hosted compilation
AppDomain unloading
Here is the error log (although it doesn't really contain good information for me)
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at IVitalSignService.GetAllVitalSigns()
at VitalSignServiceClient.GetAllVitalSigns()
Inner Exception:
The underlying connection was closed: An unexpected error occurred on a receive.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception:
An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
EDIT:
Here is some more information:
In my application, I call this function:
var client = new VitalSignServiceClient();
_vitalSigns = client.GetAllVitalSignsWithValues().ToList();
client.Close();
Inside of my service, I got this function:
public ICollection<VitalSign> GetAllVitalSignsWithValues()
{
return _vitalSignManager.GetAll("VitalSignValues");
}
In my generic manager, this happens:
public ICollection<TObject> GetAll(params string[] navigationProperties)
{
var query = Context.Set<TObject>().AsQueryable();
foreach (string navigationProperty in navigationProperties)
query = query.Include(navigationProperty);
var list = query.ToList<TObject>();
return list;
}
When I try to find the problem through debugging, it does go into the service, into the generic manager and it does get the VitalSigns, it's just the moment where the client retrieves the data from the web service that the error occurs and everything fails.
Also remember that all of this actually works (but only 1 out of 10 times, so probably only when the server refreshed it or something)
SOLVED: Removed the "virtual" in front of the IList
I don't like the way you're closing/disposing your WCF proxies and EF contexts. Looking for trouble there. Look into "using" like below. I would also recommend you don't use a static EF context. Again looking for trouble by doing this. (LinqToSql declare and instantiate DataContext best practice?). Third, I know it's tempting to make a generic repository that does everything but this ends up being more work than it's worth. For testing, performance and maintainability purposes, make your API calls specific.
Try:
using(var client = new VitalSignServiceClient()
{
_vitalSigns = client.GetAllVitalSignsWithValues().ToList();
}
public ICollection<VitalSign> GetAllVitalSigns()
{
using(ctx = new YourContext())
{
// do stuff
}
}

InstanceOwnerException when running Workflow Foundation 4

I am running Workflow 4 activities, and using SQL Durable Instancing to persist the Workflow when it's suspended. I am intermittently getting an InstanceOwnerException, which is remedied by recreating the instance store. Is there any way of avoiding this exception in the first place?
System.OperationCanceledException: An error processing the current work item has caused the workflow to abort. See the inner exception for details. ---> System.Runtime.DurableInstancing.InstanceOwnerException: The execution of an InstancePersistenceCommand was interrupted because the instance owner registration for owner ID '55413a1f-0e3f-4a0f-b2b0-54c121aa0c52' has become invalid. This error indicates that the in-memory copy of all instances locked by this owner have become stale and should be discarded, along with the InstanceHandles. Typically, this error is best handled by restarting the host.
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.Runtime.DurableInstancing.InstanceStore.EndExecute(IAsyncResult result)
at System.Activities.WorkflowApplication.UnloadOrPersistAsyncResult.OnPersisted(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.Activities.WorkflowApplication.UnloadOrPersistAsyncResult.Persist()
at System.Activities.WorkflowApplication.UnloadOrPersistAsyncResult.CollectAndMap()
at System.Activities.WorkflowApplication.UnloadOrPersistAsyncResult.Track()
at System.Activities.WorkflowApplication.UnloadOrPersistAsyncResult.InitializeProvider()
at System.Activities.WorkflowApplication.UnloadOrPersistAsyncResult..ctor(WorkflowApplication instance, TimeSpan timeout, PersistenceOperation operation, Boolean isWorkflowThread, Boolean isInternalPersist, AsyncCallback callback, Object state)
at System.Activities.WorkflowApplication.BeginInternalPersist(PersistenceOperation operation, TimeSpan timeout, Boolean isInternalPersist, AsyncCallback callback, Object state)
at System.Activities.WorkflowApplication.OnBeginPersist(AsyncCallback callback, Object state)
at System.Activities.Runtime.ActivityExecutor.PersistenceWaiter.PersistWorkItem.Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
--- End of inner exception stack trace ---
The code is running on Azure, using SQL Azure to persist the Workflows. There are roles that are accessing the same instance store.
This actually turned out to be down to attempting to resume a workflow after it had already finished.

Bizarre error with Response.Redirect

I get the following error when trying to use Response.Redirect in one of my ASP.NET pages:
[ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: offset]
System.Web.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count) +8858392
System.Web.HttpResponseStreamFilterSink.Write(Byte[] buffer, Int32 offset, Int32 count) +30
System.Web.HttpWriter.Filter(Boolean finalFiltering) +8754611
System.Web.HttpResponse.FilterOutput() +82
System.Web.ApplicationStepManager.ResumeSteps(Exception error) +501
System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +123
System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +379
I've never seen this before. It is happening if I Response.Redirect during the Page Load event.
Any Ideas?
EDIT: It's not my code, This is happening if I were to just stick Response.Redirect by itself in Page_Load.
EDIT #2: Using a 302 FOUND header works fine, but isn't that what response.redirect is supposed to do anyways?
This probably won't help much, but the exception itself is thrown inside HttpResponseStream.Write(byte[] buffer, int offset, int count), when either offset < 0 (which it isn't) or buffer length is zero. From what I understand, this could happen if buffered output is enabled and something managed to write a zero bytes into a stream.
I would try calling a Flush before doing the redirect and experiment with the second parameter. I would also check the web.config for any custom filter registration (unlikely though). Also make sure that your target application does not have asynchronous page processing, which could cause a havoc.
Apparently other people have been getting similar error, but usually when writing their own filters. I would end up debugging on the assembler level...
I would review the code of the destination page carefully (since you comment the error is happening there). It is probably using something that depends on the request. I have never seen a similar error, but it really looks like you should be focusing on any special stuff that page is doing.

Categories

Resources