【问题标题】:Find MVC template view by name按名称查找 MVC 模板视图
【发布时间】:2013-04-26 19:02:47
【问题描述】:

我正在编写一个HtmlHelper 扩展,我需要按名称搜索模板是否存在。有问题的模板可能是显示或编辑器模板,具体取决于上下文。我最初的想法是使用ViewEngines.Engines.FindPartialView 方法。但是,这种方法似乎没有搜索~/Views/Shared/DisplayTemplates~/Views/Shared/EditorTemplates 目录。
我想这是有充分理由的。毕竟,ViewEngine 怎么知道在没有额外的上下文信息的情况下返回显示模板还是编辑器模板?

所以,这就引出了一个问题:我如何搜索特定的 EditorTemplate/DisplayTemplate 我已经考虑将自定义视图引擎添加到 ViewEngines 集合包括这些位置。但是,我担心这可能会有问题。

我的主要担心是 DisplayTemplate/EditorTemplate 视图可能会出现意外情况。有其他人认为这是一个问题吗?
在必要时新建一个特定的DisplayTemplateViewEngine/EditorTemplateViewEngine 实例并保持ViewEngines 集合不包含此特定功能是否更好?
我还缺少什么吗?

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    WebFormViewEngine 具有一些属性,用于定义(模式)位置以搜索视图。

    您要么遵循所使用的视图引擎的约定,要么使用自定义视图路径创建自定义视图引擎(例如扩展 Razor)。

    后者解释here

    public class CustomViewEngine : RazorViewEngine
    {
        public CustomViewEngine()
        {
            var viewLocations =  new[] {  
                "~/Views/{1}/{0}.cshtml",  
                "~/Views/Shared/{0}.cshtml",  
                "~/Views/Shared/DisplayTemplates/{0}.cshtml",  
                "~/Views/Shared/DisplayTemplates/{1}/{0}.cshtml",
                // etc
            };
    
            this.PartialViewLocationFormats = viewLocations;
            this.ViewLocationFormats = viewLocations;
        }
    }
    

    所以我猜你应该在你的助手中查找当前视图引擎并查找其视图位置路径并按顺序搜索它们。 Html 帮助器没有获取当前正在运行的视图的方法或属性吗?

    【讨论】:

    • 感谢您的回复。我实际上并没有打破常规。我的结构符合预期的 MVC 架构定义。问题是 ViewEnginesCollection 的 FindPartialView 方法不会搜索这些位置,因为它不知道您是想要显示版本还是编辑器版本。不过,我确实找到了解决方案。请参阅我的答案以供参考。再次感谢。
    • 1) 您示例中的代码是默认的 Razor 行为吗? 2){0}{1}指的是什么?
    • @Shimmy this is the default。替换值为{0} = 视图名称、{1} = 控制器名称和{2} = 区域名称(参见ViewLocation and AreaAwareViewLocation at the bottom of this file)。
    • 那么如何使用另一个控制器视图的 EditorTemplates 文件夹下的视图?
    • @Shimmy 问一个新问题。
    【解决方案2】:

    为什么你只映射相对路径

    string path = Server.MapPath("~/View/");
    

    然后根据该特定目录中的.cshtml 退出检查文件是否退出

    string fileName = "MyView.cshtml";
    if (File.Exists(path + fileName))
        //do somethings
    else
        //do another things
    

    【讨论】:

    • 使用 ViewEngine 的一个好处是它可以被模拟,使其可测试。这个解决方案真的很难进行单元测试。不过,很高兴您的意见!
    【解决方案3】:

    我非常喜欢 MVC 框架是开源的!我能够从 TemplateHelpers 类(MVC 运行时内部)确定在呈现模板时考虑了 DataBoundControlMode。答案很简单!我所要做的就是在模板名称前加上适当的模板导向器。所以,找一个展示模板:

    var metadata = ModelMetadata.FromLambdaExpression(expression, HtmlHelper.ViewData);
    ViewEngines.Engines.FindPartialView(
        _controllerContext, 
        string.Format("DisplayTemplates/{0}", metadata.TemplateHint))
    

    不需要额外的视图引擎或路由!如果您对该应用程序感兴趣,我的助手将为给定模型自动生成 UI 组件。我想让自定义模板的存在绕过自动渲染。

    【讨论】:

    • 这就是答案。但是我不能在几天内将其标记为这样。很抱歉,如果您因为它明显的“未答复”状态而被吸引到这篇文章。
    • 什么是 metadata.TemplateHint 或者它来自哪里?
    • @xr280xr:已更新以包含元数据定义。希望能为您服务!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多