4

I have an Azure Function App with a function that runs on a blob trigger. I've proven that this function can run through the Azure Portal and responds to this blob trigger without issues... or at least it did.

Now that I've added functionality which makes use of EF Core (2.2.4), it gives me the following error, both when debugging locally and when publishing to Azure:

Microsoft.Azure.WebJobs.Host: Error indexing method 'ParseThings'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'context' to type AvastusContext. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).

I have a Startup class as instructed by Azure Function App documentation here, and have followed their example to the letter, aside from the following line in place of their configured example services:

[assembly: FunctionsStartup(typeof(AvstFunctionApp.Startup))]

namespace AvstFunctionApp
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddDbContext<AvastusContext>(options => options.UseSqlServer(Environment.GetEnvironmentVariable("AvastusDb")));
        }
    }
}

And the beginning of my function:

public static class ParseThings
{
    [FunctionName("ParseThings")]
    public static void Run([BlobTrigger("summaries/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log, AvastusContext context)

I can confirm that the AddDbContext line is getting hit in a debugger, so presumably there's some bug happening behind the scenes here, or I'm doing something incredibly silly.

Things I've tried that haven't worked include:

  • Adding .BuildServiceProvider(true) to the AddDbContext line
  • Using WebJobsStartup instead of the more recently advertised FunctionsStartup
  • Downgrading to .NET Core 2.2.0
  • Changing the Function class and Run method from static to instance
  • Fixing incorrect namespace of the injected AvastusContext

It's also worth noting that there are two other functions in this Function App project which don't seem to have any serious issues, and I've been able to get dependency injection working using a similar method with EF Core for another (ASP.NET Core MVC) project in this solution.

Thank you in advance for any help anyone can provide!

P.S. I find it incredibly weird that there hasn't been anything describing this situation with the later versions of .NET Core, Azure Function Apps, and EF Core on the interwebs, which leads me to believe that this might be a simple mistake. Hopefully not.

phantomraa
  • 1,183
  • 1
  • 14
  • 24
  • I've struggled with this myself today. Try making the ParseThings class non-static and injecting the context into a constructor instead of the method. I got it working that way. I'm new to Azure functions though, so I don't know if the class needs to be static for any reason when deployed to Azure, but it works locally for me. – Matthew Sawrey May 18 '19 at 20:42
  • Thanks for the suggestion. Unfortunately, changing a Function class to an instance class instead of a static one, adding a constructor with dependency-injected parameters, and changing the `Run` method to an instance method from a static one did not fix the problem. I can confirm that an `ILogger<>` instance was not complained about, while the `AvastusContext` threw an `InvalidOperationException` for lack of resolving. – phantomraa May 20 '19 at 21:58
  • Perhaps the line where you add the DbContext should be moved above the line where you add azure functions? I'm just guessing here, but if they build the serviceprovider before you added the DbContext, that could be a problem. – Jesse de Wit May 21 '19 at 14:47
  • Thanks for that, Jesse. Unfortunately, the pattern dictated by Functions exposes the `IFunctionsHostBuilder` in an overriden `Configure` method, so I don't explicitly build anything as that's handled by the `FunctionsStartup` class. I'll update my first code block in my question to show you the lines surrounding `AddDbContext`. – phantomraa May 21 '19 at 21:02

1 Answers1

0

perhaps one solution can be you can try injecting IServiceProvider in your function instead of AvastusContext like I have injected in the repository class below:

private readonly IServiceProvider serviceProvider;

        public SomeRepository(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
        }
    
        using var context = this.serviceProvider.GetService<XYZDBContext>(); 

This will provide a context object to you. Also, Not sure why you are trying to access context in the function directly for good practice have a context class defined, and maintain repository to do any CRUD operation in the code.

Startup.cs you can add extra configurations like :

builder.Services.AddDbContext<XYZDBContext>(
            options =>
            {
                options.UseSqlServer(
                    conn,
                    sqlServerOptionsAction:
                    sqlOptions =>
                    {
                        sqlOptions.EnableRetryOnFailure(maxRetryCount: 3, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                    });
            }, ServiceLifetime.Transient);

this configuration works perfectly fine in my current solution. Try this out.

Meow
  • 42
  • 8