I have been reading some very good post from Wooncherk, Twisted Whisperer, and Alex Wolf. Their articles respectively (Wooncherk), (Twisted Whisperer), and (Alex Wolf) have
The most important thing is getting the controller to hit, the other things require some tweaking.
The routing is not correctly overridden, see http://www.nopcommerce.com/boards/t/27039/plugin-override-admin-route.aspx
The view in the admin project is used due to the path set as a custom view location: ~/Administration/MyExtension/Views. NopCommerce does not know which views are embedded in the plugins.
For a plugin based solution make sure the CustomViewEngine, RouteProvider and the views are in the plugin. Make sure the views are copied to the output directory. Register the output folder of the views in the plugin as the custom view location, for example ~/Plugins/MyPlugin/Views/Admin.
If I read your question correctly, you are creating a plugin and trying to do all the plumbings in this plugin without touching the core Admin files at all. Then you have to put all those files in your plugin project and not in Nop.Admin
From the looks of it, you are overriding both the Controller and View of the back-end (Admin area). The SO post that you quote in which my answer is only catered for overriding Admin Views, not Controllers. Overriding Controller in the Admin area is different than overriding View, and even more different if you're overriding Controllers of the front-end (assuming SEO friendly URL is involved).
Overriding a Controller is essentially asking ASP.NET MVC to use your custom Controller to serve request instead of the original Controller. Requests are directed to Controllers through Routes. So overriding a Controller is just simply manipulating Routes to direct requests to your custom Controller.
ASP.NET MVC keeps a universal lookup table that contains Routes and is called the RouteTable.Routes. A Route contains data of
Every time there's an incoming request, ASP.NET MVC will search RouteTable.Routes from top to bottom to find a route whose URL Pattern matches the request's URL. The first matching route will be used to direct the request to the matching route's Controller. There are probably several matching routes in the table but only the first will be used. Therefore, we can say the route at the top of the table has the highest precedence. Hence, the key of overriding an existing Controller is to make sure that the route pointing to your custom Controller is registered earlier than the route pointing to the original Controller
In nopCommerce, you do not need to directly manipulate the RouteTable.Routes lookup table. Normally you would just register your custom Controller route in the RegisterRoutes method of a class implementing the IRouteProvider interface with the Priority higher than the original Controller route (not applicable for SEO friendly URLs Area routes). The higher the Priority, the earlier the route is registered and therefore the higher it will be positioned in the lookup table. However, the back-end of nopCommerce is actually an ASP.NET MVC Area named Admin. This fact made it tricky to override routes the usual way. This is because, in the global.asax
//global.asax
protected void Application_Start() {
//.... Omitted for brevity
//Registering some regular mvc stuff
//The two lines below populate the RouteTable.Routes
AreaRegistration.RegisterAllAreas(); //add Area routes into the lookup table first such as the "Admin" area
RegisterRoutes(RouteTable.Routes); //followed by adding routes of classes implementing **IRouteProvider**
//.... Omitted for brevity
}
As you can see above, area routes are always registered first and therefore has the highest precedence. Hence, in IRouteProvider, no matter how high you set the Priority, it will still be lower than area routes. Because of this, you will have to manipulate the RouteTable.Routes directly. In your IRouteProvider
public void RegisterRoutes(RouteCollection routes)
{
ViewEngines.Engines.Insert(0, new CustomViewEngine());
var route = routes.MapRoute("Plugin...OrderDetailsOverride",
"Admin/Order/Edit/{id}",
new { controller = "MyOrder", action = "Edit" area = "Admin" }, //notice 'area="Admin"' is added
new { id = @"\d+" },
new[] { "MyPlugin.Controllers" }
);
routes.remove(route); //remove your route from the RouteTable.Routes
routes.insert(0, route); //only to add it back again to the top of RouteTable.Routes, above all the routes that have been registered earlier
}
public int Priority
{
get
{
return 1;
}
}
This is to override Controller. Now to overriding View. Slight adjustment to the CustomViewEngine (Make sure your CustomViewEngine is in your plugin, not in Nop.Admin)
//Insert your custom View locations to the top of the list to be given a higher precedence
newLocations.Insert(0, "~/Plugins/MyPlugin/Views/Admin/{1}/{0}.cshtml");
newLocations.Insert(0, "~/Plugins/MyPlugin/Views/Admin/Shared/{0}.cshtml");
You can actually remove the constructor of CustomViewEngine. The constructor is not necessary if you have the two lines above in the GetPath
method.