apache/openwhisk-runtime-dotnet

Action cannot load Microsoft.Extensions.DependencyInjection.Abstraction

dmlo opened this issue · 9 comments

dmlo commented

I have a c# OpenWhisk Action:

using System;
using IHWhisk.Models;
using Newtonsoft.Json.Linq;

namespace IHWhisk
{
    public class Hello
    {
        public JObject Main(JObject args)
        {
            var handian = new Handian();

            string errorText = "";
            
            try
            {
                using var db = new IHDbContext();
                db.Handians.Add(handian);
                db.SaveChanges();
            }
            catch (Exception e)
            {
                errorText = e.Message;
            }

            var message = new JObject();
            message.Add("Content-Type", new JValue("application/json"));
            message.Add("body", new JValue($"<p>Error: {errorText}</p>"));
            return message;
        }
    }
}

which uses EF Core dependency injection to configure and access the database, like so:

using System;
using Microsoft.EntityFrameworkCore;
using IHWhisk.Models;

namespace IHWhisk
{
    public class IHDbContext : DbContext
    {
        public DbSet<Handian> Handians { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder builder)
        {
            var connectionString = "Server=#.#.#.#;Database=ih;Port=5432;User Id=postgres;Password=supersecretpassword";
            builder
                .UseNpgsql(connectionString, o
                    => o.EnableRetryOnFailure());
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder
                .HasPostgresExtension("uuid-ossp")
                .Entity<BaseEntity>(entity =>
                {
                    entity.HasIndex("Discriminator");
                    entity.Property(p => p.Uuid)
                        .HasDefaultValueSql("uuid_generate_v4()"); // All IH entities get a postgres Uuid4
                })
                .Entity<Handian>(entity => { entity.Property<DateTime>(p => p.Birthday).HasDefaultValueSql("now()"); });
        }
    }
}

which when run inside my OpenWhisk installation fails with the error:

Error: Could not load file or assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=3.1.3.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. Could not find or load a specific file. (0x80131621)

I test this Action locally by invoking it from a clean console app like so:

namespace WhiskTester
{
    class Program
    {
        static void Main(string[] args)
        {
            var ihwhisk = new IHWhisk.Hello();
            var callArgs = new JObject();
            var result = ihwhisk.Main(callArgs);
            Console.WriteLine(result);
        }
    }
}

It works when tested locally... a new record is written to the database as expected.

Things I've tried to resolve the issue:

  • Successfully performed a DB insert without EF Core, ruling out a DB misconfiguration or a problem with the NGPSQL drivers
  • Replaced NGPSQL with Microsoft's SQLite driver and replicated the issue to further rule out a NGPSQL problem
  • Verified that Microsoft.Extensions.DependencyInjection.Abstractions.dll v3.1.3 is in the zip file I am sending to OpenWhisk
  • Downgraded Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Abstractions, Microsoft.EntityFrameworkCore.Design, Microsoft.EntityFrameworkCore.Tools and Npgsql.EntityFrameworkCore.PostgreSQL to version 3.1.2. The error message now references missing Microsoft.Extensions.DependencyInjection.Abstractions, Version=3.1.2.0

At this point I've reached the edge of my knowledge and would be grateful for any advice or guidance you could offer.

How your .csproj looks like? Try maybe my fork: https://github.com/kamyker/openwhisk-dotnet-csharp

@dmlo Is Microsoft.Extensions.DependencyInjection.Abstractions included in your published zip file? The dependencies need to be included there. Let me know, thanks!

dmlo commented

@shawnallen85 Microsoft.Extensions.DependencyInjection.Abstractions.dll v3.1.3 was in the zip file I was sending to OpenWhisk.

dmlo commented

@kamyker here is my csproj:

`

<PropertyGroup>
    <TargetFrameworks>netstandard2.1;netcoreapp3.1</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
  <PackageReference Include="EFCore.NamingConventions" Version="1.1.0" />
  <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
  <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.2.4" />
  <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
</ItemGroup>

<ItemGroup>
  <ProjectReference Include="..\ih-interface\ih-interface.csproj" />
</ItemGroup>

<ItemGroup>
    <None Include="config.json" CopyToPublishDirectory="Always" />
    <None Update="female-names.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="last-names.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="male-names.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="places.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
</ItemGroup>
`

No idea, "PackageReference Include="Microsoft.AspNetCore" in https://github.com/apache/openwhisk-runtime-dotnet/blob/master/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj
could be the issue.

My version looks a bit different: https://github.com/kamyker/openwhisk-dotnet-csharp/blob/master/core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj

If you can reproduce error without using database (just call something from Microsoft.Extensions.DependencyInjection.Abstractions) I can try it on my fork.

@dmlo Can you try with the latest version from the master branch? @woutersterp had submitted a change that might address this issue. Let me know, thanks!!

I found out what we need to do to resolve this issue, but to implement it requires a breaking change in how functions are built and deployed. Will hold off on this until the next release where we plan on potentially changing the contract.

Closing as this issue was about dotnet 3.1 which is EOL.