Почему .NET вдруг попытается сериализовать мой объект в моем приложении ASP.NET?

Я запускаю веб-роль Azure в полном режиме IIS. Запросы авторизуются с помощью пользовательской базовой аутентификации.

У меня есть класс MyAssembly.CustomIdentity, который наследуется от System.Security.Principal.GenericIdentity. Когда вызывается обработчик HttpApplication.AuthenticateRequest (код OnEnter() из приведенной выше ссылки), он выполняет проверки, затем создает экземпляр MyIdentity.CustomIdentity и назначает его HttpContext.Current.User. Затем фактический обработчик запросов ASP.NET получает этот объект и может использовать его, чтобы определить, для какого пользователя он предназначен.

Теперь все более или менее нормально работает в конфигурации по умолчанию, когда IIS работает под учетной записью NETWORK SERVICE. Во время запуска роли я перезапускаю пул приложений IIS под локальным пользователем (чтобы предоставить ему дополнительные привилегии). Теперь даже следующий код

public partial class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        bool isAvailable = Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsAvailable;
    }
}

будут генерировать различные исключения. Сначала он говорит, что не может сериализовать мой класс CustomIdentity (что я исправляю, добавляя атрибут Serializable), затем говорит, что не может загрузить сборку MyAssembly (что я исправляю, обрабатывая событие AppDomain.AssemblyResolve).

Чего я не понимаю, так это почему сериализация срабатывает? Почему запуск пула приложений под локальным пользователем s и вызов этого тривиального кода внезапно запускают сериализацию?


person sharptooth    schedule 27.06.2011    source источник
comment
вы не изменили управление сеансом с inproc на sql?   -  person Daniel Powell    schedule 27.06.2011
comment
@ Дэниел Пауэлл: Без понятия. Как это проверить и что это?   -  person sharptooth    schedule 27.06.2011
comment
должно быть в вашей веб-конфигурации, как хранятся сеансы, inproc в основном находится в памяти локального сервера, и вы можете уйти от вещей, которые не сериализуются, когда он настроен на sql, все, что хранится в сеансе, должно быть сериализовано msdn.microsoft.com/en-us/library/ms972429.aspx   -  person Daniel Powell    schedule 27.06.2011
comment
Делаете ли вы что-нибудь с событиями, которые могут повлиять на это? Самая большая причина неожиданных данных через BinaryFormatter — это события.   -  person Marc Gravell    schedule 27.06.2011
comment
@Marc Gravell: Наверное, я вообще ничего не делаю.   -  person sharptooth    schedule 27.06.2011


Ответы (3)


Будьте осторожны с этим ответом, так как я не совсем уверен, что он хороший.

Во-первых, я предполагаю, что вы не настроили что-то вроде управления сеансами SQL, и единственное, что вы изменили, — это пользователя, под которым работает IIS.

Вы наблюдаете два явления:

  1. Сериализация объекта, который не должен быть сериализован
  2. Загрузка вашей сборки AppDomain, который еще не загрузил ее.

Поскольку ваш домен приложения уже загрузил сборку, можно с уверенностью предположить, что исключение вызвано другим доменом приложения. Если он выдается другим доменом приложения, вероятно, это связано с тем, что этот домен приложения пытается десериализовать ваш пользовательский объект. (Он был сериализован до того, как это продемонстрирует другое исключение.)

В ПОРЯДКЕ. Теперь, даже если IIS работает под локальным пользователем, ролевая среда не работает. Эта служба устанавливается вместе с ОС Azure, вы не можете выбрать пользователя, под которым она работает (на самом деле вы, вероятно, могли бы, но я бы не стал)

Я думаю, что для получения информации от RoleEnvironnement среда выполнения Azure может использовать два пути кода:

  1. Один, если служба IIS и среда выполнения работают под одним и тем же пользователем, что не требует переключения домена приложения.
  2. другой, если служба IIS и среда выполнения не используют общего пользователя, под которым они работают. В этом случае среда выполнения требует этого, так как два пользователя не имеют одинаковых прав.

В заключение я, конечно, не знаю, почему среда выполнения Azure хочет перемещать вашего пользователя между разными доменами приложений, но, вероятно, она именно это и делает.

person Eilistraee    schedule 27.06.2011

ИЗМЕНИТЬ Перечитывая ваш вопрос, я не уверен, что это проблема. Я оставляю это здесь, потому что я потратил 5 минут на его написание, и это полезная информация :) Если вы пишете веб-приложения, вам нужно знать о состоянии сеанса и ваших вариантах хранения!


Как говорит Даниэль Пауэлл, весьма вероятно, что вы храните экземпляр своего объекта в состоянии сеанса.

Приложения ASP.NET имеют 3 стандартных режима хранения состояния сеанса. InProc (в процессе) сохраняет его в памяти, поэтому сериализация не требуется. StateServer или SqlServer попытается сериализовать состояние сеанса либо на сервер состояний ASP.NET, либо на сервер SQL соответственно.

Чтобы убедиться, что проблема именно в этом, вам нужно проверить, что такое атрибут mode элемента sessionState в файле web.config.

<sessionState mode="InProc|SqlServer|StateServer" />

Если вы используете SQL Server или State Server, ваше приложение будет сериализовать все состояние сеанса в конце каждого запроса. Здесь у вас есть несколько вариантов:

  1. Измените состояние сеанса на InProc. Это предотвратит сериализацию, но вы не сможете использовать среду с балансировкой нагрузки. Кроме того, если ваше приложение перезапустится, все пользователи потеряют свою сессию (поскольку она хранится в памяти).

  2. Прекратите помещать этот объект в Session. Если вам не нужно сохранять этот объект в сеансе, не делайте этого! Проблема решена.

  3. Сделайте объект и любые его дочерние элементы сериализуемыми, реализуя ISerializable. Это будет невозможно, если объект использует «живые» элементы, такие как соединения с базой данных и т. д.

person RB.    schedule 27.06.2011

Связано ли это со следующей ошибкой подключения:

https://connect.microsoft.com/VisualStudio/feedback/details/712500/cant-use-appdomains-inside-wcf-call-methods

person XIU    schedule 08.12.2011