ASP.NET MVC3 Physical Location of View from contro

2019-05-05 08:10发布

问题:

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.

回答1:

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");
}


回答2:

That could work:

private DateTime? GetDate(string controller, string viewName)
{
    var context = new ControllerContext(Request.RequestContext, this);
    context.RouteData.Values["controller"] = controller;
    var view = ViewEngines.Engines.FindView(context, viewName, null).View as BuildManagerCompiledView;
    var path = view == null ? null : view.ViewPath;
    return path == null ? (DateTime?) null : System.IO.File.GetLastWriteTime(path);
}