Azure CosmosDB SDK v3 with ASP.NET Web Forms - c#

I have an issue with the following code, working well in a Console App project and not working in a ASP.NET Web Forms project, both targeting .NET Framework 4.7.2.
The goal is to use the last Azure Cosmos DB SDK (v3) to get all documents in a container, without specifying a type (use of dynamic).
I've tried to target both the emulator (the last version 2.4.5) and the Azure Cosmos service.
In the ASP.NET project, the execution of queryResultSetIterator.ReadNextAsync().Result never ends (no timeout).
string endpointUri = "https://localhost:8081";
string primaryKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
string database = "SendGridEvents";
string collection = "SendGridEvents";
using (CosmosClient client = new CosmosClient(endpointUri, primaryKey))
{
Container container = client.GetDatabase(database).GetContainer(collection);
QueryDefinition queryDefinition = new QueryDefinition("SELECT * FROM c");
FeedIterator<dynamic> queryResultSetIterator = container.GetItemQueryIterator<dynamic>(queryDefinition);
List<dynamic> documents = new List<dynamic>();
while (queryResultSetIterator.HasMoreResults)
{
FeedResponse<dynamic> currentResultSet = queryResultSetIterator.ReadNextAsync().Result;
foreach (var document in currentResultSet)
{
documents.Add(document);
}
}
}

This is caused due to a deadlock because of the use of the problematic .Result.
There are countless of sources that explain this deadlock but I will link this answer from StackOverflow.
The TL;DR is that you are blocking an otherwise asynchronous call in the UI thread which is causing the deadlock. You need to properly await your call like this:
FeedResponse<dynamic> currentResultSet = await queryResultSetIterator.ReadNextAsync();
You could technically block the call if you used the ConfigureAwait(false) approach but the v3 SDK does not cascade this call all the way to the network calls so it wouldn't make any difference. WebForms allows you to have async handlers so you would be fine to make your method async and try again.

Related

Azure Function Net5 Async Probleme

I have a problem with azure function only when I publish.
the code run not in order, all the functions run at the same time.
ex :
var logger = context.GetLogger(nameof(MibProposalRequest));
logger.Log(LogLevel.Warning, $"Début de la fonction : MibProposalRequest {DateTime.UtcNow}");
try
{
var getStringResponse = await this.GetStringAsync(req, logger).ConfigureAwait(false);
if (getStringResponse.Error != null)
{
return new HttpResponseMessage()
{
StatusCode = getStringResponse.Error.StatusCode,
ReasonPhrase = getStringResponse.Error.Message
};
}
else
{
var requestBody = getStringResponse.Response.ToString();
var deserializeRequestBodyResponse = await this.DeserializeRequestBodyAsync(requestBody, logger).ConfigureAwait(false);
if (deserializeRequestBodyResponse.Error != null)
{
return new HttpResponseMessage()
{
StatusCode = deserializeRequestBodyResponse.Error.StatusCode,
ReasonPhrase = deserializeRequestBodyResponse.Error.Message
};
}
In this example I need to get the response of the function GETStringAsync and after go to the function : DeserializeRequestBodyAsync.
If I run the azure function in local (debug) it's all ok, everything it's in order.
First log the function start.
After Get the string
end deserializeObject.
But when I publish the function and I test it, when I'm loocking at the log in portal.azure.
All the function run not in good order.
So sometimes I get an error from deserializeObject function because no string to deserialize.
But its suppose to do the GetStringAsync function first.
Why this append?
Image of the log
as you can see the function start log is not the first to show up why ?
looks like all the code run completely not in order.
should be like this :
Log of vs debug
Everything is good each functions run in good order (so no problems)
Why this append only when the function is published ??
Ps: I tried to run the function not async but nothing change.
PS2: I tried to put all the code in the same function (Run) nothing changed.
PS3: I tried to put task.wait nothing changed.
I need help please 2 days I'm on this.
https://azure.microsoft.com/en-us/updates/general-availability-azure-functions-supports-net-5-in-production/?cdn=disable
From my experience this was a pain to get to work with Azure Functions on .NET 5. Either roll back to 3.1 or wait till 11/9/2021 for .NET 6 to release out of preview. .NEt 6 preview is allowed on Azure for testing.
Are you running .NET 5 in Azure in isolated mode? See link above.
"To support .NET 5, Azure Functions introduces a new isolated process model that runs .NET function apps in a separate worker process outside the Azure Functions host runtime."
I just found a solution in the code:
List<ProposalIdModel> list = (List<ProposalIdModel>)deserializeGuidsAsyncResponse.Response ?? new List<ProposalIdModel>();
Like this the list while never be null.
But it's wired in visual studio in debug no problem, but when I publish sometime the list get null.
So problem solved.
I also update to netCore6.

Cosmos DB - BulkExecutor InitializeAsync awaiting forever for the response

I am working on a Console Application to load multiple docs into Cosmos from CSV File through C# code. When I am debugging the code, the debugger stops at await bulkExecutor.InitializeAsync(); and waiting for the response forever.
Even when I am running the executables locally, I am facing the same issue.
But when I am creating the web job with the same code and deploy to Azure Portal, there it works seamlessly. For the same web job, i am again facing the same issue in local machine during debugging mode.
ConnectinMode - I have tried both Direct and Gateway but still no luck.
NOTE :
Microsoft.Azure.CosmosDB.BulkExecutor version 1.8.8
Microsoft.Azure.DocumentDB version 2.10.3
All NuGET Packages are uptodate
var client = new DocumentClient(new Uri(config.CosmosDbendpointUrl), config.CosmosDbAuthorizationKey,
new ConnectionPolicy { ConnectionMode = ConnectionMode.Gateway, ConnectionProtocol = Protocol.Tcp });
DocumentCollection dataCollection = null;
dataCollection = Utils.GetCollectionIfExists(client, config.CosmosDatabase, config.CosmosDBCollection);
if (dataCollection == null)
{
throw new Exception("The data collection does not exist");
}
// Set retry options high for initialization (default values).
client.ConnectionPolicy.RetryOptions.MaxRetryWaitTimeInSeconds = 30;
client.ConnectionPolicy.RetryOptions.MaxRetryAttemptsOnThrottledRequests = 9;
IBulkExecutor bulkExecutor = new BulkExecutor(client, dataCollection);
await bulkExecutor.InitializeAsync();
BulkExecutor has been deprecated and is no longer supported. If you are working on a new app and want bulk features use the .NET SDK v3 and set the AllowBulk = true in the client options.
You can find a sample here.
Thanks.

Microsoft Translator API work using console but not working within MVC

I have been able to get the Microsoft Translator API to work with creating a console project. I could only find examples with using console projects.
When trying to get the Translator API working within a controller I am not having any luck. I am using the same code.
Do I need to add some other type of reference to get the Translator to work with in MVC?
public async Task<string> GetAuthenticationToken(string key)
{
string endpoint = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "xxxxxxxxxxxxxxx501b7b1ce");
var response = await client.PostAsync(endpoint, null);
var token = await response.Content.ReadAsStringAsync();
return token;
}
}
Error Message
Is there any particular reason you have to create the console application first and then run it as such?
Instead of running the executable from your MVC project, I would recommend calling the TranslatorAsync() function instead.
My guess would be that the process.Start() and process.Close() calls are killing the process before it has a chance to do anything. However, without more specifics on how the function is failing, it's hard to give a better answer.
I had to change
TranslateAsync(productTest, getUserName).Wait;
to
await TranslateAsync(productTest, getUserName);
It’s working now.

How to track MongoDB requests from a console application

I have a Console Application project written in C# which I've added Application Insights to with the following NuGet packages.
Microsoft.ApplicationInsights
Microsoft.ApplicationInsights.Agent.Intercept
Microsoft.ApplicationInsights.DependencyCollector
Microsoft.ApplicationInsights.NLogTarget
Microsoft.ApplicationInsights.PerfCounterCollector
Microsoft.ApplicationInsights.Web
Microsoft.ApplicationInsights.WindowsServer
Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel
I've configured my InstrumentationKey in the config file and I'm firing up a TelemetryClient on startup using the with the following code:
var telemetryClient = new TelemetryClient();
telemetryClient.Context.User.Id = Environment.UserName;
telemetryClient.Context.Session.Id = Guid.NewGuid().ToString();
telemetryClient.Context.Device.OperatingSystem = Environment.OSVersion.ToString();
Everything is working well except AI is not capturing any requests that get sent to Mongo, I can see requests going off to SQL server in the 'Application map' but no sign of any other external requests. Is there any way that I can see telemetry of requests made to Mongo?
EDIT - Thanks to Peter Bons I ended up with pretty much the following which works like a charm and allows me to distinguish between success and failure:
var telemetryClient = new TelemetryClient();
var connectionString = connectionStringSettings.ConnectionString;
var mongoUrl = new MongoUrl(connectionString);
var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
mongoClientSettings.ClusterConfigurator = clusterConfigurator =>
{
clusterConfigurator.Subscribe<CommandSucceededEvent>(e =>
{
telemetryClient.TrackDependency("MongoDB", e.CommandName, DateTime.Now.Subtract(e.Duration), e.Duration, true);
});
clusterConfigurator.Subscribe<CommandFailedEvent>(e =>
{
telemetryClient.TrackDependency("MongoDB", $"{e.CommandName} - {e.ToString()}", DateTime.Now.Subtract(e.Duration), e.Duration, false);
});
};
var mongoClient = new MongoClient(mongoClientSettings);
I am not familiar with MongoDB but as far as I can tell there is no default support for it when it comes to Application Insights. But that does not mean you cannot do this, it will just involve some more code.
Again, I am not familiar with MongoDB but according to http://www.mattburkedev.com/logging-queries-from-mongodb-c-number-driver/ there is built-in support for logging the generated queries. Now, we only need to hook this up to Application Insights.
Since you already know how to use the TelemetryClient we can use the custom tracking methods provided by that class. See https://learn.microsoft.com/nl-nl/azure/application-insights/app-insights-api-custom-events-metrics for the available custom tracking methods.
All you need to do is to insert some code like this:
telemetryClient.TrackDependency(
"MongoDB", // The name of the dependency
query, // Text of the query
DateTime.Now, // Time that query is executed
TimeSpan.FromSeconds(0), // Time taken to execute query
true); // Indicates success
The class telemetryClient is thread-safe so you can reuse it.
Now, according to the referenced blogpost you should be able to do something like this:
var client = new MongoClient(new MongoClientSettings()
{
Server = new MongoServerAddress("localhost"),
ClusterConfigurator = cb =>
{
cb.Subscribe<CommandStartedEvent>(e =>
{
telemetryClient.TrackDependency(
"MongoDB", // The name of the dependency
e.Command.ToJson() // Text of the query
DateTime.Now, // Time that query is executed
TimeSpan.FromSeconds(0), // Time taken to execute query
true); // Indicates success
});
}
});
Again, I am not familiar with MongoDB but I hope this is a starting point for your imagination on how to adapt it to your needs using your knowledge of MongoDB.
EDIT:
If there is also a CommandCompletedEvent or similar event as opposed to the CommandStartedEvent event you should probably track the dependency there because you should then be able to calculate (or simpel read) the time spent and maybe get the actual value for the success indicator.

Analog of CRM 4 methods CrmService.CreateAsync(UpdateAsync) in CRM 2011

Is it possible to make asyncs calls, like it was in Crm 4
crmService.UpdateAsync(card, Guid.NewGuid());
in CRM 2011???
I have to do synchronization between CRM and some system with the help of SSIS.
In destination script component I'd like to use Async calls, but I don't want to write async calls on my own.
Thank you!!!
I've mainly worked with CRM 2011 (as opposed to CRM 4) but it sounds like you're about to deploy a plugin. If not, stop reading now. :)
If you are, you can set the type of call to asynchronous while registering your plugin in the PRT. Just click for the option.
You've also got another option. If you're running the newest .NET framework, there's a new keyword - async that executes the method asynchronously. And if you're targeting an older .NET version, don't despair - I used threads for a lengthy update and that worked out quite well too.
It could be answer for this question, but it's possible only in CRM 2011 UR 12
#region Execute Multiple with Results
// Create an ExecuteMultipleRequest object.
requestWithResults = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
// Create several (local, in memory) entities in a collection.
EntityCollection input = GetCollectionOfEntitiesToCreate();
// Add a CreateRequest for each entity to the request collection.
foreach (var entity in input.Entities)
{
CreateRequest createRequest = new CreateRequest { Target = entity };
requestWithResults.Requests.Add(createRequest);
}
// Execute all the requests in the request collection using a single web method call.
ExecuteMultipleResponse responseWithResults =
(ExecuteMultipleResponse)_serviceProxy.Execute(requestWithResults);
// Display the results returned in the responses.
foreach (var responseItem in responseWithResults.Responses)
{
// A valid response.
if (responseItem.Response != null)
DisplayResponse(requestWithResults.Requests[responseItem.RequestIndex], responseItem.Response);
// An error has occurred.
else if (responseItem.Fault != null)
DisplayFault(requestWithResults.Requests[responseItem.RequestIndex],
responseItem.RequestIndex, responseItem.Fault);
}
Code from MSDN

Categories

Resources