У Optmizely есть мощный двигатель персонализации, который позволяет создавать пользовательскую аудиторию/группы посетителей. Это идет с одним ограничением, хотя. Это не поддерживает асинхронные операции. Приведенное ниже решение может работать для любого сценария, в котором вы не можете выполнять асинхронные операции в оптимизации.
Вот вариант использования в реальном мире и то, как мы его обошли.
Персонализация пользовательского опыта часто начинается с того, что знает, откуда приходит ваш посетитель. Один легкий подход – перевести IP -адрес пользователя в почтовый индекс Персонализировать опыт для пользователей в зависимости от их местоположения (государственное проведение и т. Д.). В оптимизированном CMS 12 (работа на ASP.NET Core 8), на пути к этому используется использование промежуточное программное обеспечениеПолем
Почему промежуточное программное обеспечение?
Группы посетителей имеет ключевое ограничение: критерии группы посетителей должны работать синхронно. Это означает, что вы не можете безопасно вызвать внешний API или ждать асинхронного поиска при оценке группы посетителей, не вызывая блокировки потоков на внешнюю службу, что исключает многие услуги IP-TO-ZIP. С другой стороны, промежуточное программное обеспечение ASP.NET, с другой стороны, работает для каждого запроса (который может быть отфильтрован) и полностью поддерживает асинхронные операции. Использование asynchelper.runsync () как указано здесь Не является масштабируемым решением и может вызвать голод пула и тупики в вашем приложении. Это делает его идеальным местом для таких проблем, как геолокация, регистрация, аутентификация и обогащение запроса. Разрешив почтовый индекс один раз в начале трубопровода, вы избегаете дублирующих поисков в контроллерах, контроллерах блоков или представлениях одновременно, избегая блокирования вызовов на внешние службы.
Шаг 1: Создайте контейнер с запросом.
Мы будем использовать класс Scoped для хранения разрешенного почтового индекса, чтобы он легко доступен через DI.
public sealed class GeoContext
{
public string? ZipCode { get; set; }
}
Шаг 2: Определите IP → ZIP Resolver
Это ваш сервис, который превращает IP -адрес в почтовый индекс. Вы можете использовать API, Maxmind или свой собственный источник данных, 3-й стороны.
public interface IZipFromIpResolver
{
Task GetZipFromIpAsync(string ip, CancellationToken ct = default);
}
Шаг 3: Реализация промежуточного программного обеспечения
Промежуточное программное обеспечение получает IP -клиент, вызывает резолювер и хранит результат в геоконтексте
public sealed class GeoZipMiddleware
{
private readonly RequestDelegate _next;
public GeoZipMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context, GeoContext geo, IZipFromIpResolver resolver)
{
// Filter out any paths to avoid calling the service on these requests
var path = httpContext.Request.Path.Value ?? "";
if (!path.StartsWith("/assets", StringComparison.OrdinalIgnoreCase) &&
!path.StartsWith("/static", StringComparison.OrdinalIgnoreCase) &&
!path.StartsWith("/api/custom", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/globalassets", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/.well-known", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/siteassets", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/Errors", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/contentassets", StringComparison.OrdinalIgnoreCase)) // Optimizely blobs
{
var ip = context.Connection.RemoteIpAddress?.ToString();
if (!string.IsNullOrWhiteSpace(ip))
{
try
{
// Call your GeoLocation Service
geo.ZipCode = await resolver.GetZipFromIpAsync(ip);
// You can also save it within the httpContext
httpContext.Items["ZipCode"] = geo.ZipCode;
}
catch
{
// log if needed; don’t block the request
}
}
}
await _next(context);
}
}
Шаг 4: Регистрационные услуги и промежуточное программное обеспечение
Обновление программы.cs
var builder = WebApplication.CreateBuilder(args);
// Add request-scoped container
builder.Services.AddScoped();
// Add resolver implementation
// builder.Services.AddSingleton();
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
// Use middleware early in the pipeline
app.UseMiddleware();
app.UseRouting();
app.UseAuthorization();
app.MapContent();
app.Run();
Шаг 5: Используйте в контроллерах, блоках или представлениях
Поскольку GeoContext подходит, вы можете вводить его в любом месте. Вы также можете использовать httpcontext.items, чтобы получить значение (установлено в промежуточном программном обеспечении)
public override bool IsMatch(IPrincipal principal, HttpContext httpContext)
{
var zipCode = httpContext.Items["ZipCode"];
// do something with it
return true;
}
Примечания и лучшие практики
-
Кэширование: Поиск ip-zip может быть дорогим. Используйте IsynchronizedObjectCache или распределенный кэш для уменьшения вызовов API.
-
Конфиденциальность: Рассматривать данные IP и местоположения как личную информацию (GDPR/CCPA). Избегайте упорства, если у вас нет четкого варианта использования.
-
Производительность: Подумайте о пропуске статического актива и других запросов URL -адреса внутри вашего промежуточного программного обеспечения для скорости.
Завершая
Используя промежуточное программное обеспечение ASP.NET Core в оптимизации CMS 12, вы можете легко обогатить каждый запрос геолокацией или любыми другими данными. Это мощно и может значительно улучшить производительность веб -сайта, удалив блокирующие вызовы из приложения.
16 августа 2025 года
Продолжение темы
