4

I am implementing a new ASP.NET MVC 3 application that will use a form of dynamic routing to determine what view to return from a common controller action. I'd like have a default view that is displayed if there is no view at the dynamic location.

Think of it like navigating a tree structure. There is only one TreeController located in the root Controllers folder. It has a Browse action method that accepts the path of the node to browse. Each node can have a custom view so I need to first attempt to locate that view and return it from the action method, like this:

public ViewResult Browse(String path)
{
    var model = ...;

    return View(path, model);
}

So, if I navigate to "MySite/Tree/A/B/C" then I would expect to find a view at "\Views\Tree\A\B\C.aspx".

However, if there is not a custom view, I need to defer to a standard/default view (such as "\Views\Tree\Browse.aspx").

Since this is only the case for this action method, I don't believe that I should be handling NotFound errors that may result due to other circumstances. And, I'm not looking for dynamic routing as described in other posts because the path to the controller is fixed.

2 Answers 2

1

Controllers shouldn't know about physical views.

You do this by writing a custom view engine, e.g.:

public class MyViewEngine: WebFormViewEngine
{
    public MyViewEngine() 
    {
        ViewLocationFormats = ViewLocationFormats.Concat(
            new [] {"~/Views/{1}/Browse.aspx""}).ToArray();
        // similarly for AreaViewLocationFormats, etc., if needed
    }
}

See the source code for, e.g., WebFormViewEngine for details.

If you need to do this conditionally (for only a few action) then you can override FindView in that type and look at the route values.

Obviously, if you use Razor, then change that one instead.

Then, in Global.asax.cs, use it:

private void Application_Start(object sender, EventArgs e)
{
    // stuff
    ViewEngines.Engines.Add(new MyViewEngine());
Sign up to request clarification or add additional context in comments.

Comments

0

From within a Controller action this seems to work:

var fullPath = string.Format("~/Views/CustomStuff/{0}.cshtml", viewname);
var mappedPath = Server.MapPath(fullPath);
if( !System.IO.File.Exists(mappedPath) ) return View("Default");

else return View(viewname);

(note: not precompiling views)

1 Comment

If you really need to check if a view can be found, use ViewEngines.Engines.FindView() instead! Check this answer for an example: stackoverflow.com/a/947086/96175.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.