Vaccano
Vaccano

Reputation: 82341

Is there a way to have Dependency Injection and an Extension method interact?

I have a method in my NuGet package library that looks like this:

public async Task<string> GetLogoutUrl(HttpContext httpContext, string encodedUserJwt, string relativeRedirectUrl)
{
    var redirectUrl = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}/{relativeRedirectUrl}";
    var logoutUrlParameters = $"id_token_hint={encodedUserJwt}&post_logout_redirect_uri={redirectUrl}";
    var logoutUrl = $"{await DiscoveryDocument.GetLogoutEndpoint()}?{logoutUrlParameters}";
    return logoutUrl;
}

I would really like to make it an extension method of HttpContext so the users of my NuGet can call it like this: HttpContext.GetLogoutUrl(encodedUserJwt, "Home");

But the problem with that is that this method uses DiscoveryDocument that is injected into the class where this method currently resides. I have been trying to think of a way I could get the nice syntax of an extension method, but still be able to get the DiscoveryDocument from dependency injection while not breaking so many best practices that I can't sleep at night.

Is there a way in C# to have an extension method and still connect to a dependency injected object?

NOTE: I don't want to make the developers that use my NuGet to have to pass in an instance of DiscoveryDocument. For the architecture of my NuGet that would be worse than just having GetLogoutUrl not be an extension method.

Upvotes: 3

Views: 1372

Answers (1)

Nkosi
Nkosi

Reputation: 247098

Service locator via

IServiceProvider HttpContext.RequestServices { get }

will have to be used since this is a static call , which does not usually play well with DI since it is usually centered around instances.

The potential extension method would end up looking something like this

public static async Task<string> GetLogoutUrl(this HttpContext httpContext, 
    string encodedUserJwt, string relativeRedirectUrl) {
    var redirectUrl = $"{httpContext.Request.Scheme}://{httpContext.Request.Host}/{relativeRedirectUrl}";
    var logoutUrlParameters = $"id_token_hint={encodedUserJwt}&post_logout_redirect_uri={redirectUrl}";

    var DiscoveryDocument = httpContext.RequestServices
        .GetRequiredService<DiscoveryDocumentTypeHere>();

    var logoutUrl = $"{await DiscoveryDocument.GetLogoutEndpoint()}?{logoutUrlParameters}";
    return logoutUrl;
}

Upvotes: 3

Related Questions