Change where custom designer views are located.

Posted by Community Admin on 05-Aug-2018 20:53

Change where custom designer views are located.

All Replies

Posted by Community Admin on 20-Apr-2016 00:00

Is there a way to change where custom designer views for widgets are located?

The default location is: 

~/Mvc/Views/[WidgetName]/DesignerView.[ViewName].[extension]

 

I would like to override that if possible. Has anyone done this before?

Here's the guide I'm referencing that specifies that requirement: http://docs.sitefinity.com/feather-create-custom-designer-views

Posted by Community Admin on 27-Apr-2016 00:00

Hello Ryan,

The designer view must start with DesignerView. by convention. However, it can be resolved from different locations. If you want to set a specific one not searched by the default ViewEngines, you need to register a custom one:
http://www.sitefinity.com/developer-network/knowledge-base/details/mvc-add-new-view-engine-to-sitefinity

Regards,
Nikola Zagorchev
Telerik

 
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
 

Posted by Community Admin on 27-Apr-2016 00:00

Hi Nikola,

Thanks for the link to that post. It was helpful. I was actually inheriting from RazorViewEngine to begin with, and it was good to see an example of inheriting from VirtualPathProviderViewEngine.

 

Unfortunately it is still not working, here's a link to my current code: http://pastebin.com/HiMjdquD

 

I do have my Application_Start calling "ViewEngines.Engines.Add(new WidgetFolderViewEngine());"

 

What's interesting is Sitefinity is picking up the main view that I dictate for the widgets, but not the designer views. It only picks up the designer views when they're under "~/Mvc/Views/1/DesignerView.0.cshtml, and not at my custom route. 

 

So is there a way to get the designer views picked up at a custom location? My current custom location is "~/Widgets/1/Views/0.cshtml".

 

I wonder if the view engine isn't picking up these designer views because it's confused by the extra dot in it's full name?

 

Posted by Community Admin on 27-Apr-2016 00:00

It does not seem that Sitefinity is using the VirtualPathProviderViewEngine for loading the DesignerViews. Here's some new code I wrote: http://pastebin.com/rSJKnJga

 

I put a breakpoint in every overridden method when trying to see the designer view for the widget, and a relevant view was not searched for or created by the ViewEngine.

Posted by Community Admin on 27-Apr-2016 00:00

Hello Ryan,

The ViewEngine implementation seems correct. You also state that it is finding the Controllers views fro the frontend, so the ViewEngine is working.
I will need some time to set it up and test with this view engine and will let you know my results.

Regards,
Nikola Zagorchev
Telerik

 
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
 

Posted by Community Admin on 27-Apr-2016 00:00

Hey Nikola,

 

I started really digging into the difference between the ways the designer views are called when changing the view locations, here's what I found:

(1) edit is clicked on the widget

(2) a call to the following URL is made (always the same URL despite where the designer views are): localhost:53008/.../Navigation

(3) Here's the interesting part, the response back from that URL differs with a directive used on the html that's returned. When I put my designer views where I want them to be this directive looks like this:

"<server-data default-view='PropertyGrid' widget-name='Navigation' control-id='532bcbd9-908f-6451-9e80-ff00000c1994' culture='en'></server-data>"

 

Whereas if I put the designer views where Sitefinity wants them, it looks like this:

"<server-data default-view='NavigationView' widget-name='Navigation' control-id='532bcbd9-908f-6451-9e80-ff00000c1994' culture='en'></server-data>"

"

 

So, whatever is setting the values of that directive in the responding html is what seems to dictate where my designer views are, or how it finds them? I hope this helps.

 

Posted by Community Admin on 28-Apr-2016 00:00

Hi Ryan,

It seems this is a limitation, as well.
The virtual paths that are resolved using the ViewEngines locations and the WidgetName for the Designer, always assume that the folder with the Views is under a Mvc folder.
Check the FrontendControllerFactory AppendDefaultPath method and the path transformations implementation.

I will follow up with a feature request on this.

However, if you really need to make the designer views from other locations, you can handle this in the custom ViewEngine. Iterating the folders inside the main one (~/Widgets) will do the trick to map the location for the widgets controllers.
Sample code:

public class WidgetFolderViewEngine : VirtualPathProviderViewEngine
    
        /// <summary>
        ///  Initializes a new instance of the <see cref="WidgetFolderViewEngine"/> class.
        /// </summary>
        public WidgetFolderViewEngine()
        
            string[] widgetFolderFormats = new[]
            
                 // 1 Widget name 0 View name
                "~/Widgets/1/0.cshtml",
                // For embedded views use Frontend virtual path following the assembly name
                "~/Frontend-Assembly/SitefinityWebApp/Widgets/1/0.cshtml"
            ;
 
            try
            
                var dirs = Directory.GetDirectories(System.Web.HttpContext.Current.Server.MapPath("~/Widgets/"));
                foreach (var dir in dirs)
                
                    var folderName = Path.GetFileName(dir);
                    this.EnhanceLocationsUsingWidgetFolderName(folderName, ref widgetFolderFormats);
                
            
            catch (System.Exception ex)
            
                // log ex or handle it differently
            
 
            this.FileExtensions = new string[] "cshtml" ;
            this.AreaViewLocationFormats = widgetFolderFormats;
            this.AreaMasterLocationFormats = widgetFolderFormats;
            this.AreaPartialViewLocationFormats = widgetFolderFormats;
            this.ViewLocationFormats = widgetFolderFormats;
            this.MasterLocationFormats = widgetFolderFormats;
            this.PartialViewLocationFormats = widgetFolderFormats;
 
            this.ViewLocationFormats = widgetFolderFormats;
        
...

private void EnhanceLocationsUsingWidgetFolderName(string widgetForlderName, ref string[] folderFormats)
    if (!string.IsNullOrEmpty(widgetForlderName))
    
        var widgetNameFormats = new string[folderFormats.Length];
        for (int i = 0; i < folderFormats.Length; i++)
        
            string format = folderFormats[i];
            format = format.Replace("1", widgetForlderName);
            widgetNameFormats[i] = format;
        
 
        folderFormats = widgetNameFormats.Concat(folderFormats).Distinct().ToArray();
    

Hope this helps.

Regards,
Nikola Zagorchev
Telerik
 
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
 

Posted by Community Admin on 29-Apr-2016 00:00

Hi Ryan,

Here is the feature request in our portal:
http://feedback.telerik.com/Project/153/Feedback/Details/190523-feather-ability-to-modify-designer-views-conventions

You can vote to increase its popularity.
Use the workaround provided in the meantime.

Regards,
Nikola Zagorchev
Telerik

 
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
 

Posted by Community Admin on 29-Apr-2016 00:00

Thank you!

Posted by Community Admin on 29-Apr-2016 00:00

Hey Nikola, while that workaround works great for the designer views, is there any way to tell sitefinity where to pick up the corresponding javascript files for that designer view?

Say I have a designer view located at "~Widgets/Navigation/Views/DesignerView.Simple.cshtml", I would like to have a script for that located at "~/Widgets/Navigation/Scripts/designerview-simple.js".

Thanks in advance.

Posted by mavickers on 23-Oct-2019 13:05

This is an ancient post but I was looking for the same answer to the last question (relocating the script) myself.

I found a way to do it but it isn't pretty - embed the script in your project then change its logical name by editing the project file.

For instance, in your example you would have your designerview-simple.js file located under /Widgets/Navigation/Scripts/designerview-simple.js. In Visual Studio right click on the script file and select Properties. On the Properties tab change Build Action to Embedded Resource.

After doing that save the project. Then, right click on the project in the solution tab and select Unload Project. After the project unloads right click on the unloaded project and select Edit <name of your project file>.

When the editor appears do a search for your designer view script file. It should look something like this:

<EmbeddedResource Include="Widgets\Navigation\Scripts\designerview-simple.js" />

Edit this markup so that it looks like this:

<EmbeddedResource Include="Widgets\Navigation\Scripts\designerview-simple.js">
    <LogicalName><name of your assembly>.Mvc.Scripts.Navigation.designerview-simple.js</LogicalName>
</EmbeddedResource>

Save the project file then close the editor window. In the solution explorer, right click the project and select Reload Project.

What these steps do is a) embed the script into the project dll and b) moves the resource location for the script to a place in the assembly where Sitefinity looks. You can edit the project file in a different editor instead of going through these steps in Visual Studio. After editing the project file in another editor Visual Studio will prompt you to reload the project, which you should. Further, we are editing the project file in this manner because the properties tab for a file in the solution unfortunately does not allow us to edit the LogicalName property.

When loading the designer Sitefinity looks for your corresponding designerview-simple script in /Mvc/Scripts/<your module>/. I believe it looks for it both in the file system and in the assembly. If it is found a call is made to /Frontend-Assembly/<your assembly name>/Mvc/Scripts/<your module>/designerview-simple.js. I believe the call to /Frontend-Assembly figures out where the script resides and serves it accordingly.

This is a slightly messy solution but keeps the solution tidy.

This thread is closed