10

I am overriding a method, HandleRequirementAsync, so I can't modify the return type of that method. However, I am calling a method in UserManager which is async and requires an await so I had to put this code in another method.

        protected override Task HandleRequirementAsync(
          AuthorizationHandlerContext context,
          EducationArmRequirement requirement)
        {

            if (!IsEducationGroup(context).Result)
            {
                return Task.FromResult(0);
            }


            context.Succeed(requirement);

            return Task.FromResult(0);
        }

        protected async Task<bool> IsEducationGroup(AuthorizationHandlerContext context)
        {
            var userId = context.User.Identity.Name;
            ApplicationUser u = await _userManager.FindByNameAsync(userId);
            if (u.Group == 3 || u.Group == 4)
            {
                return await Task.FromResult(true);
            }
            return await Task.FromResult(false);
        }

The code above seems to work in testing but it uses .Result to unwrap the Task to get the bool. I have seen several places that say be careful of using result. I saw this question which tries to explain why but I am not getting it.

I can't put an await in the HandleRequirementAsync method to allow this to unrap normally because then I would have to modify the return type which I can't do for this overridden method.

Am I approaching this the correct way in using the .Result or am I going to come across some issues here and if so what is another way to approach this which would work?

Any help/explanations would be much appreciated.

Community
  • 1
  • 1
Xaxum
  • 3,545
  • 9
  • 46
  • 66
  • 3
    just define method as `protected override async Task HandleRequirementAsync`. There's no return type change here and you can use `await` – Aleksey L. Jul 31 '16 at 05:56
  • Also no need in `return await Task.FromResult(true);` just go with `return true;` – Aleksey L. Jul 31 '16 at 07:01
  • @AlekseyL. Thanks for the note. I tried that initially but it complained about Task as a return type and wanted Task with this error: Since 'EducationArmHandler.HandleRequirementAsync(AuthorizationHandlerContext, EducationArmRequirement)' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'? Then when changed to Task it doesn't agree with the overridden methods type so it says no overload with that type. – Xaxum Jul 31 '16 at 13:16
  • Have a look at answer below from @Charles Mager - that's what I'm talking about – Aleksey L. Jul 31 '16 at 13:35

2 Answers2

17

As hinted in the comments, the async modifier doesn't change the method signature - you can just add this. You can also simplify to remove usage of Task.FromResult in both methods:

protected override async Task HandleRequirementAsync(
    AuthorizationHandlerContext context,
    EducationArmRequirement requirement)
{
    if (await IsEducationGroup(context))
    {
        context.Succeed(requirement);
    }
}

protected async Task<bool> IsEducationGroup(AuthorizationHandlerContext context)
{
    var userId = context.User.Identity.Name;

    ApplicationUser u = await _userManager.FindByNameAsync(userId);

    return u.Group == 3 || u.Group == 4;
}
Charles Mager
  • 25,735
  • 2
  • 35
  • 45
  • Thanks. The key I was missing was the await in the if statement. I did try that at one point but apparently I had issues elsewhere. Thanks again. – Xaxum Jul 31 '16 at 13:39
  • This doesn't seem to work with .NET Core 3.1. Adding the `async` keyword expects another return type. Any suggestions? – Beltway Dec 23 '20 at 07:43
1

IsEducationGroup group function

protected async Task<bool> IsEducationGroup(AuthorizationHandlerContext context)
{ 
await Task.Run((){

            var userId = context.User.Identity.Name;
            ApplicationUser u = await _userManager.FindByNameAsync(userId);
            if (u.Group == 3 || u.Group == 4)
            {
                return true;
            }
            return false;
        }

    })

HandleRequirementAsync function

protected override async Task HandleRequirementAsync(
          AuthorizationHandlerContext context,
          EducationArmRequirement requirement)
        {

           var result =  await (!IsEducationGroup(context));
            if(!result)
                return;


            context.Succeed(requirement);
            return;
        }
H H
  • 263,252
  • 30
  • 330
  • 514
Vinoth Rajendran
  • 1,141
  • 1
  • 9
  • 13