Содержание
Хранение данных пользователя с использованием сессий — это более сложный вариант работы по управлению состоянием в 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.


