Jason Shave
Jason Shave

Reputation: 2672

HttpContext can't be referenced in supporting method call

I need to make use of two steps in multiple places on my .NET Core website. I've decided to implement an interface and supporting class in my Startup.cs so I can use DI to inject the object into my PageModel on various Razor pages in my project.

Startup.cs

services.AddSingleton<IAuthenticatedGraphClient, AuthenticatedGraphClient>();

Interface:

public interface IAuthenticatedGraphClient
{
    Task<GraphServiceClient> GetAuthenticatedGraphClientAsync(HttpContext httpContext);
}    

Implementing Class:

public class AuthenticatedGraphClient : IAuthenticatedGraphClient
{
    private ITokenAcquisition tokenAcquisition;

    public AuthenticatedGraphClient(ITokenAcquisition tokenAcquisition)
    {
        this.tokenAcquisition = tokenAcquisition;
    }

    public async Task<GraphServiceClient> GetAuthenticatedGraphClientAsync(HttpContext httpContext)
    {
        var accessToken = await TokenAcquisition.GetAccessTokenOnBehalfOfUser(httpContext, new[] { ScopeConstants.ScopeUserRead });

        return new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) => {
            requestMessage
                .Headers
                .Authorization = new AuthenticationHeaderValue("bearer", accessToken);
            return Task.FromResult(0);
        }));
    }
}

PageModel:

public class TestPageModel : PageModel
{
    private IAuthenticatedGraphClient graphClient;

    public TestPage(IAuthenticatedGraphClient graphClient)
    {
        this.graphClient = graphClient;
    }

    public async Task OnPostAsync()
    {
        var graphServiceClient = await graphClient.GetAuthenticatedGraphClientAsync(HttpContext);
        //truncated for brevity...
    }
}

I thought I had to provide the HttpContext from the PageModel class into the called method but I'm not entirely sure as this gives me an error:

An object reference is required for the non-static field, method, or property 'TokenAcquisition.GetAccessTokenOnBehalfOfUser(HttpContext, IEnumerable, string)'

I've also tried:

var accessToken = await TokenAcquisition.GetAccessTokenOnBehalfOfUser(HttpContext, new[] { ScopeConstants.ScopeUserRead });

...however this gives me the error:

'HttpContext' is a type, which is not valid in the given context

If I put the GetAuthenticatedGraphClientAsync as a method in the same PageModel class it works without issue and HttpContext is understood.

Any ideas? Is there a better pattern?

Upvotes: 0

Views: 1094

Answers (1)

rickjerrity
rickjerrity

Reputation: 814

Your first error about an object reference being required, would seem to be because your AuthenticatedGraphClient constructor takes an ITokenAcquisition parameter, which you don't seem to be passing in your Startup.cs

As for your second error about HttpContext being a type, that is true, I'm pretty sure you should be passing HttpContext.Current into GetAccessTokenOnBehalfOfUser.

EDIT: Also, you're not even using the passed in ITokenAcquisition.

var accessToken = await TokenAcquisition.GetAccessTokenOnBehalfOfUser(httpContext, new[] { ScopeConstants.ScopeUserRead });

should be:

var accessToken = await tokenAcquisition.GetAccessTokenOnBehalfOfUser(httpContext, new[] { ScopeConstants.ScopeUserRead });

Upvotes: 1

Related Questions