четверг, 12 марта 2015 г.

Используем сессию в обработчиках (HTTP handlers) ASP.NET

Представьте себе гипотетическую ситуацию, когда вам нужно отдавать пользователю файлы, с, допустим, какими-то индивидуальными для каждого пользователя данными, причем именно отдавать уже готовые файлы, а не генерировать на лету. Самым простым и очевидным вариантом было бы создать обработчик, который будет вызываться для запросов вида "*_report.pdf", но для этого нам нужно понимать, можно ли отдавать пользователю файл, который он запрашивает или он принадлежит другому пользователю.
Передавать идентификатор в явном виде не только не правильно идеологически, но и просто не красиво, да и сохраненный файл, полученный по ссылке вида 10102_u323467_report.pdf?sessId=05446DA8F736B29A будет по умолчанию сохранен с таким же "кривым" именем.

Значительно проще положить этот идентификатор в сессию и получать его в обработчике уже оттуда. Для того, чтобы объект Session был доступен, нам нужно, чтобы обработчик наследовал не только от интерфейса IHttpHandler, но од одного из интерфейсов IRequiresSessionState или IReadOnlySessionState в зависимости от того нужен ли нам доступ только на чтение (IReadOnlySessionState) или на чтение и запись (IRequiresSessionState). На самом деле, записать в объект сессии вы сможете что угодно в любом случае, единственное отличие, что при использовании IReadOnlySessionState в конце обработки запроса данные сессии не сохраняются.



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

    
    public class SessionEnabledHandler : IHttpHandler, IRequiresSessionState
    {

     public bool IsReusable
     {
      get
      {
       return true;
      }
     } 

        public void ProcessRequest(HttpContext context)
        {
            string sessionMarket = (string)context.Session["SessionData"];
            string file = context.Request.RawUrl;
            //после чего можно проверить имеет ли данный пользователь доступ к запрошенному файлу
        }
    }

Ну и заодно напомню, что такое IsReusable. Во время обработки каждого запроса объекты обработчиков полностью проходят все стадии начиная от создания и заканчивая удаления из памяти сборщиком мусора. Так вот, свойство IsReusable говорит среде выполнения о том, нужно ли после обработки запроса удалять объект или его можно сохранить и использовать для обработки последующих запросов.
Касательно нашего примера, IsReusable равный true был бы полезным, в случае, если бы наш класс ReportDownloadHandler имел конструктор, в котором бы создавались какие-то необходимые нам для обработки структуры данных или использовались бы другие дорогие операции.
Единственное, при использовании IsReusable=true необходимо проверять, чтобы к концу выполнения метода ProcessRequest состояние объекта было бы таким же, как и в начале обработки запроса.

Комментариев нет:

Отправить комментарий