次の場所にある nopcommerce ビューをオーバーライドしようとしています。
Nop.Admin/Views/Category/Tree.cshtml
プラグインフォルダーで開発したビューで:
Views/Misc/Tree.cshtml
どうすればいいですか?
次の場所にある nopcommerce ビューをオーバーライドしようとしています。
Nop.Admin/Views/Category/Tree.cshtml
プラグインフォルダーで開発したビューで:
Views/Misc/Tree.cshtml
どうすればいいですか?
私が書いたこの詳細な記事を試してみてください: nopCommerce プラグインでビューを表示する 3 つの方法 (埋め込みリソース、テーマのオーバーライド、およびカスタム ビュー エンジン)
@wooncherk のカスタム ビュー エンジンは、ビューを将来簡単にオーバーライドできるように準備するのに優れています。ただし、nopCommerce はカスタム ビューよりも管理ビューを最優先するため、既存のコア ビューをオーバーライドするには不十分です。これは、 の仮想メソッドGetPath()
で確認できますNop.Web.Framework.Themes.ThemeableVirtualPathProviderViewEngine.cs
。疑問に思っている人のために、ThemeableVirtualPathProviderViewEngine
継承されたクラスは、ThemeableRazorViewEngine
@wooncherk のCustomViewEngine
クラスによって継承されています。
上記の のスクリーンショットを参照すると
ThemeableVirtualPathProviderViewEngine
、矢印で示されているように、管理ビューが常にカスタム ビューよりも優先されることが 2 行で確認できます。
@wooncherk のカスタム ビュー エンジン メソッドを拡張して、既存の管理コア ビューのオーバーライドにも対応することができました。これには、仮想メソッドのオーバーライドとクラスGetPath()
へのコピーが含まれますCustomViewEngine
。この時点で、犯人の 2行または小さなハックコード ブロック全体を削除することは理にかなっているように思えますが、例外が発生するため、そうしないでください。
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);
}
}
カスタム ビューの優先順位を高くするために、犯人行の下に 2 行追加されていることに注意してください。
最後に、変更する必要がありますRouteProvider.cs
public class RouteProvider : IRouteProvider {
public void RegisterRoutes(RouteCollection routes) {
//Insert our CustomViewEngine into the top of the System.Web.Mvc.ViewEngines.Engines Collection to be given a higher precedence
System.Web.Mvc.ViewEngines.Engines.Insert(0, new CustomViewEngine());
}
public int Priority {
get {
return 1;
}
}
}
それはそれについてです。ここで、カスタム ビュー/部分ビューをビューの場所に配置します。この場合は、
~/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 には正しい答えがありますが、これについて詳しく説明しているブログ投稿へのリンクを共有したいと思います (カスタム ビュー エンジンのしくみや、この手法を使用するその他の利点について詳しく説明しています)。