We launched a
new site recently, and I'm posting here some thoughts that might be helpful to others.
Since the beginning of our project, it has been a top priority to ensure that our customizations are made in way that minimizes the complexity of upgrading to new versions of NopCommerce. We built the site on version 1.4 and recently upgraded to version 1.5. The upgrade effort went smoothly. Here are some strategies we employed:
DocumentationWe documented every file that was modified and every configuration change that was made. We did not document the detail of those modifications; preferring instead to add comments with within the modified files. Here is our document if you’d like to see what we modified (http://dl.dropbox.com/u/4026885/NopCommerce/SolutionCustomization.doc).
CommentsWithin each modified file a comment with the prefix //HACK: was added to identify each customization. We used the word “HACK” because it’s recognized by Visual Studio in the task window. Within ASPX and ASCX files the comment was surrounded by <% %>. When used this way, they’re not picked up as tasks, but the main benefit to us is the ability to search the solution for “//HACK” to see every customization point.
Source ControlWe used the Subversion “svn:external” property to share source files from other projects into the NopCommerce solution. That way we can continue to maintain one set of shared code where applicable. On a side note, we had too much difficulty performing a merge to update our source control system with the 1.5 code base, so instead we tagged our final 1.4 code, then deleted everything in the trunk, and re-added the customized 1.5 code.
Website AdditionsAll new web files were added to a new root folder called “Additions”. The content of this folder mimics the NopCommerce folder organization convention. For example, we created sub-folders Administration, Controls, Modules and Templates to contain the applicable files. One caveat of this approach is that “/Additions” is included in the URL of new ASPX files, but for us the benefit of isolating the customization outweighed this drawback.
Website ModificationsIf a file required modification, we considered whether to put a copy of the file into the Additions folder and update existing references to the file, or modify the file in place. The chosen approach was the one that caused the lesser impact to the existing code base. Usually, this was to put a copy in the Additions folder, but some user controls were referenced in many places so it made more sense to modify in place.
Removing Unwanted FeaturesWe first looked in the admin area for a method to turn off unwanted screen elements. Btw, if you don’t find anything, look for conditional display logic in the code behind of the applicable user control to make sure you didn’t miss it. In cases where there wasn’t an available setting to turn off the item, we targeted it via CSS with “display: none”. In general, the NopCommerce markup provides sufficient classes to target applicable elements this way. One exception was the Shipping & Returns link in InfoBlock.ascx, so we addressed that one by putting a modified copy in our /Additions/Modules folder.
Administration AreaInclusion of new modules in the admin area was as simple as updating Admin.sitemap (we put a copy in /Additions/Administration and modified that instead). One thing to be aware of when creating admin functionality in a folder other than /Administration is that you will need to copy the Web.config from the Administration folder to your Additions/Administration folder. This will apply various admin area configurations to your files, such as selection of the right app theme and inclusion of namespace references. Only in one case did we add functionality to an existing module in the Admin area. We added a new tab (called “Extra”) to the Product Variant screen. To integrate the new user control for this tab required an in-place modification to an existing NopCommerce user control.
Page InheritanceWe updated BaseNopMasterPage and BaseNopPage to inherit from new classes rather than the standard .NET ones. This allowed us to customize page processing and rendering without interfering with existing NopCommerce code. Our new classes were put in /Additions/Controls.
Master Pages and App ThemeWe made an early decision to stylize the site as much as possible without modifying the standard markup because we wanted to minimize rework after upgrades. However, if you do choose to make more extensive modifications to the rendered markup, then the impact should not be too great if you can confine the changes to the master pages. We made a copy of the default darkOrange theme and started customizing. The upgrade to 1.5 had an unexpected impact to our custom theme because the CSS classes had all been renamed, but this was fairly easy to fix.
Business LogicThe NopCommerce team has thoughtfully used the partial keyword on classes, so we were able to create new classes with the same name to add functionality to existing objects. The new class files were put in a folder Nop.BusinessLogic/Additions with sub-folders mimicking the main folder structure. The namespace of these classes should not include “.Additions” because they need to match the existing partial classes exactly.
DALWe used LINQ-to-SQL to get to the database when existing business logic objects didn’t provide the functionality we needed. It was a lot faster than making additions to the existing BLL, DAL interface, and physical DAL classes. This was fine for us, but we’re not necessarily recommending this approach ;)
Solution ModificationsWe created a solution folder called “External” (in retrospect I would call this “Additions” instead for consistency instead). New projects were added here. We had to add several references to existing NopCommerce projects to incorporate the new dependencies.
Multi-Lingual EntitiesAdding multiple language support for products and categories was the most invasive customization we had to make. Quite a few stored procedures needed modification, and in cases where a new parameter was added (the locale), we had to modify the DAL and BLL code as well. We didn’t modify the admin UI, preferring instead to export the data to an existing localization tool, and reimport the translations.
Database TablesIt’s worth noting that we never modified any existing NopCommerce tables. Instead, we always added new tables to support new functionality (using a different table prefix than “Nop_”). This means that we had tables like Napp_ProductVariant to store the additional product variant attributes we needed. In general, I don’t like “add-on” tables, but in this particular case, the benefit of isolation outweighed the ugliness of this approach.
Those are the main points that I can think of. As we worked on the implementation we treated each potential impact to the existing code base as a major issue to be avoided if at all possible, and otherwise, to be documented. I think it’s important to have this mindset if you want to be able to keep pace with future upgrades without facing major challenges.
Regards,
Gary