C# 如何用插件中的视图文件覆盖nopcommerce视图文件?
我正在尝试覆盖位于以下位置的nopcommerce视图:C# 如何用插件中的视图文件覆盖nopcommerce视图文件?,c#,asp.net-mvc-4,nopcommerce,C#,Asp.net Mvc 4,Nopcommerce,我正在尝试覆盖位于以下位置的nopcommerce视图: Nop.Admin/Views/Category/Tree.cshtml 我在插件文件夹中开发了一个视图: Views/Misc/Tree.cshtml 我该怎么做呢?试试我写的这篇详细的文章:@wooncherk的自定义视图引擎在准备将来轻松覆盖视图方面非常出色。但是,在覆盖现有的核心视图方面,它有不足之处,因为nopCommerce将管理视图置于比自定义视图更高的优先级。这可以在Nop.Web.Framework.Themes
Nop.Admin/Views/Category/Tree.cshtml
我在插件文件夹中开发了一个视图:
Views/Misc/Tree.cshtml
我该怎么做呢?试试我写的这篇详细的文章:@wooncherk的自定义视图引擎在准备将来轻松覆盖视图方面非常出色。但是,在覆盖现有的核心视图方面,它有不足之处,因为nopCommerce将管理视图置于比自定义视图更高的优先级。这可以在Nop.Web.Framework.Themes.ThemeableVirtualPathProviderViewEngine.cs的虚拟方法
GetPath()
中看到。对于那些想知道的人来说,ThemeableVirtualPathProviderViewEngine
是由ThemeableRazorViewEngine
继承的类,而后者又由@WoonCheck的CustomViewEngine
类继承
正如箭头所指出的那样,参考上面的MeableVirtualPathProviderViewEngine
屏幕截图,这两行确认管理视图的优先级始终高于自定义视图
我成功地扩展了@wooncherk的自定义视图引擎方法,以便覆盖现有的管理核心视图。这涉及重写虚拟方法GetPath()
并将其复制到CustomViewEngine
类中。此时,删除两个罪魁祸首行甚至整个小黑客代码块似乎是合乎逻辑的,但如果不这样做,将导致异常
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[Nop.Admin.Models.Cms.RenderWidgetModel]', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[Nop.Web.Models.Cms.RenderWidgetModel]'.
新的
CustomViewEngine
如下所示:
public class CustomViewEngine: ThemeableRazorViewEngine {
private readonly string[] _emptyLocations = null;
public CustomViewEngine() {
PartialViewLocationFormats = new[] {
"~/Administration/CustomExtension/Views/{1}/{0}.cshtml",
"~/Administration/CustomExtension/Views/Shared/{0}.cshtml"
};
ViewLocationFormats = new[] {
"~/Administration/CustomExtension/Views/{1}/{0}.cshtml",
"~/Administration/CustomExtension/Views/Shared/{0}.cshtml"
};
}
protected override string GetPath(ControllerContext controllerContext, string[] locations, string[] areaLocations, string locationsPropertyName, string name, string controllerName, string theme, string cacheKeyPrefix, bool useCache, out string[] searchedLocations) {
searchedLocations = _emptyLocations;
if (string.IsNullOrEmpty(name)) {
return string.Empty;
}
string areaName = GetAreaName(controllerContext.RouteData);
//little hack to get nop's admin area to be in /Administration/ instead of /Nop/Admin/ or Areas/Admin/
if (!string.IsNullOrEmpty(areaName) && areaName.Equals("admin", StringComparison.InvariantCultureIgnoreCase)) {
var newLocations = areaLocations.ToList();
newLocations.Insert(0, "~/Administration/Views/{1}/{0}.cshtml");
newLocations.Insert(0, "~/Administration/Views/Shared/{0}.cshtml");
//Insert your custom View locations to the top of the list to be given a higher precedence
newLocations.Insert(0, "~/Administration/CustomExtension/Views/{1}/{0}.cshtml");
newLocations.Insert(0, "~/Administration/CustomExtension/Views/Shared/{0}.cshtml");
areaLocations = newLocations.ToArray();
}
bool flag = !string.IsNullOrEmpty(areaName);
List<ViewLocation> viewLocations = GetViewLocations(locations, flag ? areaLocations : null);
if (viewLocations.Count == 0) {
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Properties cannot be null or empty.", new object[] { locationsPropertyName }));
}
bool flag2 = IsSpecificPath(name);
string key = CreateCacheKey(cacheKeyPrefix, name, flag2 ? string.Empty : controllerName, areaName, theme);
if (useCache) {
var cached = ViewLocationCache.GetViewLocation(controllerContext.HttpContext, key);
if (cached != null) {
return cached;
}
}
if (!flag2) {
return GetPathFromGeneralName(controllerContext, viewLocations, name, controllerName, areaName, theme, key, ref searchedLocations);
}
return GetPathFromSpecificName(controllerContext, name, key, ref searchedLocations);
}
}
就这样。现在,将自定义视图/局部视图放置到视图位置,在本例中,它们是
~/Administration/CustomExtension/Views/{1}/{0}.cshtml
~/Administration/CustomExtension/Views/Shared/{0}.cshtml
其中{1}是要覆盖的控制器的名称,{0}是要覆盖的视图/局部视图的名称
例如,如果你对
Nop.Admin/Views/Category/Tree.cshtml
,请将你的自定义Tree.cshtml
放在Nop.Admin/CustomExtension/Views/Category/Tree.cshtml
中,Twisted Whisper有正确的答案,但我想我会分享一个链接到一篇更深入讨论这个问题的博客文章(详细介绍了自定义视图引擎的工作原理以及使用此技术的其他优点)如下所示:
我无法使用您的自定义视图引擎方法覆盖现有的核心视图。除非我删除/重命名现有的核心视图,否则我的自定义视图永远不会被使用。这表明我的自定义视图的优先级低于现有的核心视图。因此我决定删除/重命名我的自定义视图并刷新页面。您可以参考这里是克里恩肖特
http://imgur.com/AJgSrnt.jpg
这确认了我的自定义视图具有最低优先级。我尝试了主题覆盖方法,但无法使其工作(我使用给定的示例:~/Themes/MyTheme/Views/WidgetsNivoSlider/Nop.Plugin.Widgets.NivoSlider.Views.WidgetsNivoSlider.PublicInfo.cshtml
)@Wooncheck我很接近,但不太了解这个帖子。请您看看并告诉我我缺少了什么好吗?在呈现之前,这个会覆盖@Html.Partial
?您能回答我的问题吗?我希望我能早点找到您的博客帖子。我花了几个小时才找到解决方案,因为我是对nopCommerce还很陌生。@alex wolf…你的帖子很有帮助,但我仍然不理解。如果你能回顾一下,让我知道我做错了什么。Whisper我很接近,但不太理解一些东西。请参考。使用newLocations.Insert(0,~/Plugins/CustomExtension/Views/Admin/{1}/{0}.cshtml);而不是newLocations.Insert(0,“~/Administration/CustomExtension/Views/{1}/{0}.cshtml”);我已经成功地实现了Wolf、Woon和您讨论过的方法,但我遇到了一个有趣的问题。长话短说,我的CustomViewEngine工作得太好了,www.mysite.com抛出了一个错误,基本上是前端网络控制器试图消化管理视图(索引).然而,当我访问www.mysite.com/admin时,一切都正常运行…本质上,我的问题是如何处理并发视图名称?在我的例子中是Nop.admin/Home/Index.cshtml和Nop.Web/Home/Index.cshtml?这不应该抛出错误。管理是一个领域,意味着管理视图总是首先得到解决t、 您是否弄糟了路由?尝试将index.cshtml
重命名为index\u bak.cshtml
。刷新页面并引发异常。正在搜索订单视图。管理视图应始终位于顶部。这对nop.web视图也有效吗?我尝试实现它,但返回了viewPath和masterPath空字符串。有什么问题吗?
~/Administration/CustomExtension/Views/{1}/{0}.cshtml
~/Administration/CustomExtension/Views/Shared/{0}.cshtml