gpt4 book ai didi

c# - MvcSiteMapProvider 中单个项目的可见性?

转载 作者:太空宇宙 更新时间:2023-11-03 10:31:57 25 4
gpt4 key购买 nike

如果当前 session IP 在以色列,我想从菜单中隐藏某个页面。这是我尝试过的方法,但实际上菜单项没有出现在任何地方。
我测试了 GeoIP 提供商,它似乎工作正常,我做错了什么?

下面是我如何创建菜单以及如何尝试跳过菜单中不需要的项目:

public class PagesDynamicNodeProvider
: DynamicNodeProviderBase
{
private static readonly Guid KeyGuid = Guid.NewGuid();
private const string IsraelOnlyItemsPageKey = "publications-in-hebrew";

public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode siteMapNode)
{
using (var context = new Context())
{
var pages = context.Pages
.Include(p => p.Language)
.Where(p => p.IsPublished)
.OrderBy(p => p.SortOrder)
.ThenByDescending(p => p.PublishDate)
.ToArray();

foreach (var page in pages)
{


//*********************************************************
//Is it the right way to 'hide' the page in current session
if (page.MenuKey == IsraelOnlyItemsPageKey && !Constants.IsIsraeliIp)
continue;

var node = new DynamicNode(
key: page.MenuKey,
parentKey: page.MenuParentKey,
title: page.MenuTitle,
description: page.Title,
controller: "Home",
action: "Page");

node.RouteValues.Add("id", page.PageId);
node.RouteValues.Add("pagetitle", page.MenuKey);

yield return node;
}
}
}
}

以下是我如何确定和缓存 IP 是否来自以色列:

private const string IsIsraeliIpCacheKey = "5522EDE1-0E22-4FDE-A664-7A5A594D3992";
private static bool? _IsIsraeliIp;
/// <summary>
/// Gets a value indicating wheather the current request IP is from Israel
/// </summary>
public static bool IsIsraeliIp
{
get
{
if (!_IsIsraeliIp.HasValue)
{
var value = HttpContext.Current.Session[IsIsraeliIpCacheKey];
if (value != null)
_IsIsraeliIp = (bool)value;
else
HttpContext.Current.Session[IsIsraeliIpCacheKey] = _IsIsraeliIp = GetIsIsraelIpFromServer() == true;
}
return _IsIsraeliIp.Value;
}
}

private static readonly Func<string, string> FormatIpWithGeoIpServerAddress = (ip) => @"http://www.telize.com/geoip/" + ip;
private static bool? GetIsIsraelIpFromServer()
{
var ip = HttpContext.Current.Request.UserHostAddress;
var address = FormatIpWithGeoIpServerAddress(ip);
string jsonResult = null;
using (var client = new WebClient())
{
try
{
jsonResult = client.DownloadString(address);
}
catch
{
return null;
}
}

if (jsonResult != null)
{
var obj = JObject.Parse(jsonResult);
var countryCode = obj["country_code"];

if (countryCode != null)
return string.Equals(countryCode.Value<string>(), "IL", StringComparison.OrdinalIgnoreCase);
}
return null;
}
  1. 是否缓存了 DynamicNodeProvider?如果是,也许这就是导致问题的原因?我怎样才能使它缓存每个 session ,以便每个 session 都有其特定的菜单?
  2. 缓存每个 session 的 IP 是否正确?
  3. 关于追踪问题的任何其他提示?

最佳答案

您的链接没有出现在任何地方的原因是站点地图被缓存并在所有用户之间共享。无论构建缓存的用户请求的状态如何,您的所有用户都会看到。

然而,如果没有缓存,查找节点层次结构的性能对于每个请求来说都会非常昂贵。一般来说,支持使用每个 SiteMap 的 session 的方法(使用外部 DI),但出于性能和可伸缩性原因不推荐使用。

推荐的方法是始终将每个用户的所有预期节点加载到 SiteMap 的缓存中(或通过 forcing a match 伪造它)。然后使用以下方法之一适本地显示和/或隐藏节点。<​​/p>

  1. Security Trimming
  2. 内置或 custom visibility providers
  3. 自定义 HTML 帮助程序模板(在 /Views/Shared/DisplayTemplates/ 文件夹中)
  4. 自定义 HTML 助手

最好将 SiteMap 视为分层数据库。您只需设置数据结构,该数据结构适用于应用程序的每个用户。然后,您针对可根据需要过滤的共享数据(SiteMap 对象)进行按请求查询。

当然,如果以上选项均未涵盖您的用例,请 answer my open question as to why anyone would want to cache per user ,因为它几乎违背了制作站点 map 的目的。

在这种情况下,您可以通过以下方式设置可见性提供程序来进行过滤。

public class IsrealVisibilityProvider : SiteMapNodeVisibilityProviderBase
{
public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
return Constants.IsIsraeliIp;
}
}

然后从您的 DynamicNodeProvider 中删除条件逻辑,并将可见性提供程序添加到它适用的每个节点。

public class PagesDynamicNodeProvider
: DynamicNodeProviderBase
{
private const string IsraelOnlyItemsPageKey = "publications-in-hebrew";

public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode siteMapNode)
{
using (var context = new Context())
{
var pages = context.Pages
.Include(p => p.Language)
.Where(p => p.IsPublished)
.OrderBy(p => p.SortOrder)
.ThenByDescending(p => p.PublishDate)
.ToArray();

foreach (var page in pages)
{
var node = new DynamicNode(
key: page.MenuKey,
parentKey: page.MenuParentKey,
title: page.MenuTitle,
description: page.Title,
controller: "Home",
action: "Page");

// Add the visibility provider to each node that has the condition you want to check
if (page.MenuKey == IsraelOnlyItemsPageKey)
{
node.VisibilityProvider = typeof(IsraelVisibilityProvider).AssemblyQualifiedName;
}
node.RouteValues.Add("id", page.PageId);
node.RouteValues.Add("pagetitle", page.MenuKey);

yield return node;
}
}
}
}

对于更复杂的可见性方案,您可能希望创建一个父可见性提供者,它根据您自己的自定义逻辑调用子可见性提供者,然后在 web.config 中将父可见性提供者设置为默认值。

<add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MyNamespace.ParentVisibilityProvider, MyAssembly"/>

或者,使用外部 DI,您可以在 SiteMapNodeVisibilityProviderStrategy 的构造函数中设置默认值。

// Visibility Providers
this.For<ISiteMapNodeVisibilityProviderStrategy>().Use<SiteMapNodeVisibilityProviderStrategy>()
.Ctor<string>("defaultProviderName").Is("MyNamespace.ParentVisibilityProvider, MyAssembly");

关于c# - MvcSiteMapProvider 中单个项目的可见性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29751962/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com