2

I'm trying to create my first webjobapp that requires the use of Entity Framework. I am trying to inject my context into the builder of the app, but I'm getting an error:
Cannot bind parameter 'db' to type ApplicationDbContext. Make sure the parameter Type is supported by the binding There are several examples on the web but the versions of the Azure WebJob appear to have changed quickly and I can't find one that works for the version I'm using. These are the package versions I'm using: Webjobs 3.0 EF.NET Core 7.0 Targeting .NET 7.0

Here is my code:

 class Program
{
    static async Task Main()
    {
        var builder = new HostBuilder();
        builder.ConfigureWebJobs(b =>
        {
            b.AddTimers();
            b.AddAzureStorageCoreServices();
        });
        builder.ConfigureLogging((context, b) =>
        {
            b.AddConsole();
        });
        builder.ConfigureAppConfiguration((hostContext, configApp) =>
         {
             configApp.SetBasePath(Directory.GetCurrentDirectory());
             configApp.AddEnvironmentVariables(prefix: "ASPNETCORE_");
             configApp.AddJsonFile($"appsettings.json", true);
             configApp.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", true);

         });
       
       builder.ConfigureServices(services => { services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer("My full connection string"));
            services.AddTransient<IEmailSender, EmailSender>();
                                              });
        var host = builder.Build();
        using (host)
        //{
            await host.RunAsync();
        }
    }
}

public class Functions

public static void Sendemails([TimerTrigger("0 0 20 * * SUN-THU")] TimerInfo timer,
         ILogger logger,  ApplicationDbContext db)

    {
   
  
        var mylist = db.Users.ToList();
    
    }
}

I tried to configure the services using the following code instead of the above code. When inspecting the builder I can see that the services were added to the builder. But inspecting the host after the call to builder.Build(), The services do not show up in the host container.

var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
     .....

  builder.ConfigureServices((context, sc) =>  sc= serviceCollection);
        var host = builder.Build();
   
        using (host)
        {
            await host.RunAsync();
        } 
}
 .....

    private void ConfigureServices(IServiceCollection services)
{
   
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(_configuration.GetConnectionString("DefaultConnection")))
           
        
    }

Project File

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <None Remove="appsettings.Development.json" />
    <None Remove="appsettings.json" />
  </ItemGroup>

  <ItemGroup>
    <Content Include="appsettings.Development.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
    <Content Include="appsettings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </Content>
  </ItemGroup>

  <ItemGroup>
    <PackageReference 
Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.1" />
    <PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.33" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi.Configuration.AppSettings" Version="1.5.0" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.SendGrid" Version="3.0.2" />
    <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="5.0.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.1" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
    <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
    <PackageReference Include="SendGrid" Version="9.28.1" />
  </ItemGroup>

</Project>
Haim Katz
  • 455
  • 3
  • 15
  • 1
    `ConfigureServices` is where you put *all* registrations, not something you call for each individual registration. Calling it twice probably replaces the old DI registrations with the latest one. – Panagiotis Kanavos Jan 12 '23 at 07:46
  • Did you try putting all registrations in a single `ConfigureServices` call? All .NET Core tutorials and samples show this. – Panagiotis Kanavos Jan 12 '23 at 07:56
  • I will try, but the comment on the hover over ConfigureServices states "Adds Services to the container. This can be called multiple times and the results will be additive". Also I commented out the 2nd call so that it is only called once and I still get the same error message. – Haim Katz Jan 12 '23 at 08:19
  • I corrected my code as above, so that there is only one call to ConfigureServices, but I'm still getting the same error. – Haim Katz Jan 12 '23 at 08:46
  • Please share your `.csproj` file. – Harshitha Jan 13 '23 at 06:01
  • Is your Application `Azure WebJob` or `Console App`. As mentioned in the document, for .NET Core Applications it is advised to go with Console Application. Refer [WebJob .NET Core code implementation section](https://dejanstojanovic.net/aspnet/2019/june/writing-azure-webjobs-with-dependency-injection-net-core/). – Harshitha Jan 13 '23 at 06:27
  • Thank you all for my comments. I added the project file. The template used was a console application and I added the WebJobs package. – Haim Katz Jan 14 '23 at 14:07
  • Remove `` from your `.csproj` file. – Harshitha Jan 18 '23 at 11:55
  • @HaimKatz "But inspecting the host after the call to builder.Build(), The services do not show up in the host container." could you please provide screenshot(hovering over host variable) – Vladimir Jan 26 '23 at 09:10

2 Answers2

1

Initially Even I got the same error.

enter image description here

Done few changes in Program.cs .

My Program.cs:

using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

class Program
{
    static async Task Main()
    {
        var builder = new HostBuilder()
            .ConfigureWebJobs(b =>
            {
                b.AddTimers();
                b.AddAzureStorageCoreServices();
            })
            .ConfigureLogging((context, b) =>
            {
                b.AddConsole();
            })
             .ConfigureAppConfiguration((hostContext, configApp) =>
             {
                 configApp.SetBasePath(Directory.GetCurrentDirectory());
                 configApp.AddEnvironmentVariables(prefix: "ASPNETCORE_");
                 configApp.AddJsonFile($"appsettings.json", true);
                 configApp.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", true);
             })

        .ConfigureServices(services =>
        {
            services.AddDbContext<ApplicationDbContext>(
        options => options.UseSqlServer("MyDefaultConnection"));
            services.AddTransient<ApplicationDbContext, ApplicationDbContext>();
        });


        var host = builder.Build();
        using (host)
        {
            await host.RunAsync();
        }
    }
}

If you are running locally, cross check the local.settings.json file once.

My local.settings.json :

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  }
}

My appsettings.json:

{
  "ConnectionStrings": {
    "AzureWebJobsStorage": "Storage Account Connection String"
  }
}

enter image description here

Also have a look at SO Thread once.

References taken from MSDoc.

Harshitha
  • 3,784
  • 2
  • 4
  • 9
  • Thank you very much Harshitha. Unfortunately the changes have not helped. I'm getting the same error. When I inspect the 'host' variable after builder.build() line, I do not see the ApplicationDbcontext as one of the services registered. I thus far am running it locally and do not have an azure storage string (I don't use it in my webjob, but I needed to add it because I was getting another error. Do I need to set up a storage account to run it locally? – Haim Katz Jan 19 '23 at 12:44
  • No, we don't need a Storage account for running locally. – Harshitha Jan 19 '23 at 12:49
  • In order for running an Azure function you need to have a storage emulator running. Azurite. And when running in Azure you will need a storage account. [docs here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-local) – Peter Jan 29 '23 at 06:52
  • To get it running even locally I had to create a storage count on azure and enter its connection string. Even though I didn't use the storage, it still was looking for it when it registered. I had to add the storage service otherwise I had an error with the timers. – Haim Katz Jan 30 '23 at 12:24
0

I do the steps from the beginning.


1-

public class ApplicationDbContext: IdentityDbContext<User, Role, Guid>
{
    public ApplicationDbContext(DbContextOptions options)
       : base(options)
    {
       
    }
 
     
    }

2-add in appsettings.json


"ConnectionStrings": {
  "SqlServer": "Data Source=;Initial Catalog=SpaceManagment;User ID=sa;Password=654321;MultipleActiveResultSets=true;TrustServerCertificate=True;Connection Timeout = 60"
},

3-


add in program.cs


 builder.Services.AddDbContext<ApplicationDbContext>(options =>
        {
            options
                .UseSqlServer(settings.SqlServer);
            //Tips
            // .ConfigureWarnings(warning => warning.Throw(RelationalEventId.QueryClientEvaluationWarning));
        });
sedaghat
  • 64
  • 5