Я хочу скрыть определенную страницу из меню, если текущий IP-адрес сеанса находится в Израиле. Вот что я пробовал, но на самом деле пункт меню нигде не появляется.
Я протестировал поставщика GeoIP и, похоже, работает, что я делаю неправильно?Видимость отдельных элементов в MvcSiteMapProvider?
Вот как я создан меню и как я стараюсь, чтобы пропустить детали я не хочу в меню:
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;
}
- Является ли
DynamicNodeProvider
кешем? Если да, возможно, именно это вызывает проблему? Как я могу сделать его кеш за сеанс, поэтому каждый сеанс получает свое конкретное меню? - Правильно ли кэшировать IP за сеанс?
- Любые другие подсказки по отслеживанию проблемы?
Привет, и спасибо за ваш полный ответ. Поставщик видимости выглядит как лучшее решение. Не только это, но и то, является ли IP израильским, уже кэшируется за сеанс, что делает его еще лучше. Теперь я также узнал, что я могу сделать недействительным кеш программным путем, поэтому я собираюсь увеличить продолжительность кеша и сбросить его вручную при изменении меню. В любом случае ** вышеуказанный код не работает **, он не может найти поставщика видимости. – Shimmy
Вот ошибка, которую я получаю: «Экземпляр поставщика видимости с именем« MyNamespace.IsraelVisibilityProvider, MyAssembly »не найден. Проверьте конфигурацию DI, чтобы убедиться, что экземпляр поставщика видимости с этим именем существует и настроен правильно». – Shimmy
Вместо этого вы можете использовать 'node.VisibilityProvider = typeof (IsraelVisibilityProvider) .AssemblyQualifiedName', чтобы гарантировать правильность строки. Кроме того, если вы импортируете пространство имен 'MvcSiteMapProvider.Reflection', вы можете использовать метод расширения typeof (IsraelVisibilityProvider).ShortAssemblyQualifiedName() '. – NightOwl888