NopCommerce based development framework with source code

Time:2021-9-15

. net developers should know that this famous high-quality B2C open source project, NopCommerce, is developed based on entityframework and MVC, has a transparent and well structured solution, and combines the best features of open source and commercial software. Official website address:http://www.nopcommerce.com/, Chinese website:http://www.nopcn.com/。 After downloading, the front and rear ends are shown as follows. If you haven’t learned about the project, it is recommended to download the code from the official website and run it locally to see the effect.

The author has developed many projects using this framework. Generally speaking, it is convenient and concise, and integrates many common components and functions of. Net development. I’ve always wanted to share it, but I’m busy working and haven’t reached it. Recently, I have time to write this article. This article will show how to extract the simplified framework of the source code and attach the source code (based on NopCommerce version 3.9). If you want to understand the framework structure and develop projects through the framework, it is valuable to read this article again. Front prompt: the source code of this framework has been uploaded to GitHub:https://github.com/dreling8/Nop.Framework, those who are interested can pay attention to the project. In the future, some other general modules will be added, such as user management (iworkcontext), plug-in function, task service, log, cache, localization, etc. Welcome star to the stars, your support is my motivation!

1、 Understand project structure

From the project structure diagram, we can also see that the hierarchy of NOP is very clear. Let’s look at the hierarchy diagram I drew first

1. Presentation

It can also be called application layer, which only focuses on the integration of the front end and does not involve any domain logic implementation. This layer is only for presentation and is dispensable to our framework. Therefore, this layer will be deleted when extracting the framework.

2. Business service layer (NOP. Services)

The service layer of the whole system provides the interface and implementation of each domain. This layer is very important. It provides the interface service for the presentation layer in the program. This layer service is required whether the presentation layer uses MVC, WinForm, or webapi interface called for app. However, the services in this layer are mainly e-commerce services, which is useless to our framework. Therefore, all services will be deleted in this framework, and only one test service class and interface will be added. When applied to the project, you should add interfaces and services in this layer.

3. Data layer (NOP. Data)

NOP uses EF and SQL Server Databases in the warehouse implementation of the data layer. If you want to expand, you can also use other ORM mapping libraries and databases in this layer. Most of the functions of this layer will be retained in the framework.

4. Infrastructure layer (NOP. Core)

Including cache implementation, configuration, domain model, etc. Some functions will be retained in the framework, and the domain domain domain model will be moved out of this layer for a separate project. Why do you do this? Usually, there are many adjustments to the domain layer, so I generally make the domain a separate project. Of course, you can not adjust it, but the framework has made the adjustment.

2、 Delete business related codes

We have understood the whole code hierarchy of NOP and began to modify the project source code based on the following two points: 1. The framework is streamlined enough without any e-commerce business. 2. Core functions are reserved. It is recommended to copy a copy of the source code before starting.

1. Test items:Under the tests folder are the test items, which are not necessary. Remove them all, develop specific businesses, and add test items separately. Because it is a test project, the whole project can run after deletion.

2. Presentation layer:The three projects here are the front end, the back end and some modules shared by the two projects. Like the test project, we also remove all of them here.

3. Plugin project:Plug in projects, like 1 and 2, are not required. Remove all plug-in projects. Now there are only three projects left (welcome to pay attention to the GitHub of the project, and I will write an article on how to add plug-ins later).

NOP. Services: business service layer, which is the external interface layer within the assembly and needs to be reserved. Delete all related business service classes, including logs, help, tasks, etc. related to the system, in order to better show the structure of the whole system. Add a test class and write nothing for the time being.

Nop.data: data layer project. This layer is basically not adjusted, and only the mapping related classes of EF are deleted.

NOP. Core: infrastructure layer. Delete the domain related to e-commerce business and create a new project nop.domain.

An error is reported. Iworkcontext (work context, used to obtain user information and other data) depends on the domain. Delete it. In this process, many files may be deleted until the project no longer reports errors. After completion, our project structure is as follows. Note that we have moved the entity base class in NOP. Core to NOP. Domain. At this step, our basic framework structure has been roughly drawn out.

3、 Add database, data entity, mapping, business layer code

1. In the local sqlserver, create a new database myproject and add a table test.


USE [MyProject]
GO 

/****** Object: Table [dbo].[Test] Script Date: 05/24/2017 23:51:21 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON

GO

CREATE TABLE [dbo].[Test](
[Id] [int] NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[Description] [nvarchar](200) NULL,
[CreateDate] [datetime] NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED



[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

2. Add entity classes and mappings. Create a new test directory under the domain project and add testentity. Create a new test directory under data project mapping and add EF mapping class.


public class TestEntity: BaseEntity
{ 

public virtual string Name { get; set; } 
public virtual string Description { get; set; } 
public virtual DateTime? CreateDate { get; set; }

}

3. Add business layer method.

In the NOP. Services project, add several common curd methods and implement them under the interfaces and classes we added earlier. In this way, we have implemented the code of the business layer.


/// <summary>

/// Test service interface

/// </summary>

public partial interface ITestService

{

/// <summary>
/// Gets all tests
/// </summary>
/// <returns>Tests</returns>

IList<TestEntity> GetAllTests();
 

/// <summary>
/// Gets a test
/// </summary>
/// <param name="testId">The test identifier</param>
/// <returns>Test</returns>

TestEntity GetTestById(int testId);

/// <summary>
/// Inserts a test
/// </summary>
/// <param name="test">Test</param>

void InsertTest(TestEntity test);

/// <summary>
/// Updates the test
/// </summary>
/// <param name="test">Test</param>

void UpdateTest(TestEntity test);

/// <summary>
/// Deletes a test
/// </summary>
/// <param name="test">Test</param>

void DeleteTest(TestEntity test);

}


/// <summary>
/// Test service
/// </summary>

public partial class TestService : ITestService

{

#region Constants
#endregion
#region Fields

 

private readonly IRepository<TestEntity> _testRepository;
#endregion
#region Ctor
public TestService(IRepository<TestEntity> testRepository)

{
this._testRepository = testRepository;

}
#endregion
#region Methods

 

/// <summary>
/// Gets all tests
/// </summary>
/// <returns>Tests</returns>

public virtual IList<TestEntity> GetAllTests()

{
return _testRepository.Table.Where(p => p.Name != null).ToList();

}

/// <summary>
/// Gets a topic
/// </summary>
/// <param name="testId">The test identifier</param>
/// <returns>Test</returns>

public virtual TestEntity GetTestById(int testId)
{

if (testId == 0)
return null;
return _testRepository.GetById(testId);

}

 

/// <summary>
/// Inserts a test
/// </summary>
/// <param name="test">Test</param>

public virtual void InsertTest(TestEntity test)
{
if (test == null)

throw new ArgumentNullException("test");
_testRepository.Insert(test);
 

}


/// <summary>
/// Updates the test
/// </summary>
/// <param name="test">Test</param>

public virtual void UpdateTest(TestEntity test)

{

if (test == null)
throw new ArgumentNullException("test");
_testRepository.Update(test);

}

/// <summary>
/// Deletes a test
/// </summary>
/// <param name="test">Test</param>

public virtual void DeleteTest(TestEntity test)

{

if (test == null)
throw new ArgumentNullException("test");
_testRepository.Delete(test);

}

#endregion

}

4、 Add presentation item

With business services, you can now add presentation layer projects to test. Why not write test items directly? Because the test project uses mock simulation data, the whole function cannot be fully displayed.

1. Add MVC template project and introduce Autofac and autofac.mvc5 through nuget.

2. Add the container registration class dependencyregistrar and implement the idependencyregistrar interface. This step is very key. We will inject the interface and implementation class to be used into the container.

/// <summary>
/// Dependency registrar
/// </summary>

public class DependencyRegistrar : IDependencyRegistrar

{

/// <summary>
/// Register services and interfaces
/// </summary>
/// <param name="builder">Container builder</param>
/// <param name="typeFinder">Type finder</param>
/// <param name="config">Config</param>

public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)

{

//Inject objectcontext

builder.Register<IDbContext>(c => new NopObjectContext("test")).InstancePerLifetimeScope();

//Inject EF into storage
builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
//Injection service and interface
builder.RegisterAssemblyTypes(typeof(TestService).Assembly)

.AsImplementedInterfaces()
.InstancePerLifetimeScope();

//Injection controllers
builder.RegisterControllers(typeFinder.GetAssemblies().ToArray());

} 

/// <summary>
/// Order of this dependency registrar implementation
/// </summary>

public int Order

{

get { return 2; }

}

}

3. Add a database access node to the configuration file

Copy codeThe code is as follows:
<add name=”test” connectionString=”Data Source=.;Initial Catalog=MyProject;Integrated Security=False;Persist Security Info=False;User ID=sa;Password=sa1234″ providerName=”System.Data.SqlClient” />

4. Add the initialization engine context when the application starts

When the project is started, nopengine will report an error because we did not use nopconfig to configure the project, annotate the injection of nopconfig in the registerdependences method, and annotate the relevant code in the initialize process. This completes the injection of classes into the container through Autofac.

public class MvcApplication : System.Web.HttpApplication
{

protected void Application_Start()
{

AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

//Engine context initialization

EngineContext.Initialize(false);

}

}
//Annotation injection of nopconfig in registerdependencies method

//builder.RegisterInstance(config).As<NopConfig>().SingleInstance();

public void Initialize(NopConfig config)

{

//register dependencies
RegisterDependencies(config);

 

//Config is not used. Please comment temporarily
//register mapper configurations
//RegisterMapperConfiguration(config);

 

//Startup tasks does not enable tasks, note
//if (!config.IgnoreStartupTasks)
//{
// RunStartupTasks();
//}

 

}

5. Add test code in controller. Add the service to the homecontroller and initialize it in the constructor. The instance will be injected automatically after the system is started. Through the breakpoint, we can see that the data is successfully added to the database.

public class HomeController : Controller

{

public ITestService _testService;
public HomeController(

ITestService testService
)

{
_testService = testService;

}

public ActionResult Index()

{
var entity = new TestEntity()
{
CreateDate = DateTime.Now,
Description = "description 2",
Name = "test data 2"

};

_testService.InsertTest(entity);

var tests = _testService.GetAllTests();

return View();

}

5、 Extend to webapi, WinForm, WPF

Now add another WinForm project, and add the relevant code in the same step. We can also use business services in WinForm.

1. Install Autofac and entityframework through nuget, and add references under the project libraries.

2. Add a dependency registration class because it is a WinForm project. Dependencyregistrar needs to make some adjustments here. It is recommended to define an empty interface iregistrarform, and the form to be injected implements iregistrarform.

/// <summary>
/// Dependency registrar
/// </summary>
public class DependencyRegistrar : IDependencyRegistrar

{

/// <summary>
/// Register services and interfaces
/// </summary>
/// <param name="builder">Container builder</param>
/// <param name="typeFinder">Type finder</param>
/// <param name="config">Config</param>

public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)

{

//Inject objectcontext

builder.Register<IDbContext>(c => new NopObjectContext("test")).InstancePerLifetimeScope();

 

//Inject EF into storage
builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
//Injection service and interface
builder.RegisterAssemblyTypes(typeof(TestService).Assembly)
.AsImplementedInterfaces()
.InstancePerLifetimeScope();

//Injection controllers
//builder.RegisterControllers(typeFinder.GetAssemblies().ToArray());


//Injection forms

var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IRegistrarForm))))
.ToArray();
foreach (var formtype in types)
{

builder.RegisterAssemblyTypes(formtype.Assembly);

}

 

}

 

/// <summary>
/// Order of this dependency registrar implementation
/// </summary>
public int Order

{

get { return 2; }

}

}

3. When starting, add enginecontext. Initialize (false), start the project and report an error because WinForm cannot be executed. Make some adjustments to the method, and add a parameter isform to indicate whether it is WinForm, which is false by default.

/// <summary>
  /// Initializes a static instance of the Nop factory.
  /// </summary>
  /// <param name="forceRecreate">Creates a new factory instance even though the factory has been previously initialized.</param>
  ///< param name = "iswinform" > client program < / param >
  [MethodImpl(MethodImplOptions.Synchronized)]
  public static IEngine Initialize(bool forceRecreate,bool isWinForm = false)
  {
   if (Singleton<IEngine>.Instance == null || forceRecreate)
   {
    Singleton<IEngine>.Instance = new NopEngine();

    NopConfig config = null;
    if (!isWinForm)
    {
      config = ConfigurationManager.GetSection("NopConfig") as NopConfig;
    }
    else
    { 
     //If WinForm is used, use this code to read the configuration and initialize nopconfig
     var appSettings = ConfigurationManager.AppSettings;
     foreach (var key in appSettings.AllKeys)
     {
       
     }
    }

    
    Singleton<IEngine>.Instance.Initialize(config);
   }
   return Singleton<IEngine>.Instance;
  }
static class Program

{

/// <summary>
///The main entry point for the application.

/// </summary>
[STAThread]

static void Main()

{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
//Engine context initialization

EngineContext.Initialize(false, true);
Application.Run(EngineContext.Current.Resolve<Form1>());

}

}

4. The test in from1 successfully called the business layer method. Here, we did not instantiate itestservice, but handed it to the automatic implementation of dependency injection.

public partial class Form1 : Form, IRegistrarForm

{
private ITestService _testService;

public Form1(
ITestService testService

)

{

InitializeComponent();

_testService = testService;

//If the form is not injected, you can use enginecontext. Current. Resolve < itestservice > (); Get examples

}

 

private void button1_Click(object sender, EventArgs e)
{
var tests = _testService.GetAllTests();

}

}

So far, the streamlined development framework based on NOP has been basically completed. If you are interested, you are recommended to pay attention to the project in GitHub:https://github.com/dreling8/Nop.FrameworkWelcome star to the stars, your support is my motivation!

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.

Recommended Today

Beautify your code VB (VBS) code formatting implementation code

However, vb.net does have many new functions that VB6 does not have. The automatic typesetting of code is one, which is the function we want to realize today – VB code formatting.Let’s look at the effect: Before formatting: Copy codeThe code is as follows: For i = 0 To WebBrowser1.Document.All.length – 1 If WebBrowser1.Document.All(i).tagName = […]