Веб-сайт ASP.NET + сеанс с поддержкой SQL - PullRequest
1 голос
/ 04 марта 2011

Мы используем проект веб-сайта ASP.NET с динамической компиляцией, недавно перешли в состояние сеанса с поддержкой SQL Server и начали получать странную ошибку.Я выяснил, что является причиной этого, но я не знаю, как решить эту проблему.

Шаги для воспроизведения на локальном хосте (с включенным сеансом sql):

  • Поместите объект, определенный в AppCode, скажем, это DanObject в сеанс.

    Session ["x"] = новый DanObject ();

  • (сеанс сериализован в базу данных)

  • Изменить что-либо вкод приложения, заставляющий сайт перекомпилироваться при следующем запросе
  • Сделать запрос на любой странице, которая обращается к сеансу

Ошибка «Не удается найти сборку» App_SubCode_CS.rmdbqb81,Версия = 0.0.0.0, Культура = нейтральная, PublicKeyToken = null '. "

Происходит следующее: каждый раз, когда AppCode компилируется, он попадает в сборку со случайным именем.Когда мой сеанс сериализован в первый раз, AppCode был назван AppCode_123.Когда я изменил свое приложение, AppCode теперь является AppCode_456.Однако у сеанса, хранящегося в моей базе данных, есть объект, определенный в AppCode_123.Когда сеанс пытается выполнить двоичную десериализацию DanObject, он взрывается, потому что не может найти AppCode_123.

Как проще всего это исправить?
* Пожалуйста, не говорите, переключитесь на веб-приложение- наша база кода огромна, и на данный момент это невозможно:)

Ответы [ 3 ]

1 голос
/ 04 марта 2011

Использовать явное пространство имен вокруг DanObject

0 голосов
/ 16 июня 2011

Проблема была в том, что у нас были отдельные папки в App_Code для разных языков кода. Вот почему в сообщении об ошибке говорится «App_SubCode_CS ...» вместо «App_Code ...», потому что определенный класс пришел из папки с кодом CS (для кода c #). Каждая из этих папок кода (определенная в web.config) компилируется в свою собственную сборку.

Обычно, когда у вас нет нескольких папок кода AppCode, ASP.NET может сериализовать и десериализовать объекты, скомпилированные в разное время или на разных серверах, поскольку имя сборки ("AppCode.randomstring") хранится вместе с именем класса. в сериализованном выводе. При десериализации инфраструктура вызывает System.Type.GetType() для имени сборки + класса, и эта функция имеет специальный регистр для обработки имен сборок, начинающихся с App_Code, где, если она не находит сборку, названную точно так же, но она делает найдите тот, который начинается с App_Code, он использует эту сборку для загрузки класса.

Если у вас есть языковые папки в App_Code, сгенерированные сборки имеют имена, подобные: App_SubCode_FOLDERNAME.randomstring, и среда, похоже, не справляется с этим случаем. Таким образом, если у вас есть 2 веб-сервера, совместно использующих сеанс с поддержкой Sql, класс Foo компилируется как "App_SubCode_FN.random1, Foo" на сервере A и "App_SubCode_FN.random2, Foo" на сервере B. Если пользователь получает Foo в своем сеансе от сервера A, а затем свой следующий запрос переходит на сервер B, сервер B не сможет десериализовать Foo, потому что не может найти сборку с именем "App_SubCode_FN.random1".

Эту проблему можно решить, избавившись от старого кода VB (позволяя скомпилировать код приложения в единую сборку, с которой лучше всего работает .NET), или написав пользовательский SerializationBinder + пользовательскую реализацию Sql Server. поддерживаемая сессия.

0 голосов
/ 04 марта 2011

Хорошо, второе самое простое решение:
Переместите код для этого класса вместо отдельной библиотеки сборок.Таким образом, когда сериализатор увидит класс, он будет иметь известное доброе имя для работы.Конечно, это лишает вас возможности вносить изменения непосредственно в каталог app_code ... что вам не следует делать в любом случае.

Третье самое простое (и лучшее) решение:
Не помещайте объекты в сессию.Если вам нужно несколько свойств, это одно, сохраняйте эти свойства как обычные строки.

<slight_rant>

Серьезно, помещение полных объектов в сессию НЕ является тем, для чего оно было построено.

См. Мой ответ здесь ( Сеансы и хранение объектов ) для получения дополнительной информации о причинах, по которым вы не хотите этого делать.

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

</slight_rant>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...