如何实现自定义RazorViewEngine来查找非标准位置的视图

本文关键字:查找 非标准 位置 视图 RazorViewEngine 自定义 何实现 实现 | 更新日期: 2023-09-27 18:28:59

我正在考虑实现一个自定义RazorViewEngine。基本上,我有两个网站的代码库实际上是相同的。不同之处在于它们看起来不一样。我想覆盖标准视图引擎,使MVC在两个独立的位置上查看其视图、布局等。一个用于公司A,另一个用于B。公司A将包含主视图,而公司B的视图将覆盖这些主视图。因此,我希望视图引擎在位置B中查找视图、布局、主视图或局部视图,如果找到,则返回;如果找不到,则默认为公司a的视图作为默认视图。显然,A公司只会查看自己的文件夹。

问题的关键是:我找到了这个网站:http://www.aspnetwiki.com/mvc-3-razor:extending-视图引擎

第一个问题,这是实现这一目标的最佳方式吗?

第二,我需要重写CreatePartialCreateViewFindPartialFindView方法吗

更新

好的,我自己已经解决了第二个问题,我想覆盖的方法是CreateViewCreatePartialView,因为在这一点上,它已经构建了视图字符串,我可以摆弄它。

如何实现自定义RazorViewEngine来查找非标准位置的视图

好的,最后我选择了一种方法,详细介绍如下:http://weblogs.asp.net/imranbaloch/archive/2011/06/27/view-engine-with-dynamic-view-location.aspx

感谢@Adriano的回答和指点,但最终我认为这种方法更符合我的需求。下面的方法允许我保留标准功能,但可以创建一个新的更高优先级的视图位置进行搜索。

public class Travel2ViewEngine : RazorViewEngine
{
    protected BrandNameEnum BrandName;
    private string[] _newAreaViewLocations = new string[] {
        "~/Areas/{2}/%1Views/{1}/{0}.cshtml",
        "~/Areas/{2}/%1Views/{1}/{0}.vbhtml",
        "~/Areas/{2}/%1Views//Shared/{0}.cshtml",
        "~/Areas/{2}/%1Views//Shared/{0}.vbhtml"
    };
    private string[] _newAreaMasterLocations = new string[] {
        "~/Areas/{2}/%1Views/{1}/{0}.cshtml",
        "~/Areas/{2}/%1Views/{1}/{0}.vbhtml",
        "~/Areas/{2}/%1Views/Shared/{0}.cshtml",
        "~/Areas/{2}/%1Views/Shared/{0}.vbhtml"
    };
    private string[] _newAreaPartialViewLocations = new string[] {
        "~/Areas/{2}/%1Views/{1}/{0}.cshtml",
        "~/Areas/{2}/%1Views/{1}/{0}.vbhtml",
        "~/Areas/{2}/%1Views/Shared/{0}.cshtml",
        "~/Areas/{2}/%1Views/Shared/{0}.vbhtml"
    };
    private string[] _newViewLocations = new string[] {
        "~/%1Views/{1}/{0}.cshtml",
        "~/%1Views/{1}/{0}.vbhtml",
        "~/%1Views/Shared/{0}.cshtml",
        "~/%1Views/Shared/{0}.vbhtml"
    };
    private string[] _newMasterLocations = new string[] {
        "~/%1Views/{1}/{0}.cshtml",
        "~/%1Views/{1}/{0}.vbhtml",
        "~/%1Views/Shared/{0}.cshtml",
        "~/%1Views/Shared/{0}.vbhtml"
    };
    private string[] _newPartialViewLocations = new string[] {
        "~/%1Views/{1}/{0}.cshtml",
        "~/%1Views/{1}/{0}.vbhtml",
        "~/%1Views/Shared/{0}.cshtml",
        "~/%1Views/Shared/{0}.vbhtml"
    };
    public Travel2ViewEngine()
        : base()
    {
        Enum.TryParse<BrandNameEnum>(Travel2.WebUI.Properties.Settings.Default.BrandName, out BrandName);
        AreaViewLocationFormats = AppendLocationFormats(_newAreaViewLocations, AreaViewLocationFormats);
        AreaMasterLocationFormats = AppendLocationFormats(_newAreaMasterLocations, AreaMasterLocationFormats);
        AreaPartialViewLocationFormats = AppendLocationFormats(_newAreaPartialViewLocations, AreaPartialViewLocationFormats);
        ViewLocationFormats = AppendLocationFormats(_newViewLocations, ViewLocationFormats);
        MasterLocationFormats = AppendLocationFormats(_newMasterLocations, MasterLocationFormats);
        PartialViewLocationFormats = AppendLocationFormats(_newPartialViewLocations, PartialViewLocationFormats);
    }
    private string[] AppendLocationFormats(string[] newLocations, string[] defaultLocations)
    {
        List<string> viewLocations = new List<string>();
        viewLocations.AddRange(newLocations);
        viewLocations.AddRange(defaultLocations);
        return viewLocations.ToArray();
    }
    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
    {
        return base.CreateView(controllerContext, viewPath.Replace("%1", BrandName.ToString()), masterPath);
    }
    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
    {
        return base.CreatePartialView(controllerContext, partialPath.Replace("%1", BrandName.ToString()));
    }
    protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
    {
        return base.FileExists(controllerContext, virtualPath.Replace("%1", BrandName.ToString()));
    }
}

然后在Gloabal.asax 中注册

protected void Application_Start(object sender, EventArgs e)
{
    RegisterRoutes(RouteTable.Routes);

    //Register our customer view engine to control T2 and TBag views and over ridding
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new Travel2ViewEngine());
}

是的,就是这样,但您不需要重写这些方法。RazorViewEngine继承自VirtualPathProviderViewEngine,因此您可以使用其属性来设置视图的位置。

例如,请阅读创建您的第一个MVC视图引擎和如何在MVC中设置默认路由(到区域)。

以下是我的答案:将此添加到您的global.ascx

        ViewEngines.Engines.Clear();
        var customEngine = new RazorViewEngine();
        customEngine.PartialViewLocationFormats = new string[]
        {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Partial/{0}.cshtml",
            "~/Views/Partial/{1}/{0}.cshtml"
        };

        customEngine.ViewLocationFormats = new string[]
        {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Controller/{1}/{0}.cshtml"
        };
        customEngine.MasterLocationFormats = new string[]
        {
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Layout/{0}.cshtml"
        };
        ViewEngines.Engines.Add(customEngine);

这些文件夹是剃刀检查你的看法。

让我知道这是否有效。