Содержание
Хранение данных пользователя с использованием сессий — это более сложный вариант работы по управлению состоянием в ASP.NET Core, чем куки или использование HttpContext.items
, но, вместе с этим, и более гибкий в плане возможностей вариант.
Сессия в ASP.NET Core
Сессия — это ряд последовательных запросов, совершенных пользователем в браузере в течение некоторого времени. Сессии в ASP.NET Core могут использоваться для хранения временных данных, которые должны быть доступны, пока пользователь работает с приложением.
Для хранения состоянии сессии в ASP.NET Core используется следующая схема работы:
- На сервер создается словарь или хэш-таблица, которая размещается в кэше и сохраняется для каждого браузера. Эта таблица хранится до тех пор, пока живёт сессия.
- На клиент отправляется идентификатор сессии. Для этого используются куки.
- В каждом запросе пользователя возвращается кука с идентификатором сессии. По этому идентификатору из кэша получаются необходимые данные.
- Куки удаляются при завершении сессии. Если сервер получает куки, установленные для истекшей сессии, то для этих cookies создается новая сессия.
Сервер хранит данные сессии в течение ограниченного промежутка времени после последнего запроса. По умолчанию этот промежуток равен 20 минутам при необходимости этот промежуток времени можно изменить.
Использование сессий в ASP.NET Core
Чтобы использовать в приложении ASP.NET Core сессии нам необходимо:
- Подключить любой сервис кэширования — любой сервис кэширования, реализующий интерфейс
IDistributedCache
- Подключить сервис для работы с сессиями (вызвать
AddSession()
) - Встроить в конвейер обработки запросов компонент middleware для поддержки сессий (вызвать метод
UseSession()
)
Реализуем этот порядок работы в приложении:
namespace AspNetSessions { public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddDistributedMemoryCache();//подключаем кэш builder.Services.AddSession(); //добавляем сервис работы с сессиями var app = builder.Build(); app.UseSession(); //включаем middleware app.Run(async (context)=> { if (context.Session.IsAvailable) { if (context.Session.Keys.Contains("session_string")) { var data = context.Session.GetString("session_string"); await context.Response.WriteAsync(data); } else { context.Session.SetString("session_string", "Hello session"); await context.Response.WriteAsync("Hello, world"); } } }); app.Run(); } } }
В приведенном выше примере реализованы все шаги по использованию сессий в ASP.NET Core:
подключение необходимых сервисов
builder.Services.AddDistributedMemoryCache();//подключаем кэш builder.Services.AddSession(); //добавляем сервис работы с сессиями
подключили компонент middleware:
app.UseSession(); //включаем middleware
и только после этого начали работать с данными сессии:
app.Run(async (context)=> { if (context.Session.IsAvailable) { if (context.Session.Keys.Contains("session_string")) { var data = context.Session.GetString("session_string"); await context.Response.WriteAsync(data); } else { context.Session.SetString("session_string", "Hello session"); await context.Response.WriteAsync("Hello, world"); } } });
здесь мы проверяем наличие ключа в кэше session_string и в зависимости от результата проверки любо добавляем новую строку в кэш:
context.Session.SetString("session_string", "Hello session");
либо выводим значение пользователю:
var data = context.Session.GetString("session_string"); await context.Response.WriteAsync(data);
Как и в случае работы с куками, при первом запуске приложение не обнаружит ничего в кэше, поэтому необходимо будет обновить страницу в браузере. Чтобы убедиться в том, что сессия работает, можно заглянуть в инструменты разработчика в браузере и убедиться, что кука с идентификатором сессии используется в запросах:
Свойство context.Session
представляет собой объект, реализующий интерфейс ISession
. Посмотрим на свойства и методы этого интерфейса
Интерфейс ISession
Свойства
Id |
уникальный идентификатор текущего сессии. |
Is |
указывает, успешно ли загружен текущая сессия. |
Keys |
список всех ключей для текущей сессии. |
Методы
Clear() |
очищает сессию. |
Commit |
сохраняет сессию в хранилище данных. |
Load |
загружает сессию из хранилища данных. |
Remove() |
удаляет значение по указанному ключу |
Set() |
устанавливает по ключу значение, которое представляет массив байтов |
Try |
получает значение в виде массива байтов по заданному ключу, если оно имеется. |
Методы расширения
Get() |
возвращает значение массива байтов из ISession . |
Get |
возвращает значение типа int из ISession . |
Get |
возвращает строковое значение из ISession . |
Set |
задает значение int в ISession . |
Set |
задает String значение в ISession . |
Как можно увидеть, в данных сессии мы можем хранить три типа значений — массивы байтов, целочисленные значения и строки. Однако, это не означает, что мы не можем записать в данные сессии, например, какой-то сложный объект. Всё, что для этого необходимо — это сериализовать объект, например,в JSON. Чтобы немного упростить себе работу в дальнейшем, можно написать два метода расширения для ISession
:
public static class SessionExtensions { public static void SetJsonObject<T>(this ISession session, string key, T obj) { session.SetString(key, JsonSerializer.Serialize<T>(obj)); } public static T? GetJsonObject<T>(this ISession session, string key) { if (session.Keys.Contains(key)) return JsonSerializer.Deserialize<T>(session.GetString(key)); else return default; } }
Первый метод записывает объект в формате Json, второй — десериализует JSON в заданный объект. Эти методы расширения можно использовать, например, так:
public class Test { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } } public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddDistributedMemoryCache();//подключаем кэш builder.Services.AddSession(); //добавляем сервис работы с сессиями var app = builder.Build(); app.UseSession(); //включаем middleware app.Run(async (context) => { if (context.Session.Keys.Contains("json")) { var data = context.Session.GetJsonObject<Test>("json"); await context.Response.WriteAsJsonAsync(data); } else { Test test = new Test() { Id = 1, Description = "test", Name = "test" }; context.Session.SetJsonObject<Test>("json", test); await context.Response.WriteAsync("Hello, world"); } }); app.Run(); } }
Результат работы приложения:
первый запрос
второй запрос
Итого
Хранение данных пользователя с использованием сессий позволяет задействовать в работе сервера кэш и сохранять не только строки и целочисленные значения, но и сложные объекты, используя сериализацию в JSON.