Step by Step Instructions for Adding a new SQL Table To NopCommerce 2.4

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
12 years ago
***************************************************************************************************
Step 1: Add your new database tables in SQL Server (Hint: use the field name Id for an incremental integer primary key)
***************************************************************************************************

***************************************************************************************************
Step 2: Install the Entity Framework Reverse Engineering Power Tool
(See: http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d)
***************************************************************************************************

***************************************************************************************************
Step 3: Create a new C# Console project in Visual Studio 2010
Create all your class entities and mappings by Right Clicking on the project you created, selecting Entity Framework and Reverse Engineering Code First.
(Hint: I couldn't get it to work for the database on my Web Host's server unless Persist Security Info=True)
***************************************************************************************************

***************************************************************************************************
Step 4: Open up your nopCommmerce Application and start adding files from top to bottom starting with Nop.Core

Libraries\Nop.Core:


Domains:
Create a new folder under Domains (Ex. CalendarEvent)
Add a class under the new folder (Ex. CalendarEvent.cs)
Replace the top of the class with:
using System;
using System.Collections.Generic;
using Nop.Core;
using Nop.Core.Domain.Localization;

Change class CalendarEvent to public partial class CalendarEvent : BaseEntity, ILocalizedEntity

add the line private ICollection<Nop.Core.Domain.CalendarEvent.CalendarEvent> _calendarEvents;
Copy in the set and gets created in the project that used the Entity Framework Reverse Engineer tool (Found in the Entities Folder) from Step 3.
Comment Out the Primary key (ex.: // public int Id { get; set; })
For the rest of the get and sets, replace the word public with public virtual

Add the following at the end:
  ///// <summary>
       ///// Gets or sets the CalendarEvents
        ///// </summary>
        public virtual ICollection<Nop.Core.Domain.CalendarEvent.CalendarEvent> CalendarEvents
        {
            get { return _calendarEvents ?? (_calendarEvents = new List<Nop.Core.Domain.CalendarEvent.CalendarEvent>()); }
            protected set { _calendarEvents = value; }
        }

Add another class called CalendarEventSortingEnums.
You can remove the usings at the top
Change  class CalendarEventSortingEnums to  public enum CalendarEventSortingEnums
Enter in a few enums for primary sorting purposes
Example:
       eventStartDateSort = 0,
        ticketsGoOnSaleStartSort = 5,
        eventTitleSort = 10,
Don't ask me why the last one has a comma, it just does
***************************************************************************************************

***************************************************************************************************
Step 5: Libraries\Nop.Data
Mappings:
Create a new folder under Domains (Ex. CalendarEvent)
Add a class under the new folder (Ex. CalendarEventMap.cs)
Replace the top usings with:
using System.Data.Entity.ModelConfiguration;
using Nop.Core.Domain.CalendarEvent;
Change class CalendarEventMap to   public partial class CalendarEventMap : EntityTypeConfiguration<Nop.Core.Domain.CalendarEvent.CalendarEvent>

Copy in all that t. stuff created in the project that used the Entity Framework Reverse Engineer tool (Found in the Mapping Folder) from Step 3.

Copy in all that t. stuff starting with:
public CalendarEventMap()
    {
      // Primary Key
      this.HasKey(t => t.EventId);

***************************************************************************************************

***************************************************************************************************
Step 6: Libraries\Nop.Services
Create a new Folder (Ex.: CalendarEvent)
Add a class under the new folder (Ex. CalendarEventService.cs)
Replace the usings with something like:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Data;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.CalendarEvent;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Localization;
using Nop.Core.Domain.Orders;
using Nop.Core.Events;
using Nop.Data;
using Nop.Services.Localization;
using Nop.Services.Messages;

change class CalendarEventService to public partial class CalendarEventService : ICalendarEventService

This one is kind of tricky and too wordy to list the changes. I am afriad you will have to go solo on this one. You will have to duplicate by copying and pasting and tweaking some of the other services code such as the Manufactuer Service. Also, you will have to create the ICalendarEventService before you get rid of the errors when you create the CalendarEventService.
***************************************************************************************************

***************************************************************************************************
Step 7: Nop.Web:
I know I have been going from Top to bottom so far but I start jumping around at this point. It is probably better to create the Model classes before you create the Mapping Extensions.

Models:
Create a new Folder (Ex.: CalendarEvent)
Add a class under the new folder (Ex. CalendarEventModel.cs)
Replace the Usings at the top with:
using System.Collections.Generic;
using Nop.Web.Framework.Mvc;
using Nop.Web.Models.Media;

Replace  public class CalendarEventModel with public class CalendarEventModel : BaseNopEntityModel

Add:
      public CalendarEventModel()
        {
            //PictureModel = new PictureModel();
            //FeaturedProducts = new List<ProductModel>();
            //Products = new List<ProductModel>();
            //PagingFilteringContext = new CatalogPagingFilteringModel();
        }
Note that I copied in some code of possible related tables that I commented out. This is a good reference for when you start relating
your new tables to each other

Copy in the set and gets created in the project that used the Entity Framework Reverse Engineer tool (Found in the Entities Folder) from Step 3.
Comment out the first get set referring to the primary key Id
Note: I have date fields so I added using System; because I was getting an error with  public Nullable<System.DateTime>
Example:
//public int Id { get; set; }
              public string EventStatus { get; set; }
              public string EventTitle { get; set; }
              public string EventBody { get; set; }
              public string EventDirections { get; set; }
              public Nullable<System.DateTime> EventStartDate { get; set; }
              public Nullable<System.DateTime> EventEndDate { get; set; }
              public Nullable<int> SortOrder { get; set; }
...


At the bottom of the class, add:
//public PictureModel PictureModel { get; set; }

        public CalendarEventPagingFilteringModel PagingFilteringContext { get; set; }

        //public IList<ProductModel> FeaturedProducts { get; set; }
        //public IList<ProductModel> Products { get; set; }

Next, we have to create CalendarEventPagingFilterModel to get rid of the error we just created.
Add the class CalendarEventPagingFilterModel
Replace the Usings with:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using Nop.Core;
using Nop.Core.Domain.CalendarEvent;
using Nop.Services.CalendarEvent;
using Nop.Services.Localization;
using Nop.Web.Framework;
using Nop.Web.Framework.Mvc;
using Nop.Web.Framework.UI.Paging;


Replace public class CalendarEventPagingFilteringModel with  public class CalendarEventPagingFilteringModel : BasePageableModel

You will have to add nested classes (see other PagingFilterModel classes as examples) but at least enter the following:
  #region Constructors

         public CalendarEventPagingFilteringModel()
        {
            this.AvailableSortOptions = new List<SelectListItem>();
            this.AvailableViewModes = new List<SelectListItem>();
            this.PageSizeOptions = new List<SelectListItem>();

        }

        #endregion

        #region Properties

      
        public bool AllowCalendarEventSorting { get; set; }
        public IList<SelectListItem> AvailableSortOptions { get; set; }

        public bool AllowCalendarEventViewModeChanging { get; set; }
        public IList<SelectListItem> AvailableViewModes { get; set; }

        public bool AllowCustomersToSelectPageSize { get; set; }
        public IList<SelectListItem> PageSizeOptions { get; set; }

        /// <summary>
        /// Order by
        /// </summary>
        [NopResourceDisplayName("CalendarEvent.OrderBy")]
        public int OrderBy { get; set; }

        /// <summary>
        /// CalendarEvent sorting
        /// </summary>
        [NopResourceDisplayName("CalendarEvent.ViewMode")]
        public string ViewMode { get; set; }


        #endregion

Hint: NopResourceDisplayName

Add the Class SearchModel.cs
Replace the Usings with:
using System.Collections.Generic;
using System.Web.Mvc;
using Nop.Web.Framework;
using Nop.Web.Framework.Mvc;

Replace   public class SearchModel with public class SearchModel : BaseNopModel

Add:
  public SearchModel()
        {
            PagingFilteringContext = new SearchPagingFilteringModel();
            CalendarEvents = new List<CalendarEventModel>();


            this.AvailableCalendarEvents = new List<SelectListItem>();
            //this.AvailableManufacturers = new List<SelectListItem>();
        }

        public string Warning { get; set; }

        public bool NoResults { get; set; }

        /// <summary>
        /// Query string
        /// </summary>
        [NopResourceDisplayName("Search.SearchTerm")]
        [AllowHtml]
        public string Q { get; set; }

        /// <summary>
        /// ID
        /// </summary>
        [NopResourceDisplayName("Search.Id")]
        public int Id { get; set; }

                /// <summary>
        /// FLAnnualBusinesses ID
        /// </summary>
        //[NopResourceDisplayName("Search.FLAnnualBusinessesId")]
        //public int FLAnnualBusinessesid { get; set; }

        //[NopResourceDisplayName("Search.Id")]
        //public int Id { get; set; }

        /*
        /// <summary>
        /// Manufacturer ID
        /// </summary>
        [NopResourceDisplayName("Search.Manufacturer")]
        public int Mid { get; set; }
        /// <summary>
        /// Price - From
        /// </summary>
        [AllowHtml]
        public string Pf { get; set; }
        /// <summary>
        /// Price - To
        /// </summary>
        [AllowHtml]
        public string Pt { get; set; }
      
        /// <summary>
        /// A value indicating whether to search in descriptions
        /// </summary>
        [NopResourceDisplayName("Search.SearchInDescriptions")]
        public bool Sid { get; set; }
        /// <summary>
        /// A value indicating whether to search in descriptions
        /// </summary>
         *  */

        [NopResourceDisplayName("Search.AdvancedSearch")]
        public bool As { get; set; }
        public IList<SelectListItem> AvailableCalendarEvents { get; set; }
       //public IList<SelectListItem> AvailableManufacturers { get; set; }

        public SearchPagingFilteringModel PagingFilteringContext { get; set; }
        public IList<CalendarEventModel> CalendarEvents { get; set; }

We still have an error with SearchPagingFilteringModel

Add the class SearchPagingFilteringModel
using Nop.Web.Framework.UI.Paging;

namespace Nop.Web.Models.CalendarEvent
{
    public class SearchPagingFilteringModel : BasePageableModel
    {
    }
}

We should have no errors at this point
***************************************************************************************************

***************************************************************************************************
Step 8: Nop.Web:

Extensions:
Open up MappingExtensions.cs
Add using Nop.Web.Models.CalendarEvent;

This part is a little bit of a pain. Use your Find and Replace skills to add the following for each field in the table:
//CalendarEvent
        public static CalendarEventModel ToModel(this CalendarEventModel entity)
        {
            if (entity == null)
                return null;

            //Name = entity.GetLocalized(x => x.Name),
            //    Description = entity.GetLocalized(x => x.Description),
            //    MetaKeywords = entity.GetLocalized(x => x.MetaKeywords),
            //    MetaDescription = entity.GetLocalized(x => x.MetaDescription),
            //    MetaTitle = entity.GetLocalized(x => x.MetaTitle),
            //    SeName = entity.GetSeName(),

            var model = new CalendarEventModel()
            {
                Id = entity.Id,
                EventStatus = entity.EventStatus,
                EventTitle = entity.EventTitle,
                EventBody = entity.EventBody,
                EventDirections = entity.EventDirections,
                EventStartDate = entity.EventStartDate,
                EventEndDate = entity.EventEndDate,
                SortOrder = entity.SortOrder,
                TicketsGoOnSaleStart = entity.TicketsGoOnSaleStart,
                TicketsGoOnSaleEnd = entity.TicketsGoOnSaleEnd,
                FeatureEventStart = entity.FeatureEventStart,
                FeatureEventEnd = entity.FeatureEventEnd,
                MainSKU = entity.MainSKU,
                MainURL = entity.MainURL,
                MainPDFURL = entity.MainPDFURL,
                MainRegistrationURL = entity.MainRegistrationURL,
                MainVenueId = entity.MainVenueId,
                MainArtistId = entity.MainArtistId,
                MainInfoContactId = entity.MainInfoContactId,
                MainInfoContact = entity.MainInfoContact,
                MainInfoTo = entity.MainInfoTo,
                MainInfoCC = entity.MainInfoCC,
                MainInfoBCC = entity.MainInfoBCC,
                MainBillingContactId = entity.MainBillingContactId,
                MainBillingContact = entity.MainBillingContact,
                MainBillingTo = entity.MainBillingTo,
                MainBillingCC = entity.MainBillingCC,
                MainBillingBCC = entity.MainBillingBCC,
                Tags = entity.Tags,
                OpenToPublic = entity.OpenToPublic,
                NoLongerAvailableMessage = entity.NoLongerAvailableMessage,
                CreatedOnUtc = entity.CreatedOnUtc,
                CreatedBy = entity.CreatedBy,
                UpdatedOnUtc = entity.UpdatedOnUtc,
                UpdatedBy = entity.UpdatedBy,


            };
            return model;
        }

***************************************************************************************************

***************************************************************************************************
Step 9: Nop.Web

Infrastructure/RouteProvider.cs

Add the following:

            //CalendarEvent
            // LJD 03/30/2012
            routes.MapLocalizedRoute("CalendarEventList",
                            "CalendarEvent/all/",
                            new { controller = "CalendarEvent", action = "CalendarEventAll" },
                            new[] { "Nop.Web.Controllers" });
            routes.MapLocalizedRoute("CalendarEvent",
                            "m/{Id}/{SeName}",
                            new { controller = "CalendarEvent", action = "CalendarEvent", SeName = UrlParameter.Optional },
                            new { Id = @"\d+" },
                            new[] { "Nop.Web.Controllers" });

***************************************************************************************************

***************************************************************************************************
Step 10: Nop.Web.Framework
Open up DependencyRegistrar.cs

Add using Nop.Services.CalendarEvent;

Add builder.RegisterType<CalendarEventService>().As<ICalendarEventService>().InstancePerHttpRequest();
***************************************************************************************************

***************************************************************************************************
Step 11: Nop.Web\Administration\
Adding the Administration Model:
Right Click on the Models folder in Nop.Administration and add a new folder called CalendarEvent
Add a new class called CalendarEventModel
Also too wordy to go through what to put into the class. Look at another Administration Model Class as a guide to creating this Model

Add CalendarEventListModel.cs
Change the Usings to:
using System.Collections.Generic;
using System.Web.Mvc;
using Nop.Web.Framework;
using Nop.Web.Framework.Mvc;
using Telerik.Web.Mvc;

Change public class CalendarEventListModel To public class CalendarEventListModel : BaseNopModel

Add:
public CalendarEventListModel()
        {
            //AvailableCategories = new List<SelectListItem>();
          
        }

        public GridModel<CalendarEventModel> CalendarEvents { get; set; }

        [NopResourceDisplayName("Admin.CalendarEvent.List.SearchCalendarEventeventTitle")]
        [AllowHtml]
        public string SearcheventTitle { get; set; }

        [NopResourceDisplayName("Admin.CalendarEvent.List.SearchCalendarEventeventStartDate")]
        [AllowHtml]
        public string SearcheventStartDate { get; set; }

        [NopResourceDisplayName("Admin.CalendarEvent.List.SearchCalendarEventticketsGoOnSaleStart")]
        [AllowHtml]
        public string SearchticketsGoOnSaleStart { get; set; }

***************************************************************************************************

***************************************************************************************************
Step 12: Nop.Web\Administration\
Adding the Administration Validator:
Right Click ont the Validators folder in Nop.Administration and add a new folder called CalendarEvent
Add a new class called CalendarEventValidator
Add the following:

using FluentValidation;
using Nop.Admin.Models.CalendarEvent;
using Nop.Services.Localization;

namespace Nop.Admin.Validators.CalendarEvent
{
    public class CalendarEventValidator : AbstractValidator<CalendarEventModel>
    {
        public CalendarEventValidator(ILocalizationService localizationService)
        {
            RuleFor(x => x.eventTitle).NotNull().WithMessage(localizationService.GetResource("Admin.CalendarEvent.Fields.eventTitle.Required"));
        }
    }
}
Hint: The LocaleStringResource Table is where you add the records for your strings
***************************************************************************************************

***************************************************************************************************
Step 14: Nop.Web\Administration\
Open Views\MappingExtensions.cs
Add:
using Nop.Admin.Models.CalendarEvent;
using Nop.Core.Domain.CalendarEvent;
using Nop.Services.CalendarEvent;

Add:

#region CalendarEvent
        public static CalendarEventModel ToModel(this CalendarEvent entity)
        {
            return Mapper.Map<CalendarEvent, CalendarEventModel>(entity);
        }

        public static CalendarEvent ToEntity(this CalendarEventModel model)
        {
            return Mapper.Map<CalendarEventModel, CalendarEvent>(model);
        }

        public static CalendarEvent ToEntity(this CalendarEventModel model, CalendarEvent destination)
        {
            return Mapper.Map(model, destination);
        }
        #endregion
***************************************************************************************************

***************************************************************************************************
Step 15: Nop.Web\Administration\
Adding the Administration Controller:

Right Click on the Controllers Folder in Nop.Admin and add a new Controller
Call it CalendarEventController.cs

Replace the Usings with:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Nop.Admin.Models.Catalog;
using Nop.Admin.Models.CalendarEvent;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.CalendarEvent;
using Nop.Core.Domain.Common;
using Nop.Services.Catalog;
using Nop.Services.CalendarEvent;
using Nop.Services.ExportImport;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Mvc;
using Telerik.Web.Mvc;


Change  public class CalendarEventController : Controller to
[AdminAuthorize]
public class CalendarEventController : BaseNopController
Again, much too wordy to detail the rest.
Look at other controllers to finish this Controller Class

Now you can start working on your views for your front end for this table.
Again, look at other views within NopCommerce for the basic layout.

***************************************************************************************************
12 years ago
Hi Louis, I've been reading your post, it is really good to pin point me on a direction I wanted to explore, however, I have a quick question, on step 4, where you state "Open up your nopCommmerce Application and start adding files from top to bottom starting with Nop.Core", you mean, merging NopCommerce Structure into the Console APP, or the other way around, moving the generated files into the NopCommerce Structure?.  Perhaps you could put a bit more detail on the new table design?.

Look forward to read from you.

regards from mexico.

ximbal
12 years ago
When he says

'Step 4: Open up your nopCommmerce Application and start adding files from top to bottom starting with Nop.Core'

He means open up the source code files for NopCommerce in Microsoft Visual Studio V10 and start adding files to the solution.

HTH
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.