Pages - Menu

%5B%5D issue when binding JSON Array to MVC Model


Had some issues during a post back of JSON object from the MVC View to the Controller by jQuery Ajax. To be precise, I am actually using Telerik Control that utilize jQuery Ajax. One of the IList<string> property is not populated in the model.


Troubleshooting


With the help of firebug, the JSON post back of the array has this extra %5B%5D in the name of the fields. Thus MVC framework couldn't map it to the property.




Solution


It takes one magic line of code for the JSON post back not to include this extra URL encoded characters in the field name. It is documented in the jQuery API

$.ajaxSettings.traditional = true;



Now the post back is correct and the MVC model can be populated.




nopCommerce - Register route for SEO Friendly Url Redirect

Scope

This document is scoped to nopCommerce 3.1. The latest version as of 2 months ago, now the latest stable nopCommerce is up to 3.2 as of today.

My goal today, is to add custom logics in the CatalogController, so that all SEO Friendly Url (generic path) will go to my custom controller not the default controller. Previously, I documented here on how I create custom controller. It is similar to what I have done before, but generic path are handled differently in nopCommerce.

Route

As documented in the official FAQ, we know how to register route for normal pages. For admin pages, I got that covered here. Today, we are going to look at how SEO Friendly pages work. 

SEO Friendly pages are the ones that does not follow the standard MVC url pattern.

In summary, there are 3 types of routes in nopCommerce.

http://mydomain/checkout/completed/
It is a normal page. It reference to the Checkout Controller and the Completed Action.

http://mydomain/Admin/setting/Catalog
It is an admin page. It is referencing to the Setting Controller and the Catalog Action from the admin area.

http://mydomain/women-s-logo-stretch-full-zip-hoodie
It is a SEO page. It is handled by a special route provider called GenericUrlRouteProvider. The string "women-s-logo-stretch-full-zip-hoodie" is called a SEO slug, usually referenced by the SeName property in some of the nopCommerce objects.

GenericUrlRouteProvider

GenericUrlRouteProvider is located in Nop.Web\Infrastructure.



By default, it has a priority set to -1000000, this is latest route by default, but of course you can override it. There are 2 type of methods are being called inside this file. MapGenericPathRoute and MapLocalizedRoute. In fact, they are not just different methods, but the methods are coming from different objects.

MapGenericPathRoute belongs to the object GenericPathRoute; and MapLocalizedRoute belongs to the object LocalizedRoute. And they have the following relationship.
public partial class GenericPathRoute : LocalizedRoute
public class LocalizedRoute : Route
There is also the following comment in this file by the core developer. This is a very important note and we will see in a minute.
//define this routes to use in UI views (in case if you want to customize some of them later)

GenericPathRoute 

As it is named, everything that are generic will get pass to this handler. All works are done inside this file. As in the source code, everything is hard coded.


This is a very important fact to know. The default behaviour of nopCommerce is not passing in any namespace, and the only way to change it is inside this piece of code.

This is located in the Nop.Web.Framework\Seo

In this example, I have added the following line, and now the .Net engine will look for the controller in the correct namespace.

data.DataTokens["Namespaces"] = new[] { "Nop.Web.Controllers.Custom" };

LocalizedRoute


LocalizedRoute handles the virtual path. It provides functionalities for the HTML helper to render any hyperlinks in the view (UI). Any changes here should be complimented by changes in GenericPathRoute.

This is located in the Nop.Web.Framework\Localization

Summary

MapGenericPathRoute would change the route provider behaviour such that when an seo-friendly url is requested, the right controller will be called in the system.

MapLocalizedRoute changes the way how the HTML helper would generate the url for links inside the view. Hence the comments from core team was saying "define this routes to use in UI views". 

nopCommerce - Customization for Model

Scope

Due to business requirements on the category page, I need to extend and introduce some new fields to the CategoryModel.


Implementation

The way how nopCommerce designed architecture is that the commonly used classes are hinted by the keyword partial. This allows developers to extend the class in the same assembly without much effort. I previously stated that this is not a clean solution and I preferred an alternate method by using IoC.

I cannot however use IoC in this scenarios.

Model instantiation are handled inside the controllers, in fact inside the methods of the controllers!! This prevented me from using dependency injection for model instantiation.

The models in nopCommerce are not inherited to any interface. Without polymorphism, it is difficult to extend objects.


Partial class didn't take me much effort to extend and fairly easy to use. The drawback is I am ending up with many loose files in the project. This is however a feasible solution.

Is this an Anti-Pattern?

Nop.Web is an MVC project that has the model, view and controllers inside. Views are meant to be dirty, as they are the UI. Thus, the project is meant to be and would be dirty.

The truth is if you are using nopCommerce as a platform for multi-tenant websites, there are some clever ways of doing this such as controller factory. It gives the controllers and models a separation from the project.




nopCommerce - EF Configuration for SQL Composite Key

It is a common practice in the fashion industry that they have designer colors like crimson or scarlet for their fashion piece, but the majority of the consumers would only use common color name like red.

I build some custom SQL tables in nopCommerce by using Entity Framework Code First.



The following is the SQL tables, where color has a field IsCore to indicate if it is a core color, and ColorMapping has a composite key that does the mapping. Fairly straight forward.


In nopCommerce, I built a custom admin screen that does the mapping. For those who are curious, the titles are dynamically pulled from the core colors in the table with IsCore flag set to true. This is similar logics I get from the Shipping Method Restrictions screen.



So far so good. One thing that got me though is the EF Configuration.

Trying random things will get different kind of errors.





How about try to copy from the ShippingMethodMap? (It is located in Nop.Data\Mapping\Shipping\) Afterall, it has the same SQL structure. The .HasMany .WithMany approach were a bit messy and didn't quite well for me.

The simplest approach seems to work for me. In my ColorMappingMap, I created a composite key and ignore the field Id. Remember, we don't have Id in the SQL table.



While on the topic of fashion industry. I just received my invitations to the Mercedes-Benz Fashion Week Australia SS 14/15 in April. Who is going?




nopCommerce - Where is the DB Connection String?

Database Connection String

This maybe a frequently asked question in nopCommerce. Where do you change the connection string for database? Web.config has been the known location for many .Net web developers, but nopCommerce takes a different approach.

The string is stored in a plain text file called Settings.txt located in App_Data, not so obvious, but once you find it, it is obvious. :)


But Why??

As to why not use the web.config? That would be a question for the core team. Why not use web.config and take advantage of the web.config transformation to easily manage the differences between development, staging and live environments? I want to know the answer too!!