我可以在ASP.NET MVC中指定"搜索视图"的自定义位置吗?

Dan*_*fer 103 asp.net-mvc views

我的mvc项目有以下布局:

  • /控制器
    • /演示
    • /演示/ DemoArea1Controller
    • /演示/ DemoArea2Controller
    • 等等...
  • /浏览次数
    • /演示
    • /Demo/DemoArea1/Index.aspx
    • /Demo/DemoArea2/Index.aspx

但是,当我有这个DemoArea1Controller:

public class DemoArea1Controller : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

我通过常用的搜索位置得到"视图'索引'或其主人找不到"错误.

如何在"Demo"视图子文件夹中指定"演示"命名空间中的控制器?

Sam*_*sel 120

您可以轻松扩展WebFormViewEngine以指定要查看的所有位置:

public class CustomViewEngine : WebFormViewEngine
{
    public CustomViewEngine()
    {
        var viewLocations =  new[] {  
            "~/Views/{1}/{0}.aspx",  
            "~/Views/{1}/{0}.ascx",  
            "~/Views/Shared/{0}.aspx",  
            "~/Views/Shared/{0}.ascx",  
            "~/AnotherPath/Views/{0}.ascx"
            // etc
        };

        this.PartialViewLocationFormats = viewLocations;
        this.ViewLocationFormats = viewLocations;
    }
}
Run Code Online (Sandbox Code Playgroud)

确保记住通过修改Global.asax.cs中的Application_Start方法来注册视图引擎

protected void Application_Start()
{
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new CustomViewEngine());
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我们跳过清除已经注册的引擎并只添加新引擎并且viewLocations只有新引擎,这不是更好吗? (5认同)
  • 没有ViewEngines.Engines.Clear()的实现; 一切正常.如果要使用*.cshtml,则必须从RazorViewEngine继承 (3认同)
  • 有什么方法可以将控制器中的“添加视图”和“转到视图”选项链接到新的视图位置?我正在使用 Visual Studio 2012 (2认同)

why*_*eee 43

现在在MVC 6中,您可以实现IViewLocationExpander接口而不会弄乱视图引擎:

public class MyViewLocationExpander : IViewLocationExpander
{
    public void PopulateValues(ViewLocationExpanderContext context) {}

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        return new[]
        {
            "/AnotherPath/Views/{1}/{0}.cshtml",
            "/AnotherPath/Views/Shared/{0}.cshtml"
        }; // add `.Union(viewLocations)` to add default locations
    }
}
Run Code Online (Sandbox Code Playgroud)

其中{0}是目标视图名称,{1}- 控制器名称和{2}- 区域名称.

您可以返回自己的位置列表,将其与default viewLocations(.Union(viewLocations))合并或只更改它们(viewLocations.Select(path => "/AnotherPath" + path)).

要在MVC中注册自定义视图位置扩展器,请ConfigureServicesStartup.cs文件中的方法中添加下一行:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.ViewLocationExpanders.Add(new MyViewLocationExpander());
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 我希望我可以投10票.正是Asp.net 5/MVC 6所需要的.美丽.当你想要将区域分组到更大的站点或逻辑分组的超级区域时,在我的情况下(和其他人)非常有用. (3认同)

Chr*_*s S 41

实际上,比将路径硬编码到构造函数中要容易得多.下面是扩展Razor引擎以添加新路径的示例.我不太确定的一件事是你在这里添加的路径是否会被缓存:

public class ExtendedRazorViewEngine : RazorViewEngine
{
    public void AddViewLocationFormat(string paths)
    {
        List<string> existingPaths = new List<string>(ViewLocationFormats);
        existingPaths.Add(paths);

        ViewLocationFormats = existingPaths.ToArray();
    }

    public void AddPartialViewLocationFormat(string paths)
    {
        List<string> existingPaths = new List<string>(PartialViewLocationFormats);
        existingPaths.Add(paths);

        PartialViewLocationFormats = existingPaths.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

还有你的Global.asax.cs

protected void Application_Start()
{
    ViewEngines.Engines.Clear();

    ExtendedRazorViewEngine engine = new ExtendedRazorViewEngine();
    engine.AddViewLocationFormat("~/MyThemes/{1}/{0}.cshtml");
    engine.AddViewLocationFormat("~/MyThemes/{1}/{0}.vbhtml");

    // Add a shared location too, as the lines above are controller specific
    engine.AddPartialViewLocationFormat("~/MyThemes/{0}.cshtml");
    engine.AddPartialViewLocationFormat("~/MyThemes/{0}.vbhtml");

    ViewEngines.Engines.Add(engine);

    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
}
Run Code Online (Sandbox Code Playgroud)

有一点需要注意:您的自定义位置将需要其根目录中的ViewStart.cshtml文件.


Mar*_*Zen 22

如果您只想添加新路径,可以添加到默认视图引擎并备用一些代码行:

ViewEngines.Engines.Clear();
var razorEngine = new RazorViewEngine();
razorEngine.MasterLocationFormats = razorEngine.MasterLocationFormats
      .Concat(new[] { 
          "~/custom/path/{0}.cshtml" 
      }).ToArray();

razorEngine.PartialViewLocationFormats = razorEngine.PartialViewLocationFormats
      .Concat(new[] { 
          "~/custom/path/{1}/{0}.cshtml",   // {1} = controller name
          "~/custom/path/Shared/{0}.cshtml" 
      }).ToArray();

ViewEngines.Engines.Add(razorEngine);
Run Code Online (Sandbox Code Playgroud)

这同样适用于 WebFormEngine

  • 对于视图:使用razorEngine.ViewLocationFormats. (2认同)

Sim*_*les 13

您可以直接更改现有的RazorViewEngine的PartialViewLocationFormats属性,而不是对RazorViewEngine进行子类化或直接替换它.此代码在Application_Start中:

System.Web.Mvc.RazorViewEngine rve = (RazorViewEngine)ViewEngines.Engines
  .Where(e=>e.GetType()==typeof(RazorViewEngine))
  .FirstOrDefault();

string[] additionalPartialViewLocations = new[] { 
  "~/Views/[YourCustomPathHere]"
};

if(rve!=null)
{
  rve.PartialViewLocationFormats = rve.PartialViewLocationFormats
    .Union( additionalPartialViewLocations )
    .ToArray();
}
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用,除了剃刀引擎类型是'FixedRazorViewEngine'而不是'RazorViewEngine'.如果找不到引擎,我也会抛出异常,因为它阻止我的应用程序成功初始化. (2认同)