bevacqua
bevacqua

Reputation: 48476

Map MVC View Route Values to physical path

Say I have a route value for a path that has a view, like

new
{
    controller = "Home",
    action = "Index"
}

How do I map this to ~/Views/Home/Index.cshtml?

I know not all views necessarily have an action, and that not all actions necessarily return a view, so that might prove to be an issue.

Update:

Maybe something like this:

IView view = ViewEngines.Engines.FindView(ControllerContext, "Index").View;
view.GetViewPath();

But that allows me to specify a controller instead of assuming I want to use my controllerContext (or maybe even mocking up a controllerContext for the Controller (string) I want..

Upvotes: 3

Views: 2102

Answers (2)

bevacqua
bevacqua

Reputation: 48476

Here's how I've done it:

private string GetPhysicalPath(string viewName, string controller)
{
    ControllerContext context = CloneControllerContext();

    if (!controller.NullOrEmpty())
    {
        context.RouteData.Values["controller"] = controller;
    }
    if (viewName.NullOrEmpty())
    {
        viewName = context.RouteData.GetActionString();
    }
    IView view = ViewEngines.Engines.FindView(viewName, context).View;
    string physicalPath = view.GetViewPath();
    return physicalPath;
}

and the extension method for GetViewPath is:

public static string GetViewPath(this IView view)
{
    BuildManagerCompiledView buildManagerCompiledView = view as BuildManagerCompiledView;
    if (buildManagerCompiledView == null)
    {
        return null;
    }
    else
    {
        return buildManagerCompiledView.ViewPath;
    }
}

and CloneControllerContext is:

private ControllerContext CloneControllerContext()
{
    ControllerContext context = new ControllerContext(Request.RequestContext, this);
    return context;
}

Upvotes: 2

Martin Booth
Martin Booth

Reputation: 8595

From RazorViewEngine.cs (in the mvc3 source), the search paths for views are as follows (assuming razor):

    ViewLocationFormats = new[] {
        "~/Views/{1}/{0}.cshtml",
        "~/Views/{1}/{0}.vbhtml",
        "~/Views/Shared/{0}.cshtml",
        "~/Views/Shared/{0}.vbhtml"
    };

{1} refers to the controller routevalue, and {0} is the view name (not part of the routevalues).

You can search these locations to try to find a view which matches your criteria but you also need to understand quite how many assumptions you are making...i.e. that the view has the same name as the action (by default yes, but not if you specify a view name in the call to View in the controller's action). You've mentioned a couple of other assumptions already

Upvotes: 1

Related Questions