How to recover WCF client after WCF service restart? - c#

I've got static WCF client but I still can't understand how can I reset / recover it?
one of my tries:
if (Core.shed.State == CommunicationState.Faulted) {
Core.shed.Close();
Core.shed = new wcfClient();
}
Doesn't work, I'm still getting
Cannot access a disposed object. Object name: 'System.ServiceModel.Channels.ServiceChannel'.
How should I reset it when my wcf service is alive again?

You can't close a WCF channel that is faulted - you must abort it and create a new one. There is no way to recover that channel.
If you change this line of code from:
Core.shed.Close();
to:
Core.shed.Abort();
then the rest of your code should work.

Related

Cannot access a disposed object. Object name: 'tlsxyz'

I'm facing a random error when sending message from an Azure function to an Azure Service Bus (Standard) Topic.
the message error is:
Cannot access a disposed object. Object name: 'tls2576'., Stacktrace :
at Microsoft.Azure.ServiceBus.Core.MessageSender.OnSendAsync(IList1
messageList) at
Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func1 operation,
TimeSpan operationTimeout) at
Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func1 operation,
TimeSpan operationTimeout) at
Microsoft.Azure.ServiceBus.Core.MessageSender.SendAsync(IList1
messageList) at ServiceBusFunctions.MyTopic.Run(HttpRequest req,
ILogger log, ExecutionContext context) in myAzureFunction
sometimes the object name in the error is 'tls2716'.
The code is running from an Azure function instance containing 3 functions. Tere are 2 redundant functions APP containing the same code called in round robin from an Application Gateway. The client code to send messages to the topic is:
var message = new Message(Encoding.UTF8.GetBytes(requestBody));
//Custom properties for topis routing
message.UserProperties.Add("P1", P1);
message.UserProperties.Add("P2", P2);
message.UserProperties.Add("P3", P3);
ITopicClient topicClient = new TopicClient(SBConnectionString, CCTopicName);
await topicClient.SendAsync(message);
await topicClient.CloseAsync();
thanks for your help
The problem was closing the static topic client when a conccurent call is using it. the Fix is not to close the topicclient to reuse it and minimze the number of connection and tunning performance when open a connection
This happens due to accessing the disposed objected after clearing from memory.

MessageReceiver.RegisterMessageHandler throws exceptions continuously if network is down

I have successfully implemented a connection to ServiceBus with MessageReceiver using RegisterMessageHandler that starts a pump (from this example) and all seems to work just fine.
But in case of exception like e.g. when I turn off network connection the pump throws exceptions continuously to the ExceptionHandler. Every second or even faster. I am wondering if this is supposed default behavior and more importantly if it's possible to change, so that e.g. connection retries can happen every 1 minute. Or am I supposed to do Thread.Sleep or something to achieve that?
receiver.RegisterMessageHandler(
async (message, cancellationToken1) => await HandleMessage(receiver, message),
new MessageHandlerOptions(HandleException)
{
AutoComplete = false,
MaxConcurrentCalls = 1
});
P.S. This is how I solved it now, but not sure if it's a proper way:
private Task HandleException(ExceptionReceivedEventArgs args)
{
_logger.Error(...);
return Task.Delay(60000);
}
P.S Here is the RetryPolicy.Default dump:
Azure Service Bus has a default retry policy (RetryPolicy.Default), but given the transport is trying to receive messages and the broker is not available, will raise exceptions.
ExceptionReceivedContext provides a context, ExceptionReceivedContext which has an action that has failed, and the original exception. You can evaluate the action and decide what needs to be done. You could also check if the exception is transient or not. For transient errors, based on the action, you could just wait for the message to be retried again later (Receive action). In other cases you could either log an error or take a more specific action.
Try to configure the "RetryExponential" on your "SubscriptionClient" like this:
var receiver = new Microsoft.Azure.ServiceBus.SubscriptionClient(_serviceBusConnString, _topic, _subscription, this._receiveMode, new RetryExponential(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), _retryPolicyMaximumRetryCount));
This is the parameters descriptions:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.servicebus.retryexponential?view=azure-dotnet
Here other post about what the properties means:
ServiceBus RetryExponential Property Meanings

Azure and SignalR: System.Net.Sockets.SocketException: An attempt was made to access a socket in a way forbidden by its access permissions

I'm currently experiencing this issue at a high frequency:
System.Net.Sockets.SocketException: An attempt was made to access a
socket in a way forbidden by its access permissions
Sometimes it happens when connecting to Azure Storage from my web app (code below), but most of the time it happens with SignalR.
Based on debug diag, I see the following:
394 client connections in w3p.dmp have been executing a request for more than 90 seconds.
Based on the memory dump, there are a significant number of connections being made to /signalr/connect and /signalr/reconnect.
It looks like I'm using AspNet.SignalR.WebSockets.WebSocketHandler to make SignalR connections from within code. At this point I'm not sure what to look for though - what could be the culprit? We have a web service living in Azure, with web apps and mobile apps connecting to a SignalR backplane (redis).
Screen from debug diag
Code for Azure Storage
public void EnqueueRequest(int requestId)
{
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings.Get("AzureStorageConnectionString"));
// Create the queue client.
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
// Retrieve a reference to a queue.
CloudQueue queue = queueClient.GetQueueReference(ConfigurationManager.AppSettings.Get("requestQueueName"));
// Create a message and add it to the queue.
CloudQueueMessage message = new CloudQueueMessage(castingCallId.ToString(CultureInfo.InvariantCulture));
queue.AddMessage(message);
}
Hub Proxy Code
var baseUrl = _dbContext.CurrentTenant.BaseUrl;
_hubConnection = new HubConnection(baseUrl);
_hubProxy = _hubConnection.CreateHubProxy("appHub");
await _hubConnection.Start();
string serialized = null;
try
{
serialized = JsonSerializerExtensions.SerializeObject(data).SanitizeData();
await _hubProxy.Invoke((isTypingNotification ? "SendTypingNotification" : "SendClientNotification"), serialized, username);
}
catch (Exception exception)
{
LogError("1: " + exception);
}
SB2055 and I worked on this and made the following changes to eliminate this issue:
Do not create a HubConnection for each message to send. A HubConnection is a heavyweight object and should be created once and reused. You can recreate the IHubProxy multiple times if needed. You can accomplish this by setting the HubConnection as a class static member variable.
We changed the connection type from web sockets to long polling.

Rest to make call to another process just once in entire life cycle

say Rest service got one request which is giving a call to another service (email service),
but when Rest service got another request which is giving a call to email service I want it to skip that step.
also rest service should be intelligent enough to see if email process is being running or stopped if stopped any next request to rest service is allowed to call email service.
Rest Method : -
void SaveDataAndCallEmailService(Data data)
{
cntx.Add(data);
cntx.SaveChanges();
SendEmail();
}
now my query is how to make "SendMail()" method to be called only once only if Email Process is not running.
for e.g. : -
void SaveDataAndCallEmailService(Data data)
{
cntx.Add(data);
cntx.SaveChanges();
if(!EmailProcessIsRunning)
SendEmail();
EmailProcessIsRunning= true;
}
Edit: -
Now, here "EmailProcessIsRunning" is always false, even though I marked it as true.
When server receive second request I found "EmailProcessIsRunning" is false again.
How to persist it's value?
In your code sample EmailProcessIsRunning is not defined anywhere. Makes if more difficult to see if there's a scope issue.
Assuming there's no scope issues, if you want to persist the value saved to EmailProcessIsRunning between requests of on a stateless webapi server you'll need to add a DependecyResolver to your server. Read this for more information http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
edit: (a simpler answer)
You can add a static property to your class, and set it to true when the process is started.
e.g.
public bool static EmailProcessIsRunning { get; set; }

WCF Endpoint not found on first execution, found on second

I'll set the scene.
We have a set of WCF Service Hosts (S1, S2...Sn) that operate in a chain to process a received message, the first service does some processing and then hands the message to the next service which does some more processing and so on. A final WCF Service (U) receives the output of Sn and validates it.
The services S1, S2,...Sn are started via .exe files separately from the service U. Sevice U is started from Visual Studio 2010 from a Unit Test and once its started a message is fired into service s1 for processing. The problem we're seeing is that once service Sn attempts to pass the message to service U for validation we are presented with an error:
There was no endpoint listening at http://localhost:9005/ValidationService.svc
The strange thing is this error only occurs on the first run of the Unit Test. If we were to re-run the test after the initial failure the test would pass without issue (Sn successfully passing the message to U). However closing services S1, S2,...Sn restarting and re-running the unit test causes the "no endpoint listening at..." to be thrown again on the first run of the test.
My thoughts are that service U might still be completing its opening processes while service Sn tries to send a message to it, however I'm unconvinced, if this was the case how can we be sure service U is open and listening before firing a message into S1?
The service U is started by the following code:
public void TestChain()
{
var binding = new BasicHttpBinding();
// Construct service U
var serviceHostU = new ServiceHost(typeof(ChainContract), "http://localhost:9005");
serviceHostU.AddServiceEndpoint(typeof(ChainContractImplementation), binding, "ValidationService.svc");
serviceHostU.Open();
//fire message into service s1
var ep = new EndpointAddress("http://localhost:8777/InputService.svc");
var inputFactory = new ChannelFactory<ChainContract>(binding, ep);
var channel = inputFactory.CreateChannel();
//fire a message into service s1.
channel.ReceiveMessage(new TestMessage());
serviceHostU.Close();
}
Any help would be greatly appreciated.
I think your supposition that the first ServiceHost is initialising while the second one makes the call is probably correct.
To handle this, you could hook a delegate to the Opened event of your ServiceHost and run your second service from there.

Categories