Есть ли способ использовать сессию для объектов в ядре asp.net, как в веб-формах? - PullRequest
0 голосов
/ 30 января 2019

У меня есть проект в веб-формах, и я пытаюсь преобразовать его в ядро ​​asp.net.Моя проблема в том, что в веб-формах я сохраняю объект в сеансе, и когда я его получаю, я могу вносить в него изменения, и он сохраняет их.С другой стороны, в ядре я установил объект для сеанса, сериализовав его.Когда я получаю это и делаю изменения, это не затрагивает объект, сохраненный в сеансе.Есть ли способ сохранить объект как есть (без его сериализации), поэтому, когда я получаю его из сеанса и вносю в него изменения, чтобы продолжать использовать его и не нужно снова устанавливать его в сеансе?

Сеанс был

 System.Web.HttpContext.Current.Session["object"]

И сделал это

AppHttpContext.Current.Session.GetString("object") 

И затем я десериализовал его в нужный объект.

Ps: Iиспользовал AppHttpContext для получения сеанса вне контроллера

Ответы [ 4 ]

0 голосов
/ 18 марта 2019

Для использования объекта / массива в сеансе вам понадобятся некоторые настройки: `

public static class SessionExtensions {
public static void SetObject(this ISession session, string key, object value)
{
    session.SetString(key, JsonConvert.SerializeObject(value));
}

public static T GetObject<T>(this ISession session, string key)
{
    var value = session.GetString(key);
    return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
} }

Теперь вы можете установить его следующим образом:

var objComplex = new ComplexClass();
HttpContext.Session.SetObject("ComplexObject", objNew);

И получить его:

var objComplex = HttpContext.Session.GetObject("ComplexObject");
0 голосов
/ 30 января 2019

Технически ASP.NET также никогда не поддерживал это.Это была случайность, которая просто работала при использовании сессий InProc (то есть в памяти), благодаря тому, как хранилище сессий работало в этом случае.Если бы вы использовали альтернативное хранилище сеансов, такое как SQL Server, вам также пришлось бы сериализовать / десериализовывать объекты в и из сеанса.ASP.NET Core отличается только тем, что использует обобщенное хранилище сеансов, поэтому он принудительно сериализует / десериализует любой объект, даже если вы используете хранилище в памяти.

Тем не менее, ваша проблема здесьчто вы просто не сохраняете свои изменения обратно.Опять же, вы полагались на случайное поведение.Поскольку ASP.NET непосредственно сохранял объект в памяти, выполнение операций над этим объектом автоматически «сохранялось», поскольку это была та же ссылка.При десериализации вы создаете новый экземпляр, поэтому операции не будут продолжаться до тех пор, пока вы не сериализуете объект обратно в сеанс.

Наконец, веб-формы или нет, это было никогда рекомендуетсяили даже правильный способ сделать вещи.Хранилище сессий является энергозависимым.Это не предназначено для чего-либо кроме кратковременного (и ненадежного) постоянства.Другими словами, вы никогда не можете рассчитывать на что-то находящееся в сеансе, поэтому вы всегда должны защищать код вокруг случая, когда данные не существуют.Если вы зависите от того, что там есть, как это звучит, как здесь, то вы всегда настраивали себя на неудачу.

Однако, если вы делаете что-то вроде многошаговой формы,допустимо, чтобы отдельные шаги входили в сеанс, хотя на самом деле следует использовать TempData вместо Session для этого.На последнем этапе, однако, ваш составной объект должен быть сохранен в чем-то вроде SQL Server, а не в сеансе.Практически во всех других случаях вы должны просто сохранить что-то вроде SQL Server и полностью избегать Session.

0 голосов
/ 30 января 2019

Задача миграции не будет простой.

Вы можете выполнить следующие действия:

1) Сначала замените свою зависимость от Session от какого-либо Сервиса, который вы можете внедрить в контроллеры или другие сервисы.Хорошей идеей было бы использовать жесткие значения кода в этой службе, чтобы проверить, может ли весь код, зависящий от вашей предыдущей реализации сеанса, использовать новую службу.

2) Реализовать фильтр (например, путем реализации IAsyncPageFilter в случаестраниц Razor), чтобы подключиться к HttpContext User и настроить какой-либо объект Lookup, который можно получить из реализации Cache. Хорошей идеей будет использование распределенного кэша Redis.Этот объект должен иметь ключ в качестве идентификатора пользователя - значения могут быть любыми данными, которые вы хотите добавить в «сеанс».Для этого используйте сервис «Кэш», скрывая детали реализации Кэша от клиентского кода.(Не забудьте сделать эти зависимости области «Запрос» так, чтобы пользователь HttpContext был правильно заполнен.)

3) Реализуйте методы в новом Сервисе для добавления / изменения объекта Cache, чтобы обновлять данные «сеанса».

Мораль истории: уменьшите зависимость от специфических функций платформы.По крайней мере, инкапсулируйте эти зависимости, используя какой-либо сервис, который может быть заменен позже без клиентского кода в зависимости от этих функций.

0 голосов
/ 30 января 2019

Ядро ASP.NET не поддерживает прямое сохранение объектов в Session, как это могут делать проекты Web Forms.В ASP.NET Cpre есть только прямая поддержка для сохранения примитивных типов в Session, например, массив string, int или byte.Поэтому любой более сложный объект необходимо будет сериализовать в строку или сериализовать непосредственно в байтовый массив, и эта сериализация может быть сохранена в Session.

Обычно люди достигают этого, выполняя JSON-сериализацию объекта для генерации строки, а затем сохраняя строку в Session.Но когда вы извлекаете строку JSON из Session и десериализуете ее обратно в объект, любые изменения этого объекта не будут отражены в предыдущем JSON, который представлял объект, который в данный момент хранится в сеансе.Таким образом, изменения в объекте не отражаются напрямую в Session.

Это поведение отличается от того, что было видно в веб-формах, и является результатом того, что объект не сохраняется в сеансе, это его сериализация.Поэтому, если вы измените объект и хотите, чтобы эти изменения были сохранены в сеансе, вам нужно будет сериализовать объект снова и сохранить эту сериализацию (например, json) в сеансе.

Помогает ли это?

...