0

The following Code works within a console application.

public Boolean Graph_IsMemberOfGroup(string Parm_AzureUserID, string Parm_GroupID) {
        Boolean Lcl_ReturnValue = false;
        Task<string> Lcl_Response = GraphPriv_IsMemberOfGroup(Parm_AzureUserID, Parm_GroupID);
        if (Lcl_Response.Result != null) {
            Lcl_ReturnValue = Lcl_Response.Result.Contains(Parm_GroupID);
        }//end if
        return (Lcl_ReturnValue);
    }

    private async Task<string> GraphPriv_IsMemberOfGroup(string Parm_AzureUserID, string Parm_GroupID) {
        string Lcl_Returnvalue = null;
        var Lcl_Uri = "https://graph.windows.net/CleMetroSchools.onmicrosoft.com/users/" + Parm_AzureUserID.Trim() + "/checkMemberGroups?api-version=1.6";
        string Lcl_RequestBody = @"{""groupIds"": [""" + Parm_GroupID.Trim() + @"""]}";
        Global_HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Global_Token.Result);
        HttpResponseMessage Lcl_PostResult = await Global_HttpClient.PostAsync(Lcl_Uri, new StringContent(Lcl_RequestBody, Encoding.UTF8, "application/json"));
        if (Lcl_PostResult.Content != null) {
            Lcl_Returnvalue = await Lcl_PostResult.Content.ReadAsStringAsync();
        }//end if

        return Lcl_Returnvalue;
    }

The call I use is

if (Graph_IsMemberOfGroup(CurrentUser,Group)){

The problem I am having is that when I Use the same code in a plain (not MVC) ASP.net web application. The system does not wait for GraphPriv_IsMemberOfGroup to completed before it tries to process the if (Lcl_Response.Result != null) {

Anything I have tried so far with waits either will not compile or waits forever. I have been searching for several days and all I have managed to do is travel deeper down the rabbit hole of confusion.

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
  • If the exact same code works in an ASP.NET application, it is by sheer luck. Take a look at [Asynchronous programming with async and await](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/) – user247702 Dec 03 '18 at 16:58
  • You are not using `await` when you call `GraphPriv_IsMemberOfGroup`...try adding `await` on `Task Lcl_Response = await GraphPriv_IsMemberOfGroup(Parm_AzureUserID, Parm_GroupID);` – Hackerman Dec 03 '18 at 17:02
  • Still, you should follow the recommendation from @Stijn and try to do more research and training, before using the async-await pattern. – Hackerman Dec 03 '18 at 17:03
  • I tried Task Lcl_Response = await GraphPriv_IsMemberOfGroup(Parm_AzureUserID, Parm_GroupID); but get the compile error The 'Await' operator can only be used within an asysnc method. – user1394231 Dec 03 '18 at 17:07
  • I have read and re read async and await but I am still unsure what to do. Please understand that I have been trying to figure this out since August. I cannot tell you the number of hours I have spent watching youtube videos and reading web pages trying to figure out how to do one thing. (Verify that a user is a member of an AD group) Much of what I read is either outdated or only has snippets of code that leave a lot of important parts out. – user1394231 Dec 03 '18 at 17:16
  • It's not a simple concept, especially for beginners. But I'm afraid SO isn't the place to teach it to you. If you're not making any progress with your own research (videos and web pages), consider asking someone in real life, taking an actual course with a teacher, or perhaps find a decent book. – user247702 Dec 03 '18 at 17:32
  • If I had someone in real life I wouldn't be asking here! After 30 years of coding including writing drivers in assembly language I never thought I would have this much trouble making an HTTP call from a web application. I am the sole employee developer of almost 30 years at an Urban school district. (The trend is to buy packages or outsource out of country) I have been using C# since it first came one scene, and this is the first time I have ever needed to make an HTTP call from a web app. – user1394231 Dec 03 '18 at 17:54
  • Have you considered using the [Microsoft.Graph NuGet package](https://www.nuget.org/packages/Microsoft.Graph)? It should deal with the HTTP calls for you. You'll still need to understand async/await but you might have an easier time when you don't have to spend time on the low-level details. I haven't taken a detailed look at the library, but it does seem to contain methods to call the `checkMemberGroups` endpoint. – user247702 Dec 04 '18 at 10:25
  • Also, sorry if I offended you in any way with that comment yesterday, it was not my intention. – user247702 Dec 04 '18 at 10:26
  • Thanks for the Microsoft Graph package suggestion. I will look into it. – user1394231 Dec 04 '18 at 14:55
  • I know I need sometype of between Task Lcl_Response = GraphPriv_IsMemberOfGroup(Parm_AzureUserID, Parm_GroupID); and if (Lcl_Response.Result != null) { but Task Lcl_Response = await GraphPriv_IsMemberOfGroup(Parm_AzureUserID, Parm_GroupID); and await Lcl_Response will not compile. (I have tried to make the whole procedure an async but that only move the problem to a different location.) Lcl_Response.wait(); waits forever. In any case I am going to try Microsoft Graph package – user1394231 Dec 04 '18 at 15:04
  • Worst case I write windows applications to write out all the groups I am concerned about and ther members to a SQL table. (I have an the windows side of this working for sometime with all sorts of call to Graph) Since I have around 50,000 accounts I will have to cycle through them as I will not be able to hit everyone in a single night. Downside is when changes are made children may not have access for days until a long term solution can be found. – user1394231 Dec 04 '18 at 15:11
  • Yes, using async/await usually means you have to make everything up to the top also use async/await. It's possible to avoid it but they're advanced scenarios. The good news is that it *is* possible today to make a console application easily use async/await. Take a look at [this question and answer](https://stackoverflow.com/questions/51456208/cannot-create-an-async-main) to enable using `static async Task Main` instead of `static void Main`. – user247702 Dec 04 '18 at 16:24

1 Answers1

2

You're misapplying the async/await model here. You shouldn't be looking for a Task<string>, you should be looking for string from an awaited method:

public async Task<Boolean> Graph_IsMemberOfGroup(string Parm_AzureUserID, string Parm_GroupID) {
    Boolean Lcl_ReturnValue = false;
    string Lcl_Response = await GraphPriv_IsMemberOfGroup(Parm_AzureUserID, Parm_GroupID);
    return Lcl_Response.Result.Contains(Parm_GroupID);
}

An async method returns a value wrapped in a Task<>, The await keyword tells the code to wait for the method to return and unwrap the response. So if an async method returns Task<string> then you would call that method using string s = await method().

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
  • Thank you for your response. The problem I having with the code as you have provided is giving me compile error on the await line as follows. Error CS4032 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'. GraphTest – user1394231 Dec 04 '18 at 18:40
  • Sorry, missed that bit. You need to turn `Graph_IsMemberOfGroup` into an async method. This enables the async/await framework. – Marc LaFleur Dec 04 '18 at 18:43
  • If I turn that into an async then the same overall problem moves up a level to a protected void Button1_Click(object sender, EventArgs e) Which I cannot make an async :( in order for it to wait for the task to finish. Wondering if this has actually been done in a web app. – user1394231 Dec 04 '18 at 19:22
  • What platform/framework are you using? You should be able to set up your event handlers as async as well – Marc LaFleur Dec 05 '18 at 17:00
  • 1
    Thank you, Thank you Thank you! – user1394231 Dec 06 '18 at 16:52