How to determine if a View exists in ASP.NET MVC 3?
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.
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());
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)
精彩评论