I am writing a console app with .Net Core version 3.1. The purpose is to allow a user to access Microsoft OneDrive accounts and fiddle with them as desired. Getting past the authorizing stage is proving difficult. Here is a code snippet demonstrating what I have going:
//using statements
namespace HelloOneDrive
{
public class Program
{
static void Main(string[] args)
{
Task handleThing = (new Thing()).Handle();
}
}
public class Thing
{
public async Task Handle()
{
ClientCredentialProvider credentials;
string tenantId = //value
string clientId = //value
string clientSecret = //value
AuthenticationResult authResult;
string[] scopes = { "https://graph.microsoft.com/.default" };
CancellationToken cancellationToken = new CancellationToken();
GraphServiceClient client = null;
try
{
credentials = new ClientCredentialProvider(ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantId)
.WithClientSecret(clientSecret)
.Build());
}
catch (Exception ex)
{
//[logic for handling an exception, that never gets thrown]
}
try
{
authResult = await credentials
.ClientApplication
.AcquireTokenForClient(scopes)
.ExecuteAsync(cancellationToken);
}
catch (Exception ex)
{
//[logic for handling an exception, that never gets thrown]
//The program fails silently and suddenly, rather than hit
//this catch block.
Console.WriteLine("hello");
}
if (authResult != null)
{
client = new GraphServiceClient(
new DelegateAuthenticationProvider(
requestMessage =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
return Task.FromResult(0);
}));
}
if (client != null)
{
...
The debugger will get to the second try-catch
block, try to define authResult
, and then suddenly end. No exception is caught; the program just ends.
In case it is useful, the NuGet packages I am using are:
Help?
You are calling an async
method from a non-async Main
and not waiting for the result. Thus, your Handle()
method is executed synchronously until it reaches the first async call. (authResult = await credentials...
) Then the synchronous execution flow is handed back to the Main
method, which has nothing else to do, so it exits. And if the Main
method comes to an end, of course the whole process ends because the runtime does not wait for running Tasks to complete unless you explicitely tell it to do so.
You could for instance Wait()
for the task in the Main
method
static void Main(string[] args)
{
Task handleThing = (new Thing()).Handle();
handleThing.Wait();
}
or you could make your Main
async as well, and then await
your Handle()
Task
static async Task Main(string[] args)
{
await (new Thing()).Handle();
}