+1-888-365-2779
Try Now
More in this section

Forums / Project Feather / Change where custom designer views are located.

Change where custom designer views are located.

10 posts, 0 answered
  1. Ryan
    Ryan avatar
    6 posts
    Registered:
    12 Apr 2016
    20 Apr
    Link to this post

    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

  2. Nikola Zagorchev
    Nikola Zagorchev avatar
    424 posts
    Registered:
    08 Dec 2016
    27 Apr
    Link to this post
    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
     
  3. Ryan
    Ryan avatar
    6 posts
    Registered:
    12 Apr 2016
    27 Apr in reply to Nikola Zagorchev
    Link to this post

    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?

     

  4. Ryan
    Ryan avatar
    6 posts
    Registered:
    12 Apr 2016
    27 Apr
    Link to this post

    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.

  5. Nikola Zagorchev
    Nikola Zagorchev avatar
    424 posts
    Registered:
    08 Dec 2016
    27 Apr
    Link to this post
    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
     
  6. Ryan
    Ryan avatar
    6 posts
    Registered:
    12 Apr 2016
    27 Apr
    Link to this post

    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): http://localhost:53008/Telerik.Sitefinity.Frontend/Designer/Master/Navigation?package=BusinessName&controlId=532bcbd9-908f-6451-9e80-ff00000c1994

    (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.

     

  7. Nikola Zagorchev
    Nikola Zagorchev avatar
    424 posts
    Registered:
    08 Dec 2016
    28 Apr
    Link to this post
    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
     
  8. Nikola Zagorchev
    Nikola Zagorchev avatar
    424 posts
    Registered:
    08 Dec 2016
    29 Apr
    Link to this post
    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
     
  9. Ryan
    Ryan avatar
    6 posts
    Registered:
    12 Apr 2016
    29 Apr
    Link to this post
    Thank you!
  10. Ryan
    Ryan avatar
    6 posts
    Registered:
    12 Apr 2016
    29 Apr
    Link to this post

    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.

10 posts, 0 answered