注释中的 MvcSiteMapProvider 可见性指令在实现自定义可见性提供程序时不起作用
MvcSiteMapProvider Visibility directives in annotation doesn't work when implementing custom visibility provider
我正在使用 C# 注释而不是通过 XML
配置 MvcSiteMapProvider
。我根据文档实现了自定义可见性提供程序。我的 class 来自 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)
returns true
.我希望 FilteredSiteMapNodeVisibilityProvider
将处理 Visibility
属性和 return 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
内部处理。如何实现?
字典键区分大小写。 FilteredSiteMapVisibilityProvider
没有返回 false
的原因是因为您设置了一个名为 Visibility
的属性,而不是预期的名称 visibility
.
[MvcSiteMapNode(Title = "My View", ParentKey = "ParentController", Key = "MyView", Order = 922, PreservedRouteParameters = "id", Attributes = @"{ ""visibility"": ""SiteMapPathHelper,!*"" }")]
就提高可见度而言 "universal",这很难做到,因为每个人都有不同的可见度要求。可见性提供者的目的是实现您自己的可见性要求。 FilteredSiteMapNodeVisibilityProvider
尽可能通用,如果不能满足您的要求,您需要定制。
请注意,您可以通过将 VisibilityProvider
设置为自定义可见性提供程序 class.
的类型字符串来 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
as shown here 来完成。
请注意,如果需要,您可以继承此 class 以便与内部 DI 容器一起使用 - 但对于内部 DI,您需要一个默认构造函数,因此它在内部使用的类型必须是硬编码的进入构造函数。但是您可以根据需要为整个可见性配置创建任意数量的这些 classes。
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, customizing the templates (or creating new templates and specifying the templateName in the HTML helper explicitly) in the /Views/Shared/DisplayTemplates/
folder, or even creating custom HTML helpers。
我正在使用 C# 注释而不是通过 XML
配置 MvcSiteMapProvider
。我根据文档实现了自定义可见性提供程序。我的 class 来自 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)
returns true
.我希望 FilteredSiteMapNodeVisibilityProvider
将处理 Visibility
属性和 return 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
内部处理。如何实现?
字典键区分大小写。 FilteredSiteMapVisibilityProvider
没有返回 false
的原因是因为您设置了一个名为 Visibility
的属性,而不是预期的名称 visibility
.
[MvcSiteMapNode(Title = "My View", ParentKey = "ParentController", Key = "MyView", Order = 922, PreservedRouteParameters = "id", Attributes = @"{ ""visibility"": ""SiteMapPathHelper,!*"" }")]
就提高可见度而言 "universal",这很难做到,因为每个人都有不同的可见度要求。可见性提供者的目的是实现您自己的可见性要求。 FilteredSiteMapNodeVisibilityProvider
尽可能通用,如果不能满足您的要求,您需要定制。
请注意,您可以通过将 VisibilityProvider
设置为自定义可见性提供程序 class.
[MvcSiteMapNode(Title = "My View", ParentKey = "ParentController", Key = "MyView", Order = 922, PreservedRouteParameters = "id", VisibilityProvider = "MyNamespace.CustomVisibilityProvider, MyAssembly", Attributes = @"{ ""customVisibility"": ""foo"" }")]
如果您需要在同一节点上使用多个可见性提供程序,可以使用外部 DI 和 CompositeSiteMapNodeVisibilityProvider
as shown here 来完成。
请注意,如果需要,您可以继承此 class 以便与内部 DI 容器一起使用 - 但对于内部 DI,您需要一个默认构造函数,因此它在内部使用的类型必须是硬编码的进入构造函数。但是您可以根据需要为整个可见性配置创建任意数量的这些 classes。
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, customizing the templates (or creating new templates and specifying the templateName in the HTML helper explicitly) in the /Views/Shared/DisplayTemplates/
folder, or even creating custom HTML helpers。