logo
Welcome to our new AbleCommerce forums. As a guest, you may view the information here. To post to this forum, you must have a registered account with us, either as a new user evaluating AbleCommerce or an existing user of the application. For all questions related to the older version of Gold and earlier, please go to AbleCommerce Gold forum. Please use your AbleCommerce username and password to Login. New Registrations are disabled.

Notification

Icon
Error

Options
Go to last post Go to first unread
Joe Payne2  
#1 Posted : Wednesday, March 31, 2021 7:30:15 AM(UTC)
Joe Payne2

Rank: Advanced Member

Groups: HelpDesk, Developers
Joined: 11/9/2018(UTC)
Posts: 564

Thanks: 122 times
Was thanked: 26 time(s) in 25 post(s)
I've got a bunch of new views for various customizations. I'd like to isolate them in a /Areas/Admin/Views/Custom/ folder. But MVC won't find them there. Is there a file I can modify that will add that folder to the search path for views?

Wanna join the discussion?! Login to your AbleCommerce Forums forum account. New Registrations are disabled.

sweeperqb  
#2 Posted : Wednesday, March 31, 2021 10:19:01 AM(UTC)
sweeperqb

Rank: Advanced Member

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 125

Thanks: 14 times
Was thanked: 3 time(s) in 3 post(s)
Joe, would adding something like this to the Application_Start method in Global.asax be feasible for you?

Locate the following chunk of code:

Code:

    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new ThemeableRazorViewEngine());
    ViewEngines.Engines.Add(new RazorViewEngine());


That bit of code registers the view paths. You would either need to create your own custom razor view engine and register it before the ThemeableRazorViewEngine, or you can hijack one of them and inject your custom view paths by overwriting their format arrays. The code below does exactly that.

Code:
/***********************************************************************************/
            var razorEngine = ViewEngines.Engines.OfType<ThemeableRazorViewEngine>().FirstOrDefault();
            if (razorEngine != null)
            {
                // Add Custom folder to the default location scheme for STANDARD Views
                razorEngine.AreaMasterLocationFormats =
                    new string[]
                    {
                        "~/Areas/{2}/Views/Custom/{1}/{0}.cshtml"
                        // add other folders here (if any)
                    }.Concat(razorEngine.AreaMasterLocationFormats).ToArray();

                // Add Custom folder to the AREA default location scheme for STANDARD Views
                razorEngine.AreaViewLocationFormats =
                    new string[]
                    {
                        "~/Areas/{2}/Views/Custom/{1}/{0}.cshtml"
                        // add other folders here (if any)
                    }.Concat(razorEngine.AreaViewLocationFormats).ToArray();

                // Add Custom folder to the AREA default location scheme for PARTIAL Views
                razorEngine.AreaPartialViewLocationFormats =
                    new string[]
                    {
                        "~/Areas/{2}/Views/Custom/{1}/{0}.cshtml"
                        // add other folders here (if any)
                    }.Concat(razorEngine.AreaPartialViewLocationFormats).ToArray();

                // Add Custom folder to the default location scheme for STANDARD Views
                razorEngine.MasterLocationFormats =
                    new string[]
                    {
                        "~/Views/Custom/{1}/{0}.cshtml"
                        // add other folders here (if any)
                    }.Concat(razorEngine.MasterLocationFormats).ToArray();

                // Add Custom folder to the default location scheme for STANDARD Views
                razorEngine.ViewLocationFormats =
                    new string[]
                    {
                        "~/Views/Custom/{1}/{0}.cshtml"
                        // add other folders here (if any)
                    }.Concat(razorEngine.ViewLocationFormats).ToArray();

                // Add Custom folder to the default location scheme for PARTIAL Views
                razorEngine.PartialViewLocationFormats =
                    new string[] {
                        "~/Views/Custom/{1}/{0}.cshtml"
                        // add other folders here (if any)
                    }.Concat(razorEngine.PartialViewLocationFormats).ToArray();
            }
            /***********************************************************************************/


NOTE: This code should be added after the the code in the first block.

I chose to hijack the ThemeableRazorViewEngine because it is registered first so it's rules are processed before the RazorViewEngine.

I should mention that I assumed all of your custom views wouldn't be sitting directly in the Custom folder, but sub-folders. For example, if you were overriding the /Areas/Admin/Help/About view, I assumed your custom path would be /Areas/Admin/Views/Custom/Help/About.cshtml. If you prefer for it to be /Areas/Admin/Views/Custom/About.cshtml, you would have to remove the /{1} part from the custom paths. Also, some people prefer to put their Partial views in a /Shared folder; I didn't do that in the example.

Joe Payne2  
#3 Posted : Thursday, April 1, 2021 8:30:50 AM(UTC)
Joe Payne2

Rank: Advanced Member

Groups: HelpDesk, Developers
Joined: 11/9/2018(UTC)
Posts: 564

Thanks: 122 times
Was thanked: 26 time(s) in 25 post(s)
Hey I really appreciate the detailed reply. I found an easier solution after I posted my question. It's actually pretty simple now that I've researched it more.

First, just make a class that inherits RazorViewEngine and put in the /Code/ folder. In the custom view engine, add additional paths as shown below.

Code:

    public class CustomViewEngine : RazorViewEngine
    {
        public CustomViewEngine()
        {
            var viewLocations = new[] {
                "~/Areas/Admin/Views/Custom/{1}/{0}.cshtml",
                "~/Areas/Admin/Views/Shared/Custom/{0}.cshtml"
            };

            this.PartialViewLocationFormats = viewLocations;
            this.ViewLocationFormats = viewLocations;
        }
    }


Then register the custom view engine in global.asax immediately after the default razor engine is registered:

Code:

ViewEngines.Engines.Add(new CustomViewEngine());


What's really slick is when I modify an existing Able controller but create a new view. For instance, adding a new Dashboard partial view. Before this, I had to mix my custom views in the Able views found in the /Areas/Admin/Views/Dashboard/ folder.

Now I can create a Dashboard folder in /Areas/Admin/Views/Custom/ folder and MVC finds my custom views.

I hate mixing my files with Able files. The existing controllers are already a nightmare to work in because of how large they are. So I isolate everything I do in separate and better-organized file structures.
sweeperqb  
#4 Posted : Friday, April 2, 2021 10:54:19 AM(UTC)
sweeperqb

Rank: Advanced Member

Groups: Authorized User, Developers
Joined: 5/30/2020(UTC)
Posts: 125

Thanks: 14 times
Was thanked: 3 time(s) in 3 post(s)
Joe, have you tested and made sure everything shows the custom views? You mentioned registering your custom view engine "immediately after the default razor engine". The reason I ask is that MVC usually attempts to match on the rules in the order that they are registered. The only reason I can think of that yours may be winning is that you spelled out the /Admin area as part of the ViewLocationFormats, so it matches before the generic AreaViewLocationFormats rules are processed. If you end up having problems with your custom views not showing, be sure to try moving your custom view engine to the front of the list before you pull all your hair out :)
Joe Payne2  
#5 Posted : Friday, April 2, 2021 3:18:40 PM(UTC)
Joe Payne2

Rank: Advanced Member

Groups: HelpDesk, Developers
Joined: 11/9/2018(UTC)
Posts: 564

Thanks: 122 times
Was thanked: 26 time(s) in 25 post(s)
Seems to be working fine. I'm not replacing the default engine, just adding a second razor engine so far as I can tell. I've seen no issues with existing views, that'd be pretty obvious right away. And my custom views get picked up.

I've already moved everything. It's nice having my custom stuff organized away from the Able stuff. Makes it much quicker to find my controllers and views.

I'll update here if I come across any new issues related to it.
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.