Category Archives: Umbraco

Securing Backend Pages in MVC for Umbraco 4.11.1

Beginning of the year I posted an article on how you can create backend pages in the open source ASP.NET CMS Umbraco (http://blog.bartdemeyer.be/2013/01/using-mvc-backend-pages-in-umbraco-4-11-1). At the end of the post I published a little TODO list:

  • Block access to the backend controller for non authenticated users
  • Adapt the actions that you get in the Umbraco back end by right clicking
  • Due to a very busy work schedule I didn’t had the time to look into this list. In the mean while version 6 was released by the Umbraco core team.

    Last week I received the question if I had already found a solution for the first item on the todo list: blocking access to the backend controller for non authenticated users.

    Between the search for Easter eggs together with my son, backing pancakes and nothing interesting on the TV this evening I found the time to implement the feature.

    Reminder: the problem

    A small reminder of the problem we are facing. We’ve created a MVC controller to access from the Umbraco backend to perform our own business logic like shown in the image below.

    image

    We used the implementation if the Umbraco’s Surface  Controller that will create a MVC area. If we know the structure of the URL to this area – controller – action we can access the page without logging in the Umbraco backend.

    image

    This is off course a security risk we have to solve. We don’t want non authenticated users to be able to access our business logic.

    Using the Authorization attribute

    In ASP.NET MVC access to certain controllers or individual actions is managed by using the Authorization annotation attribute. You can use the default attribute where you are able to filter request based on specific users or specific user roles.

    But you can off course inherit from the default attribute and implement your own authorization attribute.

    Create the UmbracoAuthorizeAttribute

    In this post I’ll extend the project we’ve created during the previous post and that you can find on Github.

    Add a folder ‘Helpers’ in the UmbracoMVCDemo.BackEnd project. In that folder create a new class ‘UmbracoAuthorizeAttribute’. Add the public keyword to the class implementation and we shall inherit from the System.Web.MVC.AuthorizeAttribute.

    Implementing authorization

    Implementing your own authorization login can be done by overriding two methods from the base class: AuthorizeCore(HttpContextBase httpContext) and OnAuthorization(AuthorizationContext filterContext).

    In AuthorizeCore(HttpContextBase httpContext) we will connect to the Umbraco backend to check if the user is authenticated or not.

    I’ll first check if the httpContext contains any value, if not we’ll throw an exception. After that I’ll use a method from the Umbraco BasePage: ValidateUserContextID. This method will return true if the user is authenticated and false if not. With that result we’ll set a class variable we can use in the implementation of the OnAuthorization method.

    In this implementation we’ll first execute the base class implementation before we check the failedAuthentication class variable. If the authentication in the failedAuthentication failed we’ll send the user to the login page using the FormsAuthentication class.

    Adding authorization to our controller

    It’s not enough to create the attribute, we still have to tell our controller to use the authentications we’ve implemented. Open up the DemoAdminSurfaceController class we created in the previous post and add the UmbracoAuthorize attribute (line 4).

    Testing

    I’ve opened up another browser and accessed the same action again. (keep in mind that we make use of the default FormsAuthentication that will use a session cookie. Therefor will a new tab in the same browser not give the desired effect). Because we’re not authenticated we get redirected to the login page.

    image

    You’ll see the url we entered in the ReturnUrl parameter. If we now enter our credentials we’ll get redirected to the Umbraco back end. Although the ReturnUrl is filled out we’ll not be redirected to the correct page. We still have to click on our demo Section and demo node.

    Remark

    I’ve had to alter the default web.config file to be correctly redirected to the login page. I’m not sure this needs to be done if you have a fresh installation, I’ll add it here to avoid bad redirections.

    Source

    You can find the full source code from this post and the earlier posts on Github. Feel free to download, fork, comment, …

    The hard search for missing Extension methods in Umbraco 4.7.0

    Implementing SignalR

    For one of our company websites we got the question from HR to implement a chatbox on the website so interested candidates could contact them in an easy way. After comparing a few open source alternatives we decided to build our own using the just released SignalR framework.

    Everything worked fine on our development server where we’re running a backup of the production Umbraco website. Our dev team could easily create the chatbox and sooner as expected we had a working chatbox to present to HR.

    Moving changes to staging

    Like all our development projects we work in different steps. Development on the local machine or development server, client tests on the staging machine. This way we remove the risk that some developers test come in the way of our clients testing.

    For this implementation the client is our own HR department, still we follow the same development guidelines to avoid test data on the acceptance (staging) environment.

    Extension methods missing

    After copying all DLL’s and usercontrols to the staging environment we noticed that all of our Macros in Razor where failing. Suddenly the ‘umbraco.MacroEngines.DynamicNodeList‘ was missing the extension methods like ‘First’ and ‘FirstOrDefault’.

    image

    Start debugging

    First reaction was of course to delete all the DLL’s we’ve altered for this last release and to reinstate the old DLL’s. Still we faced the same problem.

    Back to start, we took a new backup from the production server and started the deploy again. There we noticed we overwritten a third party DLL ‘Newtonsoft.Json.dll’, a well known library for Json conversions created by James Newton-King. More information on his website.

    We skipped the replacement of the DLL and all of our Razor scripts we’re working like before. Problem solved (we thought).

    SignalR failed to work

    After the re-deploy of our chatbox DLL’s and usercontrols we couldn’t get the chatbox to work. It seemed the SignalR hub was missing to contact the server to register a chat user. A check with Firebug reveled the hub couldn’t be loaded because a DLL reference couldn’t find the correct version of the DLL. Of course the ‘Newtonsoft.Json.dll’ was playing up again.

    image

    Some more debugging

    No problem, we find out where Umbraco references the DLL and update it to the latest version and rebuild the Umbraco DLL and we’re good to go. Wrong, we checked the source of the 4.7.0 version that was available on codeplex but no sign of ‘Newtonsoft.Json.dll’.

    Then it had to be one of our own projects referencing the DLL? No, none of our own project had a reference to the ‘Newtonsoft.Json.dll’.

    I loaded the project on disk, configured it in IIS and attached the Visual Studio debugger. In the Debug menu –> windows –> Modules component I could find the ‘Newtonsoft.Json.dll’ reference but no way to find out witch component was responsible for loading the DLL.

    Some more (manual) debugging

    As I couldn’t find a way to find out who was responsible for loading the DLL I had only one option left.

    I took a look at the download at codeplex and removed all DLL’s that were not in the original download. Of course some other problems showed up as all custom created usercontrols failed to load but the Razor Extension methods worked and I could start a tedious process of adding DLL’s to the bin folder with my Visual Studio debugger attached and to reload the site every time.

    Found the problem

    When I copied the ‘Twitterizer2.dll’ back into the bin folder the Razor scripts failed again. I finally found the source of the problem. After a quick look at the Github repository of the Twitterizer project I found the Newtonsoft references and the different versions in the packages folder.

    Resolving the problem

    I did found the problem but we wanted to keep the Twitter possibilities that we had implemented before so we needed the Twitterizer2 DLL.I forked the project on Github and cloned the project locally.

    After updating the package to the latest version (the same our SignalR implementation was using) I’ve rebuilded the DLL and copied it to the Umbraco bin folder. Finally we had our Razor scripts working and our chatbox was responding!

     

    It took me half a day of debugging before I did found the problem. If anyone has a good way to find out witch component loads a certain DLL, let me know in the comments or by a tweet, …

    Using MVC backend pages in Umbraco 4.11.1

    Umbraco backend

    In a previous post we saw the use of your own MVC controllers in the Umbraco front end. The Umbraco community has made effort to document these possibilities on our.umbraco.org. The use of MVC in the back end of the Umbraco interface is not very well documented and it took me some analysis and debugging of the source code to find out how this could be implemented.

    Default you have 7 sections in the backend:

    • Content
    • Media
    • Settings
    • Developer
    • Users
    • Members
    • Translation (hidden by default for the admin user)

    These sections will do in a plain website where you don’t want to use custom code.

    One of my personal projects is to create a new website for the sport club where I’m already 15 years affiliated with. The current website is already 7 or 8 years old and was written in PHP. Needless to say that the look and feel is outdated, the PHP code I’ve written 8 years ago wasn’t the most beautiful piece of code I’ve created.
    I wanted to create a new website in ASP.NET MVC but I don’t want to put the effort in creating controllers and views for the administration part where a good CMS can fill up this gap.

    Because I’m already familiar with Umbraco it looked a good choice to combine the strength of Umbraco with custom development. But therefor I had to get custom MVC controllers working in the backend.

    New backend project

    This blog post goes further on the project created in the previous post. You can download the source at Github.

    In the existing solution we’ll add a new project by right clicking the solution and choose Add – New project.

    image

    Choose for a ASP.NET MVC 3 Web Application and give it a name (in this demo: UmbracoMVCDemo.BackEnd)

    image

    In the next window choose for Internet Application and the Razor view engine. We’ll need the core Umbraco libraries so open up the Package Manager Console and type ‘”Install-Package UmbracoCms.Core” and hit enter. Wait for the “Successfully added ‘UmbracoCms.Core 4.11.1’ to UmbracoMVCDemo.BackEnd.” message and we’re ready to go.

    Adding a new section

    First we’ll have to create a new section in the Umbraco backend. Open op your windows explorer and go to the root of the Umbraco installation. Open up the config folder and open up the applications.config file.

    <?xml version="1.0" encoding="utf-8"?>
    <applications>
      <add alias="content" name="Content" icon=".traycontent" sortOrder="0" />
      <add alias="media" name="Media" icon=".traymedia" sortOrder="1" />
      <add alias="settings" name="Settings" icon=".traysettings" sortOrder="2" />
      <add alias="developer" name="Developer" icon=".traydeveloper" sortOrder="3" />
      <add alias="users" name="Users" icon=".trayusers" sortOrder="4" />
      <add alias="member" name="Members" icon=".traymember" sortOrder="5" />
      <add alias="translation" name="Translation" icon=".traytranslation" sortOrder="6" />
    </applications>
    
    

    You’ll see the existing 7 sections configured in the config file. We’ll add a new one:

      <add alias="demo" name="Demo" icon="demo.gif" sortOrder="7" />
    

    We give the new application or section the alias ‘demo’ and the name ‘Demo’. For the icon we’ll add a new picture called ‘demo.gif‘ and set the sort order to 7. (The default images are showed using sprites where the icon name is actually the css class to define the background image. You can choose to alter the existing sprite and add a css class or select new picture). Create a new picture with your favorite image editor, name it ‘demo.gif’ and place it in the folder: [Umbraco root]/umbraco/images/tray/ folder.

    We’ll have to force the application pool to restart before Umbraco loads the new section. Open up the web.config file in the umbraco installation root and add a line break, save and refresh the page.

    Still the new section is not available in the backend because none of the users have access to this new section. Go to the users section, open up your user and add a check in the sections area next to the demo section. Refresh your page and you’ll see the new section appear.

    image

    When you click the Demo section at the bottom of the page we’ll see a new section opening up with an empty tree and the section name in square brackets.

    Adding a tree

    Next step will be to create the tree for our Demo section. This tree you can populate with data you choose. For this demo we’ll use some dummy data.

    In our backed project add a folder ‘Trees’ and add a new class named DemoTree. This class will have to inhered from the umbraco.cms.presentation.Trees.BaseTree class. This class has 3 abstract methods that we’ll need to implement.

    • RenderJS: the javascript that will run when a tree node is clicked
    • Render: the creation of tree nodes
    • CreateRootNode: to define the root node.

    We’ll also have to create a constructor that will receive a string that will forward to the base class.

    Last but not least we’ll have to decorate the class with the umbraco.businesslogic.TreeArrtibute where we define the application alias and title.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using umbraco.cms.presentation.Trees;
    
    namespace UmbracoMVCDemo.BackEnd.Trees
    {
    	[Tree("demo","demo","Demo")]
        public class DemoTree : umbraco.cms.presentation.Trees.BaseTree
        {
            public DemoTree(string application) : base(application)
            {
            }
    
            public override void RenderJS(ref StringBuilder Javascript)
            {
                throw new NotImplementedException();
            }
    
            public override void Render(ref XmlTree tree)
            {
                throw new NotImplementedException();
            }
    
            protected override void CreateRootNode(ref XmlTreeNode rootNode)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    Let’s start with defining the root node what is as simple as setting the NodeType and NodeId parameter.

    protected override void CreateRootNode(ref XmlTreeNode rootNode)
    {
    	rootNode.NodeType = "init" + TreeAlias;
    	rootNode.NodeID = "init";
    }
    

    Next we’ll implement the Render method and attach 2 nodes to the tree.

    public override void Render(ref XmlTree tree)
    {
    	XmlTreeNode xNode = XmlTreeNode.Create(this);
    	xNode.NodeID = "1";
    	xNode.Text = "Demo Node 1";
    	xNode.Action = "";
    	xNode.Icon = "folder.gif";
    	xNode.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	if (xNode != null)
    	{
    		tree.Add(xNode);
    		OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	}
    
    	XmlTreeNode xNode2 = XmlTreeNode.Create(this);
    	xNode2.NodeID = "2";
    	xNode2.Text = "Demo node 2";
    	xNode2.Action = "";
    	xNode2.Icon = "folder.gif";
    	xNode2.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	if (xNode2 != null)
    	{
    		tree.Add(xNode2);
    		OnAfterNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	}
    }
    

    In the RenderJS method remove the ‘throw new NotImplementedException” line and build the project. We’ll have to copy the UmbracoMVCDemo.BackEnd.dll from the bin folder to the Umbraco installation bin folder.

    Refresh the page and you’ll see two new node appear. Notice that the Demo root node isn’t surrounded by square brackets any more.

    image

    If you open up the trees.config file in the umbraco root – config folder you’ll see Umbraco automatically added the tree.

    For now the nodes don’t do much if you click on it because we left the Action attribute empty. Before we can add an action we need the editor for the right hand side.

    Adding an editor – controller and views

    Like I said before we want to create the editor in a MVC pattern instead of the default Webforms like was possible before. Therefor will create a new controller by right clicking the controllers folder in the backend project.

    image

    Name the controller DemoAdminController and choose for the empty controller template. Because we’ll already have a DemoController in the frontend application I named this one DemoAdmin to avoid confusion.

    The Controller will have to inhered from the Umbraco.Web.Mvc.SurfaceController before we can use it in the backend.

    IMPORTANT: Although the documentation of version 5 stated the controller didn’t need to be suffixed by ‘Surface’ I noticed there are constraints set on the PluginControllerResolver in the Umbraco source code. We can remove this constraint in the source code but the easiest way is to rename our controller to DemoAdminSurfaceController. This will change our URL’s but they won’t be visible in the Umbraco backend anyway.

    We have to decorate the class with the Umbraco.Web.Mvc.PluginController attribute. (yes, the plugincontroller attribute although we’re inheriting a SurfaceController). In this attribute we’ll have to enter the area name. Every plugin will be placed in his own MVC area to avoid duplicate views and controllers. We’ll set the area name to ‘demo’.

    Last but not least we’ll have to create two constructors. One without parameters, one that will take a Umbraco.Web.UmbracoContext instance and forward this to the base class.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Umbraco.Web;
    using Umbraco.Web.Mvc;
    
    namespace UmbracoMVCDemo.BackEnd.Controllers
    {
        [PluginController("Demo")]
        public class DemoAdminSurfaceController : SurfaceController
        {
    
            public DemoAdminSurfaceController()
            {
            }
    
            public DemoAdminSurfaceController(UmbracoContext umbracoContext)
                : base(umbracoContext)
            {
            }
    
            public ActionResult Index()
            {
                return View();
            }
        }
    }
    
    

    Last but not least we’ll have to create a view to back up the Index action on our controller that will for now will be one line:

    “<h1>Backend Demo Controller – view</h1>”

    Build the backend project and copy the dll to the Umbraco installation bin folder. Default will the view be searched in the following folder:

    [Umbraco ROOT]/App_Plugins/Demo/Views/DemoAdminSurface/. That is App_Plugins/[AreaName]/Views/[ControllerName]/. Create the folders and add the index view.

    I we go to the Umbraco backend we”’ll notice the 2 demo nodes still don’t do anything if we click them. We’ll first have to assign an action to these nodes.

    Assign an action to the nodes

    To assign an action to the nodes we’ll have to do two things. We’ll have to implement the RenderJS method in out Tree class and fill out the Action parameter from our nodes in the Render method.

    In the RenderJS method will render the necessary javascript that will open our editor in the right hand pane by using the ‘UmbClientMgr’ javascript object.

    public override void RenderJS(ref StringBuilder Javascript)
    {
    	Javascript.Append(
    	@"function openDemoController() {
    		UmbClientMgr.contentFrame('/Demo/DemoAdminSurface');
    	}");
    }
    

    In the Render method will add a call to the javascript action we just created (for now only on the first node).

    public override void Render(ref XmlTree tree)
    {
    	XmlTreeNode xNode = XmlTreeNode.Create(this);
    	xNode.NodeID = "1";
    	xNode.Text = "Demo Node 1";
    	xNode.Action = "javascript:openDemoController();";
    	xNode.Icon = "folder.gif";
    	xNode.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	if (xNode != null)
    	{
    		tree.Add(xNode);
    		OnAfterNodeRender(ref tree, ref xNode, EventArgs.Empty);
    	}
    
    	XmlTreeNode xNode2 = XmlTreeNode.Create(this);
    	xNode2.NodeID = "2";
    	xNode2.Text = "Demo node 2";
    	xNode2.Action = "";
    	xNode2.Icon = "folder.gif";
    	xNode2.OpenIcon = "folder_o.gif";
    	OnBeforeNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	if (xNode2 != null)
    	{
    		tree.Add(xNode2);
    		OnAfterNodeRender(ref tree, ref xNode2, EventArgs.Empty);
    	}
    }
    

    Build the project and copy the dll to the Umbraco installation bin folder and refresh the backend in the browser. If we now click the first test node we’ll see the test view appear in the right hand side frame.

    Automating the copy process

    Just like in the previous blog post you can use the build events to automate the copy process of DLL’s and views. Place the 2 xcopy commands in the post build event.

    xcopy $(TargetPath) $(SolutionDir)UmbracoMVCDemo\bin\ /C /Y
    xcopy $(ProjectDir)Views $(SolutionDir)UmbracoMVCDemo\App_Plugins\Demo\Views\ /E /Y

    Source code

    You can find the solution above on Github.

    To do’s

    There are still some things I need to resolve:

    • Block access to the backend controller for non authenticated users
    • Adapt the actions that you get in the Umbraco back end by right clicking
    • ….

    Using MVC frontend pages in Umbraco 4.11.1

    Umbraco CMS

    Umbraco had a rough year, is the least we can say . After working on version 5 from the bottom up for almost 2 years they decided beginning 2012 to stop the version 5 with reason. Although I understand the reasons I’m very glad I didn’t had put any effort yet in the V5.

    Umbraco is an Open Source ASP.NET Content Management System that gives the developer a lot of freedom without interfering with the generated HTML, CSS and javascript. It has a steep learning curve but when you start to find your way into it, it gives you a lot of freedom.

    At my company we used the 4.7 version to create the company websites (abc-groep.be). In that version we could only use Webforms user controls to incorporate our own business logic. As I’m a big fan of MVC this stopped me to use the CMS for personal projects. The V5 version was the big promise to use MVC in Umbraco (it was actually build on MVC). Lucky for me the Umbraco developers have taken into account that MVC is a big deal for developers and while the V5 was dead the V4 version branch was enriched with MVC.

    In this post we’ll look into how you can use your own MVC controllers and views to create front end pages in an Umbraco installation.

    Installing Umbraco in new web project

    Let’s startup Visual Studio and create a new blank web project. Give it a name (here I used UmbracoMVCDemo) and click create. You’ll see that VS only creates an empty project with just 1 file, the web.config.

    image

    image

    After creating the project we’ll add Umbraco by Nuget. Open the Package Console Manager and type “PM> Install-Package UmbracoCms” and hit enter. You’ll see the installation of a couple of dependencies passing by and you should see “Successfully added ‘UmbracoCms 4.11.1’ to UmbracoMVCDemo.”. If you hit F5 you’re browser should fire up  and show the installation page of your local Umbraco CMS.

    image

    Folow the instructions to create your database (MS SQL Server, MS SQL Express Edition, MYSQL and) Microsoft SQL CE 4 database. Choose an administrator user and choose to have no template installed. (if you want you can install these later on).

    After installation go to http://localhost:53998/umbraco/login.aspx (choose the correct port as configured in IIS Express or IIS). Log in with your just created administrator and you should see an empty website.

    image

    We then only have to specify we want to use MVC for our views. Open up the Umbraco.Settings.config file in the config folder under the root. Find and alter the next setting:

    <defaultRenderingEngine>MVC</defaultRenderingEngine>

    Adding new project

    We start by adding a new project in our solution with a right click on the solution and choose Add – New Project

    image

    Choose a new ASP.NET MVC 3 Web Application and give it a name (in this demo UmbracoMVCDemo.FrontEnd).

    image

    In the next dialog choose for an internet application with Razor as View engine. We will need to have the Umbraco core libraries that we can add with Nuget. Open up the Package manager Console and type “Install-Package UmbracoCms.Core”, hit enter and wait for the “Successfully added ‘UmbracoCms.Core 4.11.1’ to UmbracoMVCDemo.FrontEnd.” message.

    Create new controller

    Add a new controller by right clicking the controllers folder and choose for Add – New Controller. Name it DemoController and choose for the Empty controller template.

    The controller needs to inhered from the Umbraco.Web.Mvc.RenderMvcController controller instead of the default ASP.NET Controller class. Next to that we’ll have to override the default Index Action method. We need to add a view for the Index action and add some test text in the view.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Umbraco.Web.Models;
    
    namespace UmbracoMVCDemo.FrontEnd.Controllers
    {
        public class DemoController : Umbraco.Web.Mvc.RenderMvcController
        {
            //
            // GET: /Demo/
    
            public override ActionResult Index(RenderModel model)
            {
                //Do some stuff here, then return the base method
                return base.Index(model);
            }
    
        }
    }
    
    
    @{
        ViewBag.Title = "Index";
    }</pre>
    <h2>Index</h2>
    <pre>
    This is our own Demo controller and View.
    

    And that’s it, we’re ready to build. After building our Frontend project we’ll have to copy the generated UmbracoMVCDemo.FrontEnd.dll from the bin folder to the bin folder of our Umbraco installation. Next to the DLL we have to copy the Index.cshtml view from the views/Demo directory to the Umbraco installation views subfolder.

    Configuring Umbraco for our DemoController

    Umbraco uses a technique called ‘Hijacking routes’ to allow custom controllers. Basically will Umbraco for every Document Type check if he can find a controller that inhered the MVCRenderController and has the same name as the document type. If they can find a controller they will execute the overridden Index Action.

    Open up your Umbraco interface in a browser window and click on settings. Right click on Document Types and choose Create. Type Demo and uncheck “Create matching template”. That’s all configuration that has to be done.

    Go to the content section and right click on Content and choose Create. Select the Demo document type and name it Demo. After the entry is created click on the ‘save and publish’ button on top of the entry. Open up a  new browser tab and go to http://localhost:53998/Demo (change the port to the port in your IIS or IIS Express settings) and you’ll see our test text appearing.

    image

    Using own models, …

    At our.umbraco.org you’ll can find a lot of information on how to use your own custom models, bypass the Umbraco pipeline with your own routes, use templates to access different actions, ….

    Automate the copy process

    The copy action of the dll and your views can get a bit tedious after some time (in my case after the first time) but you can use after build events to automate this process. Open up the properties of the FrontEnd project and select the Buils events tab.

    In the Post-build event command line add:

    xcopy $(TargetPath) $(SolutionDir)UmbracoMVCDemo\bin\ /C /Y
    xcopy $(ProjectDir)Views  $(SolutionDir)UmbracoMVCDemo\Views\ /E /Y
    

    The views location

    We saw before that we had to copy the Index.cshtml view from our Frontend project to our Umbraco installation root – Views subfolder. Especially if you want to use multiple actions in a controller the Umbraco Views folder gets messy. I’m more a fan of a folder per controller with in there the views for that controller.

    That’s possible but there is a catch. The Umbraco engine checks if the view is present in the Views folder before allowing the request to use your controller. If the view is missing an empty page is returned. But if we add a Demo folder and add our index.cshtml view in there we’ll see that that view will be used before the view in the root views folder. (This seems to be intended and default ASP.NET MVC behavior)

    Therefor we only need a placeholder view in the basic views folder. This can be an empty view or just add a text that refers to the correct folder. And we can then create a Demo subfolder and add the correct views in that Demo folder.

    The post build action will also copy the views to the correct subfolder instead of the root views folder.

    Second part to be careful with is when creating multiple controllers there will be multiple Index.cshtml views what will give problems in the root views folder. I can strongly recommend creating a second action with an unique name so you can use templates with a unique name for every controller.

    Source

    You can find the demo project at Github.

    Next…

    In a next blog post we’ll look into using our own MVC controllers to create backend functionality.