Странный 64/32-разрядный идентификатор GUID в IIS7
Одна из моих команд недавно встретила интересный глюк в матрице. Если кто-нибудь сможет объяснить это, это будет здорово. Возможно, это сложно объяснить, так что несите меня.
Мы создаем приложение ASP.Net. В нем мы имеем простую инструкцию "if".
Guid adminId = Guid.Empty;
if (mRoles.Contains("Admin"))
{
adminId = mUserId;
}
(где mRoles - это список и содержит "Admin" )
Это работает так, как ожидалось (например, adminID назначается mUserId). Однако при переписывании использовать тернарный оператор ниже этого нет! (adminID назначается Guid Empty)!
Guid adminId = mRoles.Contains("Admin") ? mUserId : Guid.Empty;
Разработчик, который обнаружил это, находится на 64-битной машине (IIS7/64-разрядная перспектива), и если он изменит свои настройки в IIS следующим образом...
В разделе "Пул приложений по умолчанию" > "Дополнительные настройки" установите флажок "Включить 32-разрядные приложения". Теперь оба утверждения работают!
Мы считаем, что это возможно сделать с тем, что Guid является структурой, а не классом, и что значение каким-то образом смещается под 64-разрядный процесс.
Я подозреваю, что проблема подобна этой...
http://www.mail-archive.com/[email protected]/msg00164.html
Это может объяснить, почему работает первый простой оператор if. (поскольку создание переменной adminId возможно создание указателя, а тернарный оператор - нет?)
Если кто-нибудь может пролить свет на это, это будет здорово.
Это ошибка совместимости? или наше непонимание объединения трехмерных операторов и структур?
Спасибо.
UPDATE
Объедините простое приложение и не сможете воспроизвести его в совершенно новом проекте, поэтому оно должно быть чем-то иным, чем GUID.
//Работает (назначает mUserId для adminId)
Guid adminId = true ? mUserId : Guid.Empty;
//Не работает (даже если t == true!!!!???)
bool t = (mRoles.Contains("TenantAdmin");
Guid adminId = t ? mUserId : Guid.Empty;
Думаю, мы вернемся к чертежной доске. Спасибо всем за вашу помощь, и если мы получим еще больше, я отправлю обратно сюда снова.
Единственное, что, возможно, было не слишком ясным, это то, что mRoles не является строкой Generic List of Type. Это строка [], а метод Contains() - метод расширения LINQs, если это имеет какое-то значение, но не может понять, почему: -?
ОБНОВЛЕНИЕ 2
Мы посмотрели на IL, и это правильно (и теперь работает с перерывами!). Мы обнаружили, что, когда пул приложений по умолчанию загружает больше приложений, он снова начинает сбой. Единственное, о чем мы можем думать, это то, что некоторые из этих других приложений могут содержать какой-то неуправляемый код, который каким-то образом мешает нашему приложению, возможно ли это?
Ответы
Ответ 1
Кажется, это ошибка в IIS и кусок неуправляемого кода в другом запуске приложения в том же пуле приложений. На данный момент мы работаем над этим, и подпишем его с помощью Microsoft через наше партнерство. Когда он будет решен, я отправлю сюда, чтобы вы знали.
Спасибо всем за вашу помощь.
Ответ 2
Пожалуйста, попробуйте скобки вокруг вашего тернарного оператора, если вы этого еще не сделали.
У нас была аналогичная проблема, в которой код вроде вашего:
Guid adminId = t ? mUserId : Guid.Empty;
был скомпилирован в неправильном порядке:
(Guid adminId = t) ? mUserId : Guid.Empty;
Добавление скобок для указания исправления:
Guid adminId = (t ? mUserId : Guid.Empty);
Я понял, что он делает, глядя на скомпилированный код с .NET Reflector.
Ответ 3
Может быть, это поможет конкретно сказать оператору присваивания, что возвращение от тернарного оператора Guid?
Guid adminId = (Guid)(mRoles.Contains("Admin") ? mUserId : Guid.Empty);
Просто дикая догадка...
Ответ 4
просто интересно, какой тип 64-битной машины считает mUserId? Предположительно, не руководство.
Ответ 5
Я не уверен, но я думаю, что при использовании теневой операции оба исполнения должны выполняться, но с GUID это может привести к тому, что два GUID будут оцениваться как.
Ответ 6
Вы пробовали следующее:
Guid adminId = mRoles.Contains("Admin") ? (Guid)mUserId : Guid.Empty;
Любопытно, если по какой-либо причине mUserId внутренне распознан как другой тип в 64-битной операционной системе, и если бы явное литье помогло бы. Возможно также следующее:
Guid adminId = mRoles.Contains("Admin") ? new Guid(mUserId.ToByteArray()) : Guid.Empty;