Cannot access a disposed object. Object name: 'tlsxyz' - c#

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.

Related

Azure Service Bus send message every other time

I've a c# dotnet webjob and a simple desktop app.
Sending a message apperaes to work only every other time.
serviceBusClient = new QueueClient(_config["ServiceBusConnectionString"], "queuename", ReceiveMode.ReceiveAndDelete);
await serviceBusClient.SendMigrationMessageAsync("1", label);
await serviceBusClient.SendMigrationMessageAsync("2", label);
await serviceBusClient.SendMigrationMessageAsync("3", label);
await serviceBusClient.SendMigrationMessageAsync("4", label);
SendMigrationMessageAsync is an extension:
public static async Task SendMigrationMessageAsync(this IQueueClient client, string messageText, string label)
{
Message message = new Message(Encoding.UTF8.GetBytes(messageText));
message.Label = label;
await client.SendAsync(message);
}
In the destkop app I registered to receive the message and also registered a message exception handler (which is not call at all).
In this scenario I can only receive message "2" and "4".
When I stopped execution after the first message had been sent, the message never showed up on the Azure service.
Thanks in advance
EDITED:
I found out that arter creating brand new Azure Service Bus Namespace, all is working fine.
I had basic pricing tier and even after upgrading to standard I was able to only send every other message.
Creating new service sorted this out.
Is there any limitation or throtling? I haven't sent many messages at all, something around 300 daily.
You most probably had two processes with the same subscription id, so they are "stealing" messages from each other. Let's say there are two console apps, the first one sending messages and the second one receiving.
With both having same subscription id it looks like this:
And with the unique subscription for each process everything is ok:

OWIN Store update, insert, or delete statement affected an unexpected number of rows (0) Error

I'm running into a very odd issue where the refresh token "disappears" after a few hours on an Azure App Service which hosts my Wep Api project. I've implemented OAuth for my password flow. Our AccessToken expires after 1 hour and our RefreshToken expires after one week.
For some background. This is happening on an Azure App service where i'm hosting my Web Api and a mobile front end is making calls to it (there are more than one users/mobile devices making a call to this app service).
Here's what a sample initial call looks like using /token call:
My grant_type is password. Normally i get back a refresh_token field along with the access_token, token_type and expires_in.
Works fine for the first few hours after i push to the app service then refresh_token disappears. I am truly stumped by this issue.
Here's my CreateAsync Code:
public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
var clientid = context.Ticket.Properties.Dictionary["as:client_id"];
if (string.IsNullOrEmpty(clientid))
{
return;
}
string refreshTokenId = await CreateRefreshTokenId(clientid, context);
if (refreshTokenId != null)
{
context.SetToken(refreshTokenId);
}
else
{
throw new Exception("refresh token could not be created");
}
}
private async Task<string> CreateRefreshTokenId(string clientId, AuthenticationTokenCreateContext context)
{
var ticket = context.Ticket;
var refreshTokenId = Guid.NewGuid().ToString("n");
var refreshTokenLifeTime = ConfigurationManager.AppSettings["as:clientRefreshTokenLifeTime"];
var token = new CreateRefreshTokenDTO
{
RefreshTokenId = refreshTokenId,
ClientId = clientId,
Subject = ticket.Identity.Name,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
};
ticket.Properties.IssuedUtc = token.IssuedUtc;
ticket.Properties.ExpiresUtc = token.ExpiresUtc;
token.ProtectedTicket = context.SerializeTicket();
var result = await createRefreshTokenManager.ManagerRequest(new CreateRefreshTokenRequest
{
RefreshToken = token
});
return result.IsError ? null : refreshTokenId;
}
I've added the exception in the else statement to see if it will throw and exception and it does in fact throw, which leads me to believe that the refreshTokenId is null. I've also added logging to a log table but for whatever reason, when this error is thrown it should save to the DB table (which i've tested locally and works) but on the App server it is not saving to the table. Very perplexing... UPDATE: PLEASE SEE UPDATE BELOW ON WHY NO LOGS WERE SAVING
Then, what is supposed to happen after this is that now that the front end (mobile, in this case) has the access and refresh tokens, when the access token expires, another call is made to /token but with grant_type = refresh_token:
UPDATE
Eventually I was able to reproduce the issue locally through trial and error and waiting for access token to expire (not entirely sure). But in any case, I was able to produce this error:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.
This error was the reason i was not able to save any logs to the DB.
Im using Castle Windsor as my IoC and EF6.
My calls are in this order:
1] Attempt to validate the context. In here i make another await call to a LoginUserManager where I basically get and verify user info
// This is used for validating the context
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
2] CreateAsync for creating access and refresh tokens from Context
public async Task CreateAsync(AuthenticationTokenCreateContext context)
Inside CreateAsync I make an await call CreateOrUpdateRefreshTokenManagerwhich either does an Update if entry exists or a Create. And ultimately make a SaveChanges(). This SaveChanges() is what causes the error If I don't call a SaveChanges() no entry is updated or created in that table. This is odd because in other parts of my code i dont call SaveChanges() at all at the end of the web request lifecycle yet an update/create/delete is made. Im assuming that EF/Windsor handles the saving for me.
My thoughts is that because this flow is different from all my other endpoints and that its handling two Async calls that somewhere in between I am disposing the DbContext and that is maybe why im seeing it failing on the second (CreateAsync) call. Not sure, just my thought here.
Anyway, sorry for the long winded post here. I wanted to post as much info as possible and am hoping that this may also help someone else facing this or similar issue.
Thanks!
UPDATE 2
I've noticed that after getting this error on /token call, any other (AllowAnonymous) calls i make work - even those that involve the DB. But the /token call in particular no longer works. My only way around this is to restart the server.
UPDATE 3
I was able to reproduce this issu ONLY on mobile testing (linked to Azure server) but cannot reproduce locally. Steps I used to reproduce:
Log in with one account
Logout
Log in with another account
Logout
Log in with the first account I tried) - This FAILS
Alright ya'll I was able to figure out this issue and i'll do my best to describe what was happening here.
For those of you who have followed a tutorial such as this one or any other similar one, you'll see that you basically have some repository structure set up along with maybe your own context which you inherit the base context, right?
In my case, I was handling the Dispose of the context at the end of the request by overriding the Dispose(bool disposing) method found in the ApiController class. If you're building a WebApi, you'll know what im talking about because any controllers you write inherit this. And if you've got some IoC set up with Lifetimes set to the end of a request, it'll dispose there :)
However, in this case of the /token call I noticed that we were never hitting any controllers...or at least none that utilized ApiController so i couldn't even hit that Dispose method. That meant that the context stayed "active". And in my second, third, fourth, etc calls to /token endpoint, I noticed in the watcher that the context calls were building up (meaning it was saving prior edits to the context i made from previous /token calls - they were never getting disposed! Thus making the context stale).
Unfortunately, the way around this for my situation was to wrap any context calls made within the /token request in a using statement, that way i knew after the using finished up it would dispose properly. And this seemed to work :)
So if you've got a similar project laid out to mine or similar to that tutorial i shared you may run into this issue.

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.

How to recover WCF client after WCF service restart?

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.

Categories