Microsoft.Indentity.Client - using from Openedge

Posted by oedev on 12-Mar-2020 09:25

Openedge 11.7

I'm trying to use the code examples provided by Microsoft (https://docs.microsoft.com/en-gb/azure/active-directory/develop/quickstart-v2-windows-desktop) to authorise a user to access the Microsoft Graph API using the Microsoft.Identity.Client library (https://www.nuget.org/packages/Microsoft.Identity.Client)

There are multiple ways to obtain a client, but all are executed asynchronously;

  authResult = await app.AcquireTokenInteractive(scopes)
                        .WithAccount(accounts.FirstOrDefault())
                        .WithParentActivityOrWindow(new WindowInteropHelper(this).Handle) // optional, used to center the browser on the window
                        .WithPrompt(Prompt.SelectAccount)
                        .ExecuteAsync();


I think asynchronous calls will be problematic to integrate with Openedge? 

Has anyone integrated with this library using Openedge?

All Replies

Posted by dbeavon on 12-Mar-2020 13:14

Are you doing this from a U/I environment or from a PASOE agent?  That makes a ton of difference where async operations are concerned.  I will assume you are running this in _mproapsv (PASOE).

Generally speaking you can change an async api into a synchronous one by using Task.Run() to send a task to the TaskScheduler (thread pool).  Once you've sent it, you immediately wait on it (using the GetAwaiter().GetResult()).   You may find cautionary tales about doing stuff like this, but they are typically related to environments where there is a U/I, a dispatcher, you are performing U/I -related in your Task, and there is a potential for U/I related deadlocks in the dispatcher (eg. winforms or wpf).

Async programming is a half-way point between synchronous and multi-threaded development.  In most cases it just works.  

Have you tried just forgoing the "await" and assigning the task to a local (TaskObj) and then using TaskObj.GetAwaiter().GetResult().  I would suspect that will work.  It would depend on something called the ambient "synchronization context".

Caveat:  I would assume that the CLR bridge in _mproapsv has a normal TaskScheduler (the thread pool).  But I haven't tried this for myself.  If I were you, I'd take a drastically different approach and create a local windows service to host a WCF interface (SOAP or REST) and interact with that stuff rather than trying to do this "in-process" - within an ABL host process like _progres or _mproapsv.

... The CLR bridge is nice in a pinch but has limitations.  If you are trying to build something complex (more than 100 lines of .Net interop) then it may be better to switch to an out-of-process approach.

Posted by dbeavon on 12-Mar-2020 13:16

Nevermind my first question.  Looks like you are doing this from a U/I.  I think your best bet is Task.Run() and then GetAwatier().GetResult().  

Posted by oedev on 12-Mar-2020 15:41

Thanks for taking the time to responsd.

It is from a UI so will look at Task.Run.

Thanks!

This thread is closed