Sendgrid-csharp: Dependency Injection in Startup.cs

Created on 3 May 2019  路  7Comments  路  Source: sendgrid/sendgrid-csharp

Hi, sorry for not following the template, but regarding issues #847 and #521, I was wondering if there is any progress?

I would like to inject a SendGridClient through DI to a controller, instead of instantiating a new client every request.

I can't rely on services.AddHttpClient<ISendGridClient, SendGridClient>(); because I need to add the Key that is typically called in the SendGridClient constructor.

Is this workflow being looked in to?

Thanks

hard community enhancement

Most helpful comment

You can use Install-Package SendGrid.Extensions.DependencyInjection -Version 1.0.0
And use it in your startup Configure method. Something like this.

builder.Services.AddSendGrid(options => {
options.ApiKey = Environment.GetEnvironmentVariable("SENDGRID_API_KEY");

All 7 comments

Hello @KevinMallinson,

I don't know the answer to this offhand, I will need to investigate further.

In the mean time, could you please elaborate on what the behavior you are seeking would look like in code if we had already implemented it so that I may better understand your workflow?

With Best Regards,

Elmer

The behaviour would look something like this (psuedocode):

MySendGridClient.cs

public class MySendGridClient : ISendGridClient
{
    // Concrete implementation that we forward our calls to
    private SendGridClient _myClient;

    public class MySendGridClient(HttpClient httpClient, string apiKey)
    {
        //Add custom headers, etc
        // ...

        _myClient = new SendGridClient(apiKey, httpClient);
    }

    // Below this line, each method of the interface is implemented, 
    // simply by forwarding to our internal sendgridclient.

    public Task SomeMethod() => _myClient.SomeMethod();
    // etc.
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddHttpClient<ISendGridClient, MySendGridClient>();
}

MyController.cs

public class MyController
{
    public MyController(ISendGridClient myClient)
    {
        // myClient is passed via dependency injection
        // it is always instantiated, no need to re-instantiate each time
        // Care needs to be taken to ensure concurrency and thread safety
    }
}

Hopefully that makes sense,

Thanks.

Edit: Changed the example to look more like the Twilio example

Thank you @KevinMallinson,

Your description was very helpful, thanks for taking the time!

I've added this to our internal backlog for consideration as well as opened it up for community contribution.

With Best Regards,

Elmer

This could be added relatively easily by adding a constructor that accepts an IOptions<SendGridClientOptions> argument, unwraps the option type, and calls the existing constructor with the SendGridClientOptions options signature.

In your DI configuration, you'd do something along the lines of:

services.Configure<SendGridClientOptions>(Configuration.GetSection("SendGrid");
services.AddScoped<ISendGridClient, SendGridClient>();

Let me know if you want me to apply these changes, I'll happily implement them and submit a PR.

Hello @aevitas,

A PR would be most welcome. Thank you!

With best regards,

Elmer

@aevitas @thinkingserious

839 was merged, will #904 require changes, and is this still planned on being merged?

You can use Install-Package SendGrid.Extensions.DependencyInjection -Version 1.0.0
And use it in your startup Configure method. Something like this.

builder.Services.AddSendGrid(options => {
options.ApiKey = Environment.GetEnvironmentVariable("SENDGRID_API_KEY");

Was this page helpful?
0 / 5 - 0 ratings