ASP.Net MVC 3显示模板和编辑模板自定义位置,如何?

Dev*_*nia 11 asp.net-mvc razor asp.net-mvc-3

我要使用Nuts,我正在使用MVCContrib,使用Portable Areas创建可插拔站点,到目前为止一切运行良好,除了当我开始使用MVC模板时,发生的事情是如果我将模板放在相应的文件夹中查看它的工作原理,例子

HostApplication/Views/Home/DisplayTemplates/FirstName.cshtml
HostApplication/Areas/PortableArea_Blog/Views/Home/DisplayTemplates/Auther.cshtml
Run Code Online (Sandbox Code Playgroud)

但我真正想要的是能够创建通用模板从主机应用程序或便携式区域设置和利用它,所以要做到这一点,我创建了一个新的便携式区域称为DisplayTemplates(利用MVCContrib能力编译视图),这里是便携式区域结构

DisplayTemplates
|-Views
  |-CommentTemplate.cshtml
Run Code Online (Sandbox Code Playgroud)

现在在我的主机应用程序中我创建了一个测试模型并添加了UIHint属性

public class HostModel
    {


        [UIHint("~/Areas/DisplayTemplates/Comment.cshtml")]
        public string Name { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

但它不起作用,所以我认为它与部分视图位置有关,所以我创建了一个CustomView引擎来查找该位置的部分视图并在Global.asax中注册它,这里有一个简短的想法,所以我不会厌烦你完整的代码

public class AreaViewEngine : RazorViewEngine
    {
        public AreaViewEngine()
        {

            // {0} = View name
            // {1} = Controller name

            // View locations
            ViewLocationFormats = new[]
                                      {
                                          "~/Areas/DisplayTemplates/{0}.cshtml"

                                      };

            PartialViewLocationFormats = ViewLocationFormats;

            AreaPartialViewLocationFormats = ViewLocationFormats;
        }

        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return new RazorView(controllerContext, partialPath, null, true, new[] { "cshtml" });
        }

        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            return new RazorView(controllerContext, viewPath, masterPath, true, new[] { "cshtml" });
        }




    }
Run Code Online (Sandbox Code Playgroud)

什么是更奇怪的是,似乎有明确的位置,以显示模板UIHint,不能正常工作,这里有一个例子

public class HostModel
    {
        //this works
        [UIHint("FirstName")]
        //this does not work
        [UIHint("~/Views/Home/DisplayTemplates/FirstName.cshtml")]
        public string Name { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

是的

FirstName.cshtml is in HostApplication/Views/Home/DisplayTemplates/FirstName.cshtml
Run Code Online (Sandbox Code Playgroud)

再次抱歉这篇长篇文章,但我放弃了寻找解决方案,所以任何帮助都会完全受到赞赏.

One*_*key 12

丹尼是对的.找到模板的方式与找到部分视图的方式相同.

默认情况下,WebFormViewEngine和RazorViewEngine将在以下位置搜索模板.

对于显示模板:

〜/ Views/{controller}/DisplayTemplates~/Views/Shared/DisplayTemplates

对于编辑器模板:

〜/ Views/{controller}/EditorTemplates~/Views/Shared/EditorTemplates

我认为子目录的名称(即"DisplayTemplates"和"EditorTemplates")在某处被硬编码到MVC中(我知道它是开源的,我可以找到它,但我不会去).

我认为更改位置的最简单方法是覆盖ViewEngine.我的自定义ViewEngine在这一点上非常复杂,但我怀疑你可以逃脱以下几点.

假设您希望模板位于〜/ Views/Templates中.

创建一个继承自您现在使用的视图引擎的类(可能是WebFormViewEngine或RazorViewEngine).添加一个空构造函数.它应该是这样的:

namespace MySite
{
    public class MySiteViewEngine : RazorViewEngine // <<-- or WebFormViewEngine
    {
         public MySiteViewEngine()
         {
             // We'll put some code here in a later step
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,将以下行添加到Global.asax.cs的Application_Start方法:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MySiteViewEngine());
Run Code Online (Sandbox Code Playgroud)

此时,编译并运行您的应用程序.一切都应该像现在一样运行.您基本上使用的是之前使用的相同视图引擎.

但现在,我们想要在查找PartialViews时添加搜索位置.这可以通过添加到PartialViewLocationFormats来完成.所以,现在在自定义视图引擎的构造函数中,您希望像这样添加到基类的数组:

base.PartialViewLocationFormats = new string[] {
    "~/Views/Templates/{0}.cshtml"
}.Union(base.PartialViewLocationFormats).ToArray<string>();
Run Code Online (Sandbox Code Playgroud)

关于上述内容的几点说明:

  • 上面的条目将使您的视图引擎在〜/ Views/Templates/DisplayTemplates/String.cshtml中查找String显示模板.
  • 这些视图引擎中的位置格式包括文件扩展名,因此如果你使用Razor/C#使用"cshtml",Razor/VB使用"vbhtml",WebForms会添加"aspx"和"ascx".
  • 我在上面的方式,我将我的位置格式添加到列表的顶部,但保留所有默认位置.您可以考虑删除它们.
  • 观察当前格式,您将看到您还将获得格式为{1}位置的控制器,因此如果您希望在每个控制器下都有一个Templates目录.
  • 小心,一旦你开始使用视图引擎移动它,就会让人上瘾.你可能会发现自己周围的一切.

祝好运.

  • 碰巧遇到了我在这篇文章中提到的硬编码值。它们位于 \mvc3\src\SystemWebMvc\Mvc\Html\TemplateHelpers.cs 中的 MVC 代码中。可能有一种方法可以覆盖 TemplateHelpers 类并重写 modeViewPaths 字典,但这可能比它的价值更多。仅重写字典仍然会将模板保留为 PartialViews 位置的子目录,而不会覆盖 ExecuteTemplate。 (2认同)

nul*_*ull 8

您可以在运行时轻松修改现有的ViewEngine,而不是创建新的ViewEngine:

private void FixMvcTemplateAreaBug(string areaName)
{
    foreach (BuildManagerViewEngine viewEngine in ViewEngines.Engines)
    {
        List<string> viewLocations = 
                     new List<string>(viewEngine.PartialViewLocationFormats);

        foreach (var extension in viewEngine.FileExtensions)
            viewLocations.Add("~/Areas/" + areaName + 
                              "/Views/Shared/{0}." + extension);

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

把上面放在适当的位置(如区域注册),你会没事的.