.netasp.net-coreentity-framework-corejson-api

API error - Unable to load one or more of the requested types Method CommitAsync from assembly JsonApiDotNetCore


I have a basic API developed using ASP.NET Core, Entity Framework Core and JsonApiDotNetCore. When I try to execute the I am getting the following exception:

Unable to load one or more of the requested types.
Method 'CommitAsync' in type 'JsonApiDotNetCore.Extensions.SafeTransactionProxy' from assembly 'JsonApiDotNetCore, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.

Can anyone help me with what I am doing wrong here please.

My code: Model class:

using JsonApiDotNetCore.Models;
using System;

namespace FF_Reports_API.Model
{
    public class Pitch : Identifiable
    {
        [Attr("id")]
        public Int64 id { get; set; }

        [Attr("pitch_name")]
        public string pitch_name { get; set; }
    }
}

Controller:

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JsonApiDotNetCore.Configuration;
using JsonApiDotNetCore.Controllers;
using JsonApiDotNetCore.Services;
using Microsoft.Extensions.Logging;
using FF_Reports_API.Model;
using Microsoft.Extensions.Configuration;
using FF_Reports_API.Services;

namespace FF_Reports_API.Controllers
{
    public class PitchController : JsonApiController<Pitch>
    {

        private readonly IPitchService _pitchService;
        IConfiguration _Configuration;
        public PitchController(
            IJsonApiContext jsonApiContext,
            IResourceService<Pitch> resourceService,
            ILoggerFactory loggerFactory,
            IConfiguration configuration,
            IPitchService pitchService)
            : base(jsonApiContext, resourceService, loggerFactory)
        {
            _Configuration = configuration;
            _pitchService = pitchService;
        }

        //[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
        [HttpGet]
        public async Task<IActionResult> Pitches()
        {
            var pitches = await _pitchService.GetPitches();
            if (pitches.Count == 0)
            {
                return NotFound();
            }
            return Ok(pitches);

        }
    }
}

Interface:

using FF_Reports_API.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace FF_Reports_API.Services
{
    public interface IPitchService
    {
        public Task<List<Pitch>> GetPitches();

    }
}

Service class:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using FF_Reports_API.Context;
using FF_Reports_API.Model;
using FF_Reports_API.Services;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace FF_Reports_API.Services
{
    public class PitchService : IPitchService
    {

        readonly IConfiguration _configuration;
        readonly AppDbContext _appDbContext;
        public PitchService(IConfiguration configuration, AppDbContext appDbContext)
        {
            this._configuration = configuration;
            this._appDbContext = appDbContext;
        }

        public async Task<List<Pitch>> GetPitches()
        {
            var dtPitches = new DataTable();
            var PitchesList = new List<Pitch>();
            using (var _dbContext = _appDbContext)
            {
                SqlConnection con = (SqlConnection)_dbContext.Database.GetDbConnection();
                using (con)
                {
                    var cmd = new SqlCommand("[PitchPower2].[uspGetPitches]", con);
                    cmd.CommandType = CommandType.StoredProcedure;

                    using (var dataAdapter = new SqlDataAdapter(cmd))
                    {
                        dataAdapter.Fill(dtPitches);

                    }
                    if (dtPitches.Rows.Count > 0)
                    {
                        PitchesList = dtPitches.AsEnumerable()
                            .Select(x => new Pitch
                            {
                                id = (Int64)x["id"],
                                pitch_name = (string)x["pitch_name"]

                            }).ToList();
                    }
                }
            }
            return PitchesList;
        }

    }
}

Startup:

using FF_Reports_API.Context;
using JsonApiDotNetCore.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace FF_Reports_API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddControllers();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
            services.AddMvc(options => options.EnableEndpointRouting = false);

            // Add the Entity Framework Core DbContext like you normally would
            services.AddDbContext<AppDbContext>(options =>
            {
                // Use whatever provider you want, this is just an example
                options.UseSqlServer(Configuration.GetConnectionString("Connection"));

            });

            // Add JsonApiDotNetCore
            services.AddJsonApi<AppDbContext>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, AppDbContext context)
        {
            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseJsonApi();
            //app.UseEndpoints(endpoints => endpoints.MapControllers());
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=PitchController}/{action=Pitches}/");
            });
        }
    }
}

The connection string is in appsettings.json


Solution

  • The package JsonApiDotNetCore at version 3.1.0 depends of Microsoft.EntityFrameworkCore at version 2.1.0. But your project force Microsoft.EntityFrameworkCore at version 5.0.17.

    Microsoft.EntityFrameworkCore 5 isn't retro-compatible with Microsoft.EntityFrameworkCore 2.1.

    You need to align the version Microsoft.EntityFrameworkCore dependency between your project and JsonApiDotNetCore.

    For this, you can downgrade Microsoft.EntityFrameworkCore version to 2.1. But this version isn't supported by Microsoft.

    Or you can update Microsoft.EntityFrameworkCore version to 6 and JsonApiDotNetCore to 5.

    None JsonApiDotNetCore versions support Microsoft.EntityFrameworkCore 5.