ASP.NET MVC Tip #24 – Retrieve Views from Different Folders

In this tip, I demonstrate how you can retrieve a view from any folder in an ASP.NET MVC application. I show you how to use both specific paths and relative paths.

Until today, I thought that a controller action could return a view from only one of two places:

· Views\controller name

· Views\Shared

For example, if you are working with the ProductController, then I believed that you could only return a view from either the Views\Product folder or the Views\Shared folder. When looking through the source code for the ViewLocator class, I discovered that I was wrong. If you supply a “Specific Path” for a view, you can retrieve a view from any location in an ASP.NET MVC application.

The ProductController.Index() action in Listing 1 returns a view from the specific path ~\Confusing\ButWorks.aspx.

Listing 1 – ProductController.vb (VB.NET)

Public Class ProductController
    Inherits Controller

      Public Function Index() As ActionResult
       Return View("~\Confusing\ButWorks.aspx")
      End Function
End Class

Listing 1 – ProductController.cs (C#)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Tip24.Controllers
{
    public class ProductController : Controller
    {
        public ActionResult Index()
        {
            return View( @"~\Confusing\ButWorks.aspx");
        }
    }
}

A specific path is a path that starts with either the character ~ or /. Any other path gets treated differently.

You also can use relative paths such as SubProduct\Details or SubProduct/Details. Either relative path will return a view located at Views\Product\SubProduct\Details.aspx. Listing 2 contains a complete code listing that illustrates using relative paths.

Listing 2 – ProductController.vb (VB.NET)

Public Class ProductController
    Inherits Controller

      Public Function Index() As ActionResult
       Return View("SubProduct\Details")
      End Function

End Class

Listing 2 – ProductController.cs (C#)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Tip24.Controllers
{
    public class ProductController : Controller
    {
        public ActionResult Index()
        {
            return View(@"SubProduct\Details");
        }

    }
}

Now, I want to be the first to warn you that you should never, never, never use this tip (Please delete this entry from your news aggregator immediately). There is a good reason for following the conventions inherent in an MVC application. Placing your files in known locations makes it easier for everyone to understand your application.

Discussion

  1. http:// says:

    Good tip. Agreed on the ‘never break this rule’ bit. Except I break it. My User, Products, etc controllers all, er, control their own Admin actions rather than making a different AdminUser, AdminProducts, etc controller, so I do sub-folder those views. So rather than having a index.aspx and an admin_index.aspx in the same folder. I have an index.aspx and an admin/index.aspx, and I use View(“admin/index”) in the admin_index() action. Breaking the rules? Sure, a little, but it’s still crystal clear.

  2. Scordi says:

    Hi,

    yesterday I did a post on my Blog in german language to show how to implement a custom viewlocator which only defines another target folder for the views. In my example its ‘/MVC/Views’.

    Maybe you want to complete your blog post by mentioning this approach.

    Here is my blogpost:

    blog.dotnet-expert.de/…/…%c3%bcrASPNetMVC.aspx

    Greet,
    Jens

  3. Eric Hexter says:

    Thanks for stressing the convention. I think it is really important have this been an extreme case for drifting from the convention.

  4. Merritt says:

    I had to include ‘Views’ in the path to get this to work:

    @”~\Views\Confusing\ButWorks.aspx”

  5. http:// says:

    I landed on this post because I’m trying to do what Jens is doing – it would be nice to have a configurable root directory, rather than assuming the root of the web site.

    For example, I am trying to have the MVC run under an /admin/ directory, but nowhere else in the web site.

    Jens’ solution actually is pretty good! Thanks for the discussion!

  6. Hi..
    thanks for the tutorial..

  7. Jason Monroe says:

    @Stephen

    I know that I’m late to the party with MVC and I’m digging up a 9 month post.. but this one is relevant to something I was trying to solve :)

    I wanted to organize all of my “Admin” views into a ~/Views/Admin//.aspx scheme so that the root of my views folder wouldn’t be cluttered with folders of views that are not relevant to the bulk of the site, and once written are rarely if ever touched.

    My solution was to write a new base class for the administration controllers (inherited from controller) and building up the viewName from the base.

    I made a post about it here: http://www.clanmonroe.com/…/…iews-in-asp.net-mvc.aspx

    What’s prompted me to comment on your post (aside from a ) was your comment about “I want to be the first to warn you that you should never, never, never use this tip”.

    I would like to add this food for thought: “Part of being a good developer is following the rules… Part of being a great developer is knowing when to break them.”

  8. Coupon Codes says:

    “Part of being a good developer is following the rules… Part of being a great developer is knowing when to break them.”- That’s a great mantra! I found Jen’s solution to be just what I was looking for.

  9. Len Ocin says:

    Why do you write up advice and then put in a footnote (which nobody will ever read until too late) they should not follow your advice?

    Sh!t, you made me do it, and now I’m stuck on the POST implementation of a View controller, which you and your stupid advice never thought of.

  10. pc says:

    cheers that folder view looks alot better

  11. Gary Kellett says:

    I agree it is always better to “follow the rules”, but it is good to know when/how to break them.

    For example, in the application I am writing, I have seperated out a number of controllers into various sections – lets take “Sales” for example. I have a CustomersController, ProjectsController and SalesInvoicingController. It would seem logically incorrect to put all of these actions within the same controller.

    Now in the same pattern, I group my views under a “Sales” folder, so a subfolder for “Customers”, one for “Projects” and one for “SalesInvoicing”.

    Mvc should really pick these up as they match the name and hierarchy of the controllers exactly, but no – I have to break the rules to return a specific view for each action in the controller. I am sure there must be a better way than hard-coding in the view paths…….

  12. b24 I tried to mock a call to a Linq to SQL query, but I am struggling.

  13. into various sections – lets take “Sales” for example. I have a CustomersController, ProjectsController and SalesInvoicingController. It would seem logically incorrect to put all of these actions within the same controller.

  14. footnote (which nobody will ever read until too late) they should not follow your advice?

    Sh!t, you made me do it, and now I’m stuck on the POST implementation of a View controller, which you and your stupid advice never thought of.

  15. GED Online says:

    they should not follow your advice?

    Sh!t, you made me do it, and now I’m stuck on the POST implementation of a View controller

  16. hierarchy of the controllers exactly, but no – I have to break the rules to return a specific view for each action in the controller. I am sure there must be a better way than hard-coding in the view paths

  17. I have to break the rules to return a specific view for each action in the controller. I am sure there must be a better way than hard-coding in the view paths

  18. footnote (which nobody will ever read until too late) they should not follow your advice?

  19. cheers that folder view looks alot better

  20. Sharon says:

    Thanks! into various sections – lets take “Sales” for example. I have a CustomersController, ProjectsController and SalesInvoicingController. It would seem logically incorrect to put all of these actions within the same controller.discount codes | promotional codes are more important than ever to people trying to save money on their shopping online.Such as Asda Discount Codes | Tesco Voucher Codes | Argos Discount Codes | Comet Discount Codes all the UK retailers seem to be gearing up to offer us big discounts, offers and incentives to get on and shop. Diapers Coupon Codes|Newegg promo codes and Musicians Friend Coupon Codes and Kohls Coupon Codes and Sears Coupon Codes A minute or two online can save you big money.

  21. ggggg It looks like DataContextExtensions.cs line 45 of the Save method should pass the primaryKeyName through to Update.

  22. van leasing says:

    Its a good idea for making things much easier to understand by placing the files in the known locations.

  23. thank you for sharing such a beautiful articles, Keep it up4

  24. Nathanial says:

    Thanks for stressing the convention. I think it is really important have this been an extreme case for drifting from the convention.

    swingers clubs toronto |web design toronto |cheap toronto web hosting

  25. HD Video Converter says:

    As the users of HD Camcorders like Sony, Canon, Panasonic, this HD Video Converter is necessary to help us convert hd Video easily and quickly. The Converter for HD provides several practical editing functions to help you achieve ideal output effect. Trim function is to cut videos into clips which you can just convert and transfer to your player. Crop function helps you remove black bars around the movie. You could use Effect function to adjust video brightness, contrast, saturation and more parameters. More powerful and considerate functions are waiting for you to explore.Mac Video Converter l Rip Blu Ray l VOB Converter