Ciao ho seguito il corso Pluralsight su NopCommerce, ma è per la versione precedente.
Ho cercato di creare la stessa funzionalità in NopCommerce 4.10
Quando provo a installare il plug-in, ottengo l'errore:
Non è stato trovato nessun costruttore che avesse soddisfatto tutte le dipendenze.
Nessuna tabella creata nel DB. L'errore afferma chiaramente che si tratta di una dipendenza non soddisfatta, ma quale è? Come posso soddisfarlo? Ho un contesto oggetto e 2 entità che sono state registrate con autofac e questo è tutto ciò di cui ho bisogno se ho ragione. Qual è il problema qui?
File plugin:
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"
}
Qualcuno può aiutarmi per favore!
Sto anche cercando di creare un plug-in NopCommerce 4.10 dal corso tutorial di PluralSight e ho riscontrato lo stesso errore. Quello che mi ha risolto è stato l'inclusione di un file PluginDbStartup.cs
. Prendi un esempio dai Nop.Plugin.Pickup.PickupInStore
-in Nop.Plugin.Pickup.PickupInStore
e Nop.Plugin.Shipping.FixedByWeightByTotal
, l'hanno implementato correttamente per 4.10.
La mia implementazione del plug-in è disponibile su https://github.com/florianock/NopCommerce_PromoSlider