Странная проблема 64/32-битного GUID под IIS7 - PullRequest
11 голосов
/ 27 августа 2009

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

Мы создаем приложение ASP.Net. В нем мы имеем простое утверждение «если».

Guid adminId = Guid.Empty;
if (mRoles.Contains("Admin"))
{
    adminId = mUserId;
}

(где mRoles - это список и содержит «Admin»)

Это работает так, как и ожидалось (то есть adminID назначен mUserId). Однако, когда переписано, чтобы использовать троичный оператор ниже, это не так! (adminID назначен Guid Пусто)!

Guid adminId = mRoles.Contains("Admin") ? mUserId : Guid.Empty;

Разработчик, обнаруживший это, находится на 64-битной машине (IIS7 / 64-bit Vista) и если он меняет свои настройки в IIS следующим образом ... В разделе «Пул приложений по умолчанию»> «Дополнительные параметры» установите флажок «Включить 32-разрядные приложения». Теперь оба утверждения работают!

Мы думаем, что это как-то связано, возможно, с тем фактом, что Guid - это структура, а не класс, и что значение каким-то образом смещается в 64-битном процессе.

Я подозреваю, что проблема похожа на это ... http://www.mail-archive.com/comtypes-users@lists.sourceforge.net/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 не является строкой универсального списка типов. Это строка [], а метод Contains () является методом расширения LINQ, если это имеет какое-то значение, но не могу понять, почему: -?

ОБНОВЛЕНИЕ 2

Мы посмотрели на IL, и он правильный (и теперь работает с перебоями!). Мы обнаружили, что когда пул приложений по умолчанию загружает больше приложений, он снова начинает отказывать. Единственное, о чем мы можем думать, это о том, что некоторые из этих других приложений могут содержать неуправляемый код, который как-то мешает нашему приложению, возможно ли это?

Ответы [ 6 ]

1 голос
/ 27 августа 2009

Пожалуйста, попробуйте заключить в скобки ваш троичный оператор, если вы еще этого не сделали.

У нас была похожая проблема с кодом, подобным вашему:

Guid adminId = t ? mUserId : Guid.Empty;

было скомпилировано в неправильном порядке:

(Guid adminId = t) ? mUserId : Guid.Empty;

Добавление скобок для указания исправленного порядка:

Guid adminId = (t ? mUserId : Guid.Empty);

Я понял, что он делает, посмотрев скомпилированный код с помощью .NET Reflector.

0 голосов
/ 01 сентября 2009

Это, похоже, ошибка в IIS и кусок неуправляемого кода в другом приложении, запущенном в том же пуле приложений. Мы обошли это сейчас и обсудим это с Microsoft через наше партнерство. Когда это будет решено, я отправлю сюда, чтобы сообщить вам.

Спасибо всем за помощь.

0 голосов
/ 27 августа 2009

Вы пробовали следующее:

Guid adminId = mRoles.Contains("Admin") ? (Guid)mUserId : Guid.Empty;

Просто любопытно, если по какой-либо причине mUserId внутренне распознается как другой тип в 64-битной операционной системе, и если явно приведение поможет. Следующее также может быть вариантом:

Guid adminId = mRoles.Contains("Admin") ? new Guid(mUserId.ToByteArray()) : Guid.Empty;
0 голосов
/ 27 августа 2009

Я не уверен, , но Я думаю, что при использовании тенарной операции должны выполняться обе ветви, однако с GUID это может привести к некоторой оценке двух GUID.

0 голосов
/ 27 августа 2009

просто интересно, какой тип 64-битной машины считает mUserId? Предположительно, не Guid.

0 голосов
/ 27 августа 2009

Может быть, это поможет конкретно указать оператору присваивания, что возвращение от троичного оператора - Guid?

Guid adminId = (Guid)(mRoles.Contains("Admin") ? mUserId : Guid.Empty);

Просто дикая догадка ...

...