ASP.NET MVC3 Physical Location of View from controller

asp.net-mvc-3, filepath, view

Solution

The proper way to the get physical location of a view is to map its virtual path. The virtual path can be retrieved from the `ViewPath` property of `BuildManagerCompiledView` (`RazorView` derive from that class, and your `IView` instances will therefore typically have that property).

Here is an extension method that you can use:

public static class PhysicalViewPathExtension
{
    public static string GetPhysicalViewPath(this ControllerBase controller, string viewName = null)
    {
        if (controller == null)
        {
            throw new ArgumentNullException("controller");
        }

        ControllerContext context = controller.ControllerContext;

        if (string.IsNullOrEmpty(viewName))
        {
            viewName = context.RouteData.GetRequiredString("action");
        }

        var result = ViewEngines.Engines.FindView(context, viewName, null);
        BuildManagerCompiledView compiledView = result.View as BuildManagerCompiledView;

        if (compiledView != null)
        {
            string virtualPath = compiledView.ViewPath;
            return context.HttpContext.Server.MapPath(virtualPath);
        }
        else
        {
            return null;
        }
    }
}

Use it something like this:

public ActionResult Index()
{
    string physicalPath = this.GetPhysicalViewPath();
    ViewData["PhysicalPath"] = physicalPath;
    return View();
}

or:

public ActionResult MyAction()
{
    string physicalPath = this.GetPhysicalViewPath("MyView");
    ViewData["PhysicalPath"] = physicalPath;
    return View("MyView");
}

Problem

What is the proper way to get the physical location of the View that will be served by a MVC action from inside the action? I need the last modified time of the file for sending response headers.

Original source

Related problems