none
Вопросы к XmlSerializer на платформе .Net Core 2.0 (Standard 2.0) RRS feed

  • Вопрос

  • Этот вопрос относится не только к вебу, а в принципе к самой платформе...

    В общем предыстория. Разрабатывается asp net core mvc приложение (.net core 2.0). В приложении активно используется сериализация XML, для чего были дополнительно установлены сборки System.Xml.XmlSerializer v 4.3.0 и System.Xml.XmlDocument v 4.3.0.

    Столкнулся с такой ситуацией: для работы приложения были сгенерированы классы с помощью утилиты xsd.exe. По началу было все нормально. Я создавал экземпляры некоторых сгенерированных классов, сереализовал/десериализовал их. НО!!! Попытался я создать XmlSerializer для одного класса:

    [System.Xml.Serialization.XmlRootAttribute("RequestMessage", Namespace="http://roskazna.ru/gisgmp/xsd/116/Message", IsNullable=false)]
    public partial class RequestMessageType {
        
        private object itemField;
    
        [System.Xml.Serialization.XmlElementAttribute("ChargeCreationRequest", typeof(ChargeCreationRequestType), Namespace="http://roskazna.ru/gisgmp/xsd/116/MessageData")]
        [System.Xml.Serialization.XmlElementAttribute("DoAcknowledgmentRequest", typeof(DoAcknowledgmentRequestType), Namespace="http://roskazna.ru/gisgmp/xsd/116/MessageData")]
        [System.Xml.Serialization.XmlElementAttribute("ExportRequest", typeof(DataRequest), Namespace="http://roskazna.ru/gisgmp/xsd/116/MessageData")]
        [System.Xml.Serialization.XmlElementAttribute("ImportCertificateRequest", typeof(ImportCertificateRequestType), Namespace="http://roskazna.ru/gisgmp/xsd/116/MessageData")]
        [System.Xml.Serialization.XmlElementAttribute("ImportRequest", typeof(ImportRequestType), Namespace="http://roskazna.ru/gisgmp/xsd/116/MessageData")]
        [System.Xml.Serialization.XmlElementAttribute("PackageStatusRequest", typeof(PackageStatusRequestType), Namespace="http://roskazna.ru/gisgmp/xsd/116/MessageData")]
        public object Item {
            get {
                return this.itemField;
            }
            set {
                this.itemField = value;
            }
        }
    }


    И выходит такая вот ошибка:

    System.PlatformNotSupportedException: "Compiling JScript/CSharp scripts is not supported".

    Ничего не могу с этим поделать... Погуглил, нашел вот такое: ссылка на форум. На этой странице рассказывается, что это какой то баг XmlSerializer в реализации под .net core... Написан способ решения данного бага. Но мне этот способ не помогает! И никак не могу решить эту проблему...

    Сразу скажу,что если убрать свойство Item у данного класса (у него есть и другие свойства, я росто не указывал их, для экономии места), то XmlSerializer создается без каких либо ошибок...

    Может кто подскажет, что с этим делать???

    18 сентября 2017 г. 8:21

Ответы

  • Спасибо большое за помощь! На самом деле виной всему оказалась xsd.exe!

    Сейчас поясню! В общем, так и не найдя решения, я решил сделать так, как советовали мне Вы... Я изначально не хотел так делать, уж не знаю почему... Может быть потому, что мне не казалось это правильным решением проблемы... Ну так вот, сделав все так, как Вы предлагали, я получил все ту же ошибку. Тогда я начал смотреть каждые из тех классов, которые могут помещаться в поле Item, их свойства, свойства классов их свойств. В общем наткнулся на один класс, у которого тоже есть свойство Item и с помощью атрибутов указывается, что это свойство может принимать одно из трех возможных значений классов (которые являются по сути массивами). И заметил, что само свойство Item имеет в данном случае не тип object, как должно быть, а тип одного из тех значений, которое оно может принимать:

    [System.Xml.Serialization.XmlElementAttribute("ChargesIdentifiers", typeof(DataRequestFilterConditionsChargesIdentifiers))]
    [System.Xml.Serialization.XmlElementAttribute("Payers", typeof(DataRequestFilterConditionsPayers))]
    [System.Xml.Serialization.XmlElementAttribute("PaymentsIdentifiers", typeof(DataRequestFilterConditionsPaymentsIdentifiers))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
    public DataRequestFilterConditionsChargesIdentifiers Item {
        get {
            return this.itemField;
        }
        set {
            this.itemField = value;
        }
    }

    Вот в этом и была ошибка! Я исправил тип свойства Item на object и сериализатор теперь создается без проблем!

    Странно только, что сама ошибка при создании сериализатора выглядела мягко говоря странно... С тем же успехом они бы могли и просто выдать Exception("Oops") :)

    В общем нужно следить еще и за самими сгенерированными классами...

    19 сентября 2017 г. 12:40

Все ответы

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

    This posting is provided "AS IS" with no warranties, and confers no rights.

    18 сентября 2017 г. 8:45
    Модератор
  • Так делать нельзя... Такой формат данных диктуется поставщиком предоставления сведений при информационном взаимодействии...

    Просто в .NET Framework 4.5 это работает (XmlSerializer создается, сериализует/десериализует данные), а в .NET Core 2.0 нет, выдается ошибочка...

    19 сентября 2017 г. 6:07
  • Так делать можно. Формат данных (схема XML) при этом не изменится. Что бы было понятнее:

    public ChargeCreationRequestType ChargeCreationRequest  {
            get {
                return this.itemField as ChargeCreationRequestType;
            }
            set {
                this.itemField = value;
            }
    }

    Можно добавить атрибуты если требуется, в частности чтоб не сохранялись значения null.

    И так для всех типов. На Item вешаем [XmlIgnore]

    Работает это так:

    При записи все свойства кроме одного будут иметь значения null и в XML не запишутся. Одно из значений создаст элемент с именем свойства, например ChargeCreationRequest, так же как предписано свойством Item.

    При загрузке XML элемент, скажем ChargeCreationRequest, будет загружен в свойство с тем же именем. Что установит значение Item.

    T.e. получим все то же самое, только другими методами.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    19 сентября 2017 г. 6:56
    Модератор
  • Тогда, почему же нет таких проблем в .NET Framework 4.5???
    19 сентября 2017 г. 7:35
  • Тогда, почему же нет таких проблем в .NET Framework 4.5???

    Видимо потому что в этой версии нет такой ошибки и данная конструкция работает корректно. А в "молодом" .Net Core есть какая то ошибка и данная функция не работает.  


    This posting is provided "AS IS" with no warranties, and confers no rights.

    19 сентября 2017 г. 7:53
    Модератор
  • Спасибо большое за помощь! На самом деле виной всему оказалась xsd.exe!

    Сейчас поясню! В общем, так и не найдя решения, я решил сделать так, как советовали мне Вы... Я изначально не хотел так делать, уж не знаю почему... Может быть потому, что мне не казалось это правильным решением проблемы... Ну так вот, сделав все так, как Вы предлагали, я получил все ту же ошибку. Тогда я начал смотреть каждые из тех классов, которые могут помещаться в поле Item, их свойства, свойства классов их свойств. В общем наткнулся на один класс, у которого тоже есть свойство Item и с помощью атрибутов указывается, что это свойство может принимать одно из трех возможных значений классов (которые являются по сути массивами). И заметил, что само свойство Item имеет в данном случае не тип object, как должно быть, а тип одного из тех значений, которое оно может принимать:

    [System.Xml.Serialization.XmlElementAttribute("ChargesIdentifiers", typeof(DataRequestFilterConditionsChargesIdentifiers))]
    [System.Xml.Serialization.XmlElementAttribute("Payers", typeof(DataRequestFilterConditionsPayers))]
    [System.Xml.Serialization.XmlElementAttribute("PaymentsIdentifiers", typeof(DataRequestFilterConditionsPaymentsIdentifiers))]
    [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")]
    public DataRequestFilterConditionsChargesIdentifiers Item {
        get {
            return this.itemField;
        }
        set {
            this.itemField = value;
        }
    }

    Вот в этом и была ошибка! Я исправил тип свойства Item на object и сериализатор теперь создается без проблем!

    Странно только, что сама ошибка при создании сериализатора выглядела мягко говоря странно... С тем же успехом они бы могли и просто выдать Exception("Oops") :)

    В общем нужно следить еще и за самими сгенерированными классами...

    19 сентября 2017 г. 12:40