1

I am attempting to develop a plugin our company needs for NOPCommerce.

I had some difficulty getting my controller and views to override the default ones and posted this SO question. From the kind assistance of the respondents I was able to get everything working. I went to work on another area of the code and when I came back it wasn't working completely.

I can get my controller to override and execute in all manner of configurations now that I understand the interactions with RouteProvider.cs.

My views however are not being hit...but they were as I had breakpoints and they were getting hit.

I know that MVC has a pattern / syntax expectation and that if you don't play within those bounds things don't work and I believe that is what is happening. My problem is I don't understand one of the rules of the game.

Here is the rundown as thoroughly as I can think of.

Plugin folder structure:

Project structure


Directory Output:

C:\ ...\Presentation\Nop.Web\Plugins\Payments.StoreCredit\Core\Views\Order


My controller...which is getting hit...and route provider entry:

var OverrideRoute = routes.MapRoute("Plugin....OrderOverride", "Admin/Order/Edit/{id}",
                 new { controller = "Order", action = "Edit" },
                 new { id = @"\d+" },
                 new[] { "Company.Plugin.Payments.StoreCredit.Core.Controllers" }
            );

            routes.Remove(OverrideRoute); //remove route 
            routes.Insert(0, OverrideRoute); //add it back to the top

public ActionResult Edit(int id)
{
  ....again just to be clear controller is being hit...
  return View(model);
}

CustomViewEngine:

protected override string GetPath(...parms) 
{
  ...
  //custom View locations to the top of the list to be given a higher precedence
  newLocations.Insert(0, "~/Plugin/Payments.StoreCredit/Views/Core/{1}/{0}.cshtml");
  ....
}

Some things I've noticed but can't piece together

If I set a breakpoint on the CustomViewEngine it only ever gets hit when I actually browse the list of plugins such as:

//localhost:53764/Admin/Plugin/List

I've tried NUMEROUS variations of the CustomViewEngine newlocation.Insert but I always have just six paths that are searched. I believe my newlocations are inserted but they are not "applicable" to this context so they don't get searched? I say this because if I rename the edit.cshtml in the core admin project just to see the paths searched I get:

The path used by edit in the controller:

localhost:53764/Admin/Order/Edit/1006

returns:

enter image description here

Finally if I specify a path in the controller edit such as:

return View("~/Plugins/Payments.StoreCredit/Core/Views/Order/edit.cshtml", model);

My view is used..but then what's the point of all that fuss with the CustomViewEngine?

In other words I can kludge it together specifying paths in controllers but the CustomViewEngine is the more robust and professional way to go.

Community
  • 1
  • 1
GPGVM
  • 5,515
  • 10
  • 56
  • 97

3 Answers3

0

Shouldn't this

newLocations.Insert(0, "~/Plugin/Payments.StoreCredit/Views/Core/{1}/{0}.cshtml");

be

newLocations.Insert(0, "~/Plugins/Payments.StoreCredit/Views/Core/{1}/{0}.cshtml");

Notice the typo in plugins

rivarolle
  • 1,528
  • 11
  • 18
  • Yes I see. I will try now but I'm thinking I have tried variations of plugin(s) – GPGVM Oct 10 '14 at 17:05
  • No go. The url returned by the edit in the controller is localhost:53764/Admin/Order/Edit/1006 and the same six paths as show in OP are what was searched. – GPGVM Oct 10 '14 at 17:07
0

Please, note that you have not added the Area = "Admin" parameter to your route. If you set a breakpoint in the GetPath method you will see that, without it, your new location is not being added at all.

All you need is to add Area = "Admin" to your route definition.

Marco Regueira
  • 1,045
  • 8
  • 17
0

As long as you've successfully overridden the Admin/Order/Edit/{id} route, there is no need to do anything special with the way the Controller inside the plugin loads the View.

Usually, the "widget" plugins use Views, as they are used to display bits of information in pages. So you can take a look at these plugins from the original NopCommerce code to see how they are implemented.

I took the widgets done by NopCommerce team by example and I have always been successful with loading plugin views by having them placed like this in the plugin's project tree:

Nop.Plugin.Widgets.FooBar
|- ...
|- Views
   |- WidgetsFooBar
      |- Configure.cshtml
      |- PublicInfo.cshtml

and call them in the controller like this:

return View("Nop.Plugin.Widgets.FooBar.Views.WidgetsFooBar.Configure", model);

Note that this call to the View method accepts a "viewName". This "viewName" is resolved by "[...]ViewEngine" classes from the Nop.Web.Framework.Themes namespace.

So as you can see there is no need to use CustomViewEngine.

Also note that your plugin's name starts with "Company.Plugin..." so you might need to change that in your code accordingly.

Dan Mirescu
  • 821
  • 8
  • 12