Общий обработчик ASHX не срабатывает, пока страница не будет обновлена ​​(с помощью F5 или кнопки «Обновить»)

Я написал обработчик изображений, который также реализует кэширование на стороне клиента, отправляя 304 при выполнении определенных условий. Для доступа к разным фотографиям или собственной фотографии вошедшего в систему человека мы размещаем обработчик следующим образом на разных страницах.

<img src="EmployeePhoto.ashx" />
<img src="EmployeePhoto.ashx?self" />
<img src="EmployeePhoto.ashx?default" />

ПРОБЛЕМА В том, что если я захожу на любую страницу, щелкнув ссылку во второй раз после того, как изображение было кэшировано на странице, оно не попадет в обработчик (отладчик не попадет). Но если я обновлю эту страницу с помощью F5 или кнопки обновления, только тогда она попадет в обработчик и покажет то, что я хочу показать.

Только когда я пытаюсь получить к нему доступ с добавленным другим параметром, например "&date=" + CurrentDate, он попадает в обработчик, но убивает цель кэширования.

<img src="EmployeePhoto.ashx?default&date=03/31/14 00:00:00" /> //or something like that

Я знаю, что в этом коде нет ничего плохого, поскольку он хорошо служит, когда его нажимают. Вот код на всякий случай.

public void ProcessRequest(HttpContext context)
{
    var isDefault = true;
    var textIfModifiedSince = context.Request.Headers["If-Modified-Since"];
    context.Response.ClearHeaders();
    context.Response.Cache.SetCacheability(HttpCacheability.Public);
    context.Response.Cache.SetExpires(DateTime.Now.AddMonths(6));
    try
    {
        var isOwn = false;
        var user = /*Gets logged in user instance from service*/;
        var employeeId = 0;
        if (context.Request.QueryString.Count > 0)
        {
            if(context.Request.QueryString[0] == "self")
            {
                if (user != null)
                {
                    employeeId = Convert.ToInt32(user.EmployeeId);
                    isOwn = true;
                }
            }
            else if (!int.TryParse(context.Request.QueryString[0], out employeeId))
                employeeId = 0;
        }
        else
        {
            if (user != null)
            {
                employeeId = Convert.ToInt32(user.EmployeeId);
                isOwn = true;
            }
        }


        if (user != null && employeeId != 0)
        {
            var employee = GetEmployee(employeeId);
            if (
                (!string.IsNullOrEmpty(textIfModifiedSince) && employee.Modify_Date == null) 
                || !string.IsNullOrEmpty(textIfModifiedSince) 
                && employee.Modify_Date != null 
                && employee.Modify_Date <= Convert.ToDateTime(textIfModifiedSince).AddMinutes(1))
            {
                isDefault = false;
                context.Response.Cache.SetLastModified(Convert.ToDateTime(textIfModifiedSince));
                context.Response.Status = "304 Not Modified";
                HttpContext.Current.ApplicationInstance.CompleteRequest();
                return;
            }
            if (
                employee != null 
                && !string.IsNullOrEmpty(employee.Picture) 
                && (isOwn || employee.LocationID != null) 
                && (isOwn || HasRequiredRoles))
            {
                var path = context.Server.MapPath("~//" + EmployeePhotoPath);
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);
                var fileName = employee.Picture;
                var destinationPath =
                    context.Server.MapPath("~//" + EmployeePhotoPath).ToString(CultureInfo.InvariantCulture);
                if (File.Exists(destinationPath + fileName))
                {
                    isDefault = false;
                    context.Response.Cache.SetLastModified(employee.Modify_Date > DateTime.Now ? DateTime.Now : (employee.Modify_Date ?? DateTime.Now));
                    context.Response.ContentType = GetContentType(employee.Picture);
                    context.Response.WriteFile(EmployeePhotoPath + employee.Picture);
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                    return;
                }
                isDefault = false;
                DownloadFromSFTP(path, employee.Picture, user, employeeId.ToString(CultureInfo.InvariantCulture));
                context.Response.Cache.SetLastModified(employee.Modify_Date > DateTime.Now ? DateTime.Now : (employee.Modify_Date ?? DateTime.Now));
                context.Response.ContentType = GetContentType(employee.Picture);
                context.Response.WriteFile(EmployeePhotoPath + employee.Picture);
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
        }
    }
    catch (Exception ex)
    {
        Log.Debug("Photo Handler Failed.", ex);
    }
    finally
    {
        if (isDefault)
        {
            if (!string.IsNullOrEmpty(textIfModifiedSince))
            {
                context.Response.Cache.SetLastModified(Convert.ToDateTime(textIfModifiedSince));
                context.Response.Status = "304 Not Modified";
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
            context.Response.Cache.SetLastModified(DateTime.Now);
            context.Response.ContentType = GetContentType("images/avatar.gif");
            context.Response.WriteFile("images/avatar.gif");
            HttpContext.Current.ApplicationInstance.CompleteRequest();
        }
    }
}

ДОПОЛНЕНИЕ: Проблема возникает в следующем сценарии.

  1. Пользователь получает доступ к изображению, обращаясь к EmployeePhoto.ashx?Eid=20349.
  2. Админ меняет фото на Ид=20349
  3. Пользователь снова обращается к странице (не обновляя, а получая доступ к странице по какой-либо ссылке)

Кэшированное изображение на странице приносит старое изображение, если оно попало в обработчик, то там ситуация уже была обработана, но это не так и страница показывает саму кешированную версию. Проверял только на хроме.


person Taha Rehman Siddiqui    schedule 31.03.2014    source источник
comment
если вы хотите, чтобы изображение загружалось каждый раз, а не только в первый раз, есть некоторые идеи в этот пост   -  person Pete    schedule 31.03.2014
comment
Я посетил вопрос @Pete и уже попробовал упомянутое там решение. Но это убивает цель кэширования, так как каждый раз, когда он будет публиковать новый If-Modified-Since   -  person Taha Rehman Siddiqui    schedule 31.03.2014
comment
Это Bekaar sawaal и, кстати, 614 kese karli itni Reputation??   -  person SHAKIR SHABBIR    schedule 16.04.2014


Ответы (1)


Само использование неправильное.

Вы хотите уникальные фотографии зарегистрированных людей с одного и того же URL-адреса? Это невозможно

После попадания по URL-адресу браузер кэширует его.

Моим решением было бы добавить идентификатор пользователя к обработчику.

<img src="EmployeePhoto.ashx?uid=1" />
<img src="EmployeePhoto.ashx?self&uid=1" />
<img src="EmployeePhoto.ashx?default&uid=1" />

Таким образом, браузер сделает запрос и получит ответ, кэширует его и использует кеш для этого конкретного пользователя, поскольку URL-адреса совпадают.

Увидел ваше дополнение. Я бы предложил сохранить флаг в базе данных независимо от того, изменил ли администратор изображение или нет. Затем, если админ изменил картинку, вы можете изменить свои заголовки. Теперь удалите флаг из базы данных, чтобы в следующий раз вы не делали того же.

person Amit Joki    schedule 31.03.2014
comment
Спасибо за ответ. Я обновил вопрос со сценарием. Пожалуйста, прочитайте сценарий. Этот ответ не отвечает на мой вопрос, поэтому я не могу отметить его как один. - person Taha Rehman Siddiqui; 31.03.2014