PeopleEditor и Internet Explorer 9
Сначала я покажу как работает PeopleEditor в IE 8, а потом покажу почему он не хочет работать так же в IE 9 и что надо сделать, чтобы исправить эту ситуацию.
Как работает PeopleEditor
Когда мы вводим текст в поле и нажимаем на кнопку валидации, то происходит асинхронный вызов для валидации введенных данных на сервере в результате которого клиенту возвращается XML-документ примерно вот такого содержания:
- <Entities Append="False" Error="" DoEncodeErrorMessage="True" Separator=";" MaxHeight="3">
- <Entity Key="MSCPC11\zhukovv" DisplayText="MSCPC11\zhukovv" IsResolved="True" Description="MSCPC11\zhukovv">
- <ExtraData>
- <ArrayOfDictionaryEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <DictionaryEntry>
- <Key xsi:type="xsd:string">SPUserID</Key>
- <Value xsi:type="xsd:string">1</Value>
- </DictionaryEntry>
- <DictionaryEntry>
- <Key xsi:type="xsd:string">AccountName</Key>
- <Value xsi:type="xsd:string">MSCPC11\zhukovv</Value>
- </DictionaryEntry>
- <DictionaryEntry>
- <Key xsi:type="xsd:string">PrincipalType</Key>
- <Value xsi:type="xsd:string">User</Value>
- </DictionaryEntry>
- </ArrayOfDictionaryEntry>
- </ExtraData>
- <MultipleMatches />
- </Entity>
- </Entities>
После чего эти данные преобразуются и записываются в скрытое поле для дальнейшей передачи на сервер верифицированных данных:
Ошибка в Internet Explorer 9
Теперь мы дошли до момента, где и происходит ошибка. Если теперь отправить данные на сервер, то произойдет следующая ошибка:
Т.е. при разборе данных на сервере полученный XML не содержит определения пространства имен XSD.
Если же мы вызовем повторную валидацию данных на странице, то и в этом случае получим ошибку, но уже на стороне клиента, не доходя до асинхронного вызова. Причина та же: неверно сформирован XML-документ:
Сам асинхронный вызов происходит одинаково во всех браузерах, сервер реагирует на эти асинхронные запросы, не зависимо от браузера, их породившего. Следовательно, проблема, связанная с IE9, происходит на клиенте, а именно в момент преобразования полученных от сервера данных при асинхронном вызове на стороне клиента.
Данные в скрытом поле
Если посмотреть данные, которые в итоге записываются в скрытое поле PeopleEditor'а, то мы увидим характерное их отличие друг от друга в различных браузерах. Данные такого вида будут присутствовать в Internet Explorer 8:
- <ArrayOfDictionaryEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <DictionaryEntry>
- <Key xsi:type="xsd:string">SPUserID</Key>
- <Value xsi:type="xsd:string">1</Value>
- </DictionaryEntry>
- <DictionaryEntry>
- <Key xsi:type="xsd:string">AccountName</Key>
- <Value xsi:type="xsd:string">MSCPC11\zhukovv</Value>
- </DictionaryEntry>
- <DictionaryEntry>
- <Key xsi:type="xsd:string">PrincipalType</Key>
- <Value xsi:type="xsd:string">User</Value>
- </DictionaryEntry>
- </ArrayOfDictionaryEntry>
А в Internet Explorer 9 те же операции приведут нас к немного иному результату:
- <ArrayOfDictionaryEntry>
- <DictionaryEntry>
- <Key xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">SPUserID</Key>
- <Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">1</Value>
- </DictionaryEntry>
- <DictionaryEntry>
- <Key xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">AccountName</Key>
- <Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">MSCPC11\zhukovv</Value>
- </DictionaryEntry>
- <DictionaryEntry>
- <Key xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">PrincipalType</Key>
- <Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">User</Value>
- </DictionaryEntry>
- </ArrayOfDictionaryEntry>
EntityEditor.js
Теперь ясно, почему происходит ошибка при разборе XML-данных. Осталось понять где это происходит. Для этого нам понадобится скрипт EntityEditor.js, а именно его DEBUG-версия.
Если включить режим отладки в браузере и "проследить" процесс исполнения скрипта, то станет понятно, что виноват XmlSerializer, который не регистрирует так необходимое нам пространство XSD.
Internet Explorer 9 не умеет возвращать свойства firstChild, innerXml и прочее.
Не очень красивое решение
Я не стал искать красивое решение этой баги. Для меня было важно сделать так, чтобы все работало. Я просто добавил две строки в блок кода, в котором используется XmlSerializer:
- //delete namespace from data elements
- data = data.replace(' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type=', ' xsi:type=');
- //add namespace to root element
- data = data.replace('<ArrayOfDictionaryEntry>', '<ArrayOfDictionaryEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">');
Если кто-то знает как эти две строки заменить более красивым кодом - пишите в комментариях. Я убежден, что скоро должен выйти (или уже вышел) какой-нибудь hotfix, который решит эту проблему, когда продукт от Microsoft не работает с продуктом от Microsoft.
Вот примеры работоспособности модифицированного PeopleEditor в различных браузерах:
Уменьшаем размер EntityEditor.js
Теперь осталось сжать debug-версию файла entityeditor.debug.js. О том как это делается есть замечательная статья замечательного программиста Андрея Тарицына.
Проект, чтобы попробовать работоспособность PeopleEditor здесь.