No constructor was found that had all the dependencies satisfied.

2 years ago
Hi have been following the Pluralsight Course on NopCommerce, but it is for the older version.

I have been trying to build the same functionality in NopCommerce 4.10

Plugin Files:

PromoImageRecord.cs
using Nop.Core;

namespace Nop.Plugin.Widgets.PromoSlider.Domain
{
    public class PromoImageRecord: BaseEntity
    {
        public int PromoImageId { get; set; }
        public virtual int PromoSliderId { get; set; }
        public virtual string Caption { get; set; }
        public virtual string Url { get; set; }
        public virtual string FilePath { get; set; }
        public virtual int DisplayOrder { get; set; }

        public PromoSliderRecord PromoSlider { get; set; }

    }
}

===========================================================
PromoSliderRecord.cs
using Nop.Core;
using System;
using System.Collections.Generic;
using System.Text;

namespace Nop.Plugin.Widgets.PromoSlider.Domain
{
    public class PromoSliderRecord: BaseEntity
    {
        public PromoSliderRecord()
        {
            Images = new List<PromoImageRecord>();
        }


        public int PromoSliderId { get; set; }
        public virtual string PromoSliderName { get; set; }
        public bool IsActive { get; set; }
        public virtual string ZoneName { get; set; }
        public virtual int Interval { get; set; }
        public virtual bool PauseOnHover { get; set; }
        public virtual bool Wrap { get; set; }
        public virtual bool KeyBoard { get; set; }

        public virtual List<PromoImageRecord> Images { get; set; }


    }
}

=========================================================
PromoImageMap.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Nop.Plugin.Widgets.PromoSlider.Domain;
using System.Collections.Generic;
using System.Text;

namespace Nop.Plugin.Widgets.PromoSlider.Data
{
    public class PromoImageMap : IEntityTypeConfiguration<PromoImageRecord>
    {
        public void Configure(EntityTypeBuilder<PromoImageRecord> builder)
        {
            builder.ToTable("Some");
            builder.ToTable("PromoSlider_PromoImages");

            //Map the primary key
            builder.HasKey(m => m.PromoImageId);

            builder.Property(m => m.PromoSliderId);
            builder.Property(m => m.Caption);
            builder.Property(m => m.DisplayOrder);
            builder.Property(m => m.Url);

            builder.HasOne(x => x.PromoSlider).WithMany(x => x.Images).HasForeignKey(x => x.PromoSliderId).IsRequired();
        }
    }
}

==================================================
PromoSliderMap.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Nop.Plugin.Widgets.PromoSlider.Domain;
using System;
using System.Collections.Generic;
using System.Text;

namespace Nop.Plugin.Widgets.PromoSlider.Data
{
    public class PromoSliderMap : IEntityTypeConfiguration<PromoSliderRecord>
    {
        public PromoSliderMap()
        {
          
        }

        public void Configure(EntityTypeBuilder<PromoSliderRecord> builder)
        {
            builder.ToTable("PromoSlider_PromoSliders");
            builder.HasKey(x => x.PromoSliderId);

            builder.Property(m => m.PromoSliderName);
            builder.Property(m => m.ZoneName);
            builder.Property(m => m.Interval);
            builder.Property(m => m.KeyBoard);
            builder.Property(m => m.PauseOnHover);
            builder.Property(m => m.Wrap);

        }
    }
}

===============================================
PromoSliderObjectContext.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Nop.Core;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Nop.Data;

namespace Nop.Plugin.Widgets.PromoSlider.Data
{
    public class PromoSliderObjectContext: DbContext, IDbContext
    {
        // (LocalDb)\MSSQLLocalDB
        public PromoSliderObjectContext(string connString): base(SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), connString).Options)
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new PromoSliderMap());
            modelBuilder.ApplyConfiguration(new PromoImageMap());
            base.OnModelCreating(modelBuilder);
        }

        public string CreateDatabaseInstallationScript()
        {
            return this.Database.GenerateCreateScript();
        }

        public void Install()
        {
            var context = new PromoSliderObjectContext(@"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=NopCommercePractice11;Integrated Security=True");
            context.Database.EnsureCreated();
        }

        public void UnInstall()
        {
            //this.Database.drop
        }

        DbSet<TEntity> IDbContext.Set<TEntity>()
        {
            return base.Set<TEntity>();
        }

        int IDbContext.SaveChanges()
        {
            throw new NotImplementedException();
        }

        string IDbContext.GenerateCreateScript()
        {
            throw new NotImplementedException();
        }

        IQueryable<TQuery> IDbContext.QueryFromSql<TQuery>(string sql)
        {
            throw new NotImplementedException();
        }

        IQueryable<TEntity> IDbContext.EntityFromSql<TEntity>(string sql, params object[] parameters)
        {
            throw new NotImplementedException();
        }

        int IDbContext.ExecuteSqlCommand(RawSqlString sql, bool doNotEnsureTransaction, int? timeout, params object[] parameters)
        {
            throw new NotImplementedException();
        }

        void IDbContext.Detach<TEntity>(TEntity entity)
        {
            throw new NotImplementedException();
        }
    }
}

=================================================
PromoSliderDependencyRegistrar.cs
using Autofac;
using Nop.Core.Configuration;
using Nop.Core.Infrastructure;
using Nop.Core.Infrastructure.DependencyManagement;
using System;
using System.Collections.Generic;
using System.Text;
using Nop.Web.Framework.Mvc;
using Nop.Data;
using Nop.Plugin.Widgets.PromoSlider.Domain;
using Nop.Core.Data;
using Autofac.Core;

namespace Nop.Plugin.Widgets.PromoSlider.Data
{
    public class PromoSliderDependencyRegistrar : IDependencyRegistrar
    {
        private const string CONTEXT_NAME = "nop_object_context_promo_slider";

        public int Order => 1;

        public void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
        {
            builder.RegisterType<PromoSliderObjectContext>().InstancePerLifetimeScope();
            
            builder.RegisterType<EfRepository<PromoSliderRecord>>()
                .As<IRepository<PromoSliderRecord>>()
                .WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME))
                .InstancePerLifetimeScope();
            builder.RegisterType<EfRepository<PromoImageRecord>>()
                .As<IRepository<PromoImageRecord>>()
                .WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME))
                .InstancePerLifetimeScope();
        }
    }
}


=========================================
PromoSliderPlugin.cs

using Nop.Core.Plugins;
using Nop.Plugin.Widgets.PromoSlider.Data;
using Nop.Services.Cms;
using System;
using System.Collections.Generic;
using System.Text;

namespace Nop.Plugin.Widgets.PromoSlider
{
    public class PromoSliderPlugin: BasePlugin, IWidgetPlugin
    {
        private PromoSliderObjectContext _context;

        public PromoSliderPlugin(PromoSliderObjectContext contenxt)
        {
            _context = contenxt;
        }

        public string GetWidgetViewComponentName(string widgetZone)
        {
            return "WidgetsPromoSlider";
        }

        public IList<string> GetWidgetZones()
        {
            throw new NotImplementedException();
        }

        public override void Install()
        {
            _context.Install();
            base.Install();
        }

        public override void Uninstall()
        {
            _context.UnInstall();
            base.Uninstall();
        }
    }
}

=========================================
Notes.txt:-

Important points when developing plugins


- All views (cshtml files) and web.config file should have "Build action" set to "Content" and "Copy to output directory" set to "Copy if newer"

- When you develop a new plugin from scratch, and when a new class library is added to the solution, open its .csproj file (a main project file) in any text editor and replace its content with the following one

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>  
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <OutputPath>..\..\Presentation\Nop.Web\Plugins\Nop.Plugin.Widgets.PromoSlider</OutputPath>
    <OutDir>$(OutputPath)</OutDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <OutputPath>..\..\Presentation\Nop.Web\Plugins\Nop.Plugin.Widgets.PromoSlider</OutputPath>
    <OutDir>$(OutputPath)</OutDir>
  </PropertyGroup>
  <!-- This target execute after "Build" target -->
  <Target Name="NopTarget" AfterTargets="Build">
    <!-- Delete unnecessary libraries from plugins path -->
    <MSBuild Projects="$(MSBuildProjectDirectory)\..\..\Build\ClearPluginAssemblies.proj" Properties="PluginPath=$(MSBuildProjectDirectory)\$(OutDir)" Targets="NopClear" />
  </Target>
</Project>

Replace “PLUGIN_OUTPUT_DIRECTORY” in the code above with your real plugin output directory name.

It’s not required. But this way we can use a new ASP.NET approach to add third-party references. It was introduced in .NET Core. Furthermore, references from already referenced libraries will be loaded automatically. It’s very convenient.

============================================================
plugin.json:-

{
  "Group": "Widgets",
  "FriendlyName": "Promo Slider",
  "SystemName": "Widgets.PromoSlider",
  "Version": "1.0",
  "SupportedVersions": [ "4.10" ],
  "Author": "Any",
  "DisplayOrder": 1,
  "FileName": "Nop.Plugin.Widgets.PromoSlider.dll",
  "Description": "This plugin allows you to change the contents of main page slider"
}

======================================================

When I try to install the plugin, getting the error: No constructor was found that had all the dependencies satisfied.
Can someone please help!
2 years ago
Your object context expects a string parameter in it's constructor. And in your AutoFac registration, you are registering it without passing any parameters, thus AutoFac can't create an instance of your PromoSliderObjectContext.

Either modify your registration to include connection string or follow the standard approach used by nopCommerce plugins.


And use builder.RegisterPluginDataContext<PromoSliderObjectContext>("nop_object_context_promo_slider"); in your dependency registration.

Hope that helps.

Best Regards
Anshul
2 years ago
I was going to be using the standard RegisterPluginDataContext approach, but the method is not available on ContainerBuilder in the Register method. Any reason why?
2 years ago
kinder wrote:
I was going to be using the standard RegisterPluginDataContext approach, but the method is not available on ContainerBuilder in the Register method. Any reason why?


It's an extension method. You'll have to reference the namespace in your file.

Regards,
Anshul
2 years ago
Have managed to register the DbContext Dependency thur RegisterType function like so:-
builder.RegisterType<PromoSliderObjectContext>()
                .WithParameter(new TypedParameter(typeof(DbContextOptions<PromoSliderObjectContext>), options))
                .InstancePerLifetimeScope();

But RegisterPluginDataContext is still not working. :/
2 years ago
Have you also changed the constructor to


public PromoSliderObjectContext(DbContextOptions<PromoSliderObjectContext> options): base(options)
{

}


Are you getting the same error?

Regards,
Anshul
1 month ago
Could some one HELP ME ?

I have an issue that I only used dependency injectiono time and it works well then later when I start to use dependency injection with any class it gives me exception error because of autofac while i already Registered the class in DependecyRegistrar. Could someone Help me ? ?