我使用C#注释配置MvcSiteMapProvider
而不是XML
。我根据文档实现了自定义可见性提供程序。我从FilteredSiteMapNodeVisibilityProvider
得出我的课程:
public class CustomVisibilityProvider: FilteredSiteMapNodeVisibilityProvider
{
public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
if (node.Attributes.Keys.Contains("customVisibility"))
{
string customVisibility = (string)node.Attributes["customVisibility"];
if (!string.IsNullOrEmpty(customVisibility))
{
customVisibility = customVisibility.Trim();
...
var criteria = ...
return criteria && base.IsVisible(node, sourceMetadata);
}
}
return base.IsVisible(node, sourceMetadata);
}
}
我的控制人员的观点:
[MvcSiteMapNode(Title = "My View", ParentKey = "ParentController", Key = "MyView", Order = 922, PreservedRouteParameters = "id", Attributes = @"{ ""Visibility"": ""SiteMapPathHelper,!*"" }")]
public ActionResult MyView(int? id)
{
return ViewForEntity(id);
}
我们可以看到我没有在此视图中使用我自己的customVisibility
属性,但我想使用标准Visibility
属性。除SiteMap
外,此特定视图不应出现在菜单或其他位置。
问题是,当在菜单中检查此视图的SiteMapNode的可见性时(a.k.a。(string)sourceMetadata["HtmlHelper"] == "MvcSiteMapProvider.Web.Html.SiteMapPathHelper"
),base.IsVisible(node, sourceMetadata)
会返回true
。我希望FilteredSiteMapNodeVisibilityProvider
将处理Visibility
属性并返回false
,因为此视图应仅显示在SiteMap中。
作为一种解决方法,我目前实施了自己的检查:
private bool checkDefaultVisibility(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
bool defaultVisibility = sourceMetadata["HtmlHelper"] == null || !node.Attributes.Keys.Contains("Visibility");
if (sourceMetadata["HtmlHelper"] != null && node.Attributes.Keys.Contains("Visibility"))
{
var htmlHelper = (string)sourceMetadata["HtmlHelper"]; // Example: "MvcSiteMapProvider.Web.Html.SiteMapPathHelper"
var helpersRules = ((string)node.Attributes["Visibility"]).Split(',');
foreach(var helperRule in helpersRules)
{
if (helperRule != "!*" && htmlHelper.EndsWith("." + helperRule))
{
defaultVisibility = true;
break;
}
}
}
return defaultVisibility;
}
这是我的自定义可见性提供程序的方法。我讨厌它,因为它不是通用的,只处理特定情况。与此同时,我不想在这里重新发明轮子。我希望Visibility
内部处理MvcSiteMapProvider
。如何实现?
答案 0 :(得分:1)
字典键区分大小写。 FilteredSiteMapVisibilityProvider
未返回false
的原因是您设置了名为Visibility
的属性,而不是预期的名称visibility
。
[MvcSiteMapNode(Title = "My View", ParentKey = "ParentController", Key = "MyView", Order = 922, PreservedRouteParameters = "id", Attributes = @"{ ""visibility"": ""SiteMapPathHelper,!*"" }")]
至于提高可视性和通用性,这很难做到,因为每个人都有不同的可见性要求。可见性提供者的目的是实现您自己的可见性要求。 FilteredSiteMapNodeVisibilityProvider
具有尽可能通用的特点,如果不符合您的要求,您需要定制。
请注意,通过将VisibilityProvider
设置为自定义可见性提供程序类的类型字符串,您可以override the default visibility provider查找特定节点。
[MvcSiteMapNode(Title = "My View", ParentKey = "ParentController", Key = "MyView", Order = 922, PreservedRouteParameters = "id", VisibilityProvider = "MyNamespace.CustomVisibilityProvider, MyAssembly", Attributes = @"{ ""customVisibility"": ""foo"" }")]
如果您需要在同一节点上使用多个可见性提供程序,则可以使用外部DI和CompositeSiteMapNodeVisibilityProvider
作为shown here来完成。
请注意,如果需要,可以继承此类以与内部DI容器一起使用 - 但对于内部DI,您需要一个默认构造函数,因此它在内部使用的类型必须硬编码到构造函数中。但是,您可以根据需要为整个可见性配置创建尽可能多的类。
using MvcSiteMapProvider;
using MvcSiteMapProvider.Reflection;
public class MyCompositeVisibilityProvider : CompositeSiteMapNodeVisibilityProvider
{
public MyCompositeVisibilityProvider()
: base(
typeof(MyCompositeVisibilityProvider).ShortAssemblyQualifiedName(),
// Note that the visibility providers are executed in
// the order specified here, but execution stops when
// the first visibility provider returns false.
new FilteredSiteMapNodeVisibilityProvider(),
new TrimEmptyGroupingNodesVisibilityProvider(),
new CustomVisibilityProvider()
)
{ }
}
然后使用以下方法调用它:
[MvcSiteMapNode(Title = "My View", ParentKey = "ParentController", Key = "MyView", Order = 922, PreservedRouteParameters = "id", VisibilityProvider = "MyNamespace.MyCompositeVisibilityProvider, MyAssembly", Attributes = @"{ ""visibility"": ""SiteMapPathHelper,!*"", ""customVisibility"": ""foo"" }")]
另请注意,还有许多其他方法可以控制可见性,包括security trimming,自定义模板(或创建新模板并明确指定HTML帮助程序中的templateName),甚至创建/Views/Shared/DisplayTemplates/
文件夹custom HTML helpers