Почему элемент XSD типа s: date становится строкой при создании ссылки на службу? - PullRequest
4 голосов
/ 30 июня 2010

Я пытаюсь создать новую ссылку на службу из WSDL и все свойства, которые я ожидаю, будут DateTime вместо строки.

Например, это определение xsd для контакта:

<s:complexType name="Contact">
    <s:sequence>
        <s:element minOccurs="0" maxOccurs="1" name="Address" type="tns:Address" />
        <s:element minOccurs="0" maxOccurs="1" name="Email" type="s:string" />
        ...
        <s:element minOccurs="1" maxOccurs="1" name="BirthDate" type="s:date" />
</s:sequence>

Тип BirthDate - s: date, но сгенерированный тип (в Reference.cs) - строка.

internal partial class Contact : object, IExtensibleDataObject, INotifyPropertyChanged
{
    [OptionalField]
    private MembershipMgmtMediator.Address AddressField;

    [OptionalField]
    private string EmailField;

    private string BirthDateField;
}

Если я создаю веб-проект и добавляю его как веб-ссылку, а не как ссылку на службу, он корректно становится датой времени. Я предполагаю, что это как-то связано с тем, как wsdl.exe и svcutil.exe работают за кулисами, но, тем не менее, я застрял при попытке выяснить, как правильно заставить Visual Studio распознавать, что это свойство должно быть DateTime.

Ответы [ 3 ]

5 голосов
/ 28 января 2013

В этих вопросах есть полезная информация: Как создать xs: Date в WCF Параметр OperationContract и Лучшие практики для сериализации DateTime в .NET 3.5 .

Как заявляет Алекс в своем комментарии к вопросу, WCF не поддерживает xs:date типы.Однако, возможно, точнее сказать, что DataContractSerializer по умолчанию не поддерживает этот тип, в то время как приведенные выше вопросы показывают, что XmlSerializer может его обработать.

См. Эту ссылку для DataContractSerializer против XmlSerializer сравнения.

Если я запущу:

svcutil http://my_web_site?wsdl /ser:XmlSerializer /d:C:\temp

Затем фрагмент WSDL, подобный этому:

<s:complexType name="Contact">
    <s:sequence>
        <s:element minOccurs="1" maxOccurs="1" name="BirthDate" type="s:date" />
    </s:sequence>
</s:complexType>

Сгенерирован ли этот класс:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]
public partial class Contact
{

    private System.DateTime birthDateField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="date", Order=0)]
    public System.DateTime BirthDate
    {
        get
        {
            return this.birthDateField;
        }
        set
        {
            this.birthDateField = value;
        }
    }
}

При вызове svcutil создаются два файла: Service1.cs и output.config.Если я включу файл кода в проект и добавлю биты system.serviceModel в файл конфигурации (т. Е. Web.config или app.config), я смогу вызвать службу как обычно.Например:

Service1SoapClient client = new Service1SoapClient("Service1Soap");
var contact = client.GetContact();

Этот подход не лишен недостатков.Файл Service1.cs заметно отличается, если генерируется без параметра /ser:XmlSerializer, где вы получите дополнительные классы, такие как WebMethodNameRequest, WebMethodNameRequestBody, WebMethodNameReponse, WebMethodNameReponseBody и так далее.Если эти классы важны для вашего взаимодействия со службой, мой подход может не сработать для вас.

Редактировать:

С точки зрения свойств, допускающих обнуление, есть некоторые хорошиеинформация в этом вопросе: svcutil.exe - сгенерированный прокси-сервер не допускает пустые поля

Чтобы получить свойство, допускающее обнуление в сгенерированном прокси-классе, поле nillable должно быть установлено вWSDL.Итак, что-то вроде этого:

<s:element minOccurs="0" maxOccurs="1" name="SomeProperty" type="s:date" nillable="true" />

Создает свойство с именем public System.Nullable<System.DateTime> SomeProperty в прокси-классе.

Однако в вашем случае вы можете использовать свойство SomePropertySpecified, чтобы указать наличие илиотсутствие собственности.Эти типы свойств генерируются, когда у вас есть minOccurs="0".

С точки зрения форматирования даты, я не уверен.xs:date значения предназначены для гггг-мм-дд с дополнительной информацией о часовом поясе ( w3.org ).Если Oracle ожидает даты в другом формате, то мне интересно, как они вообще могут иметь значения xs:date.

Есть ли какая-либо документация или другая информация, которую вы можете предоставить относительно службы, которую вы пытаетесь использовать?

Редактировать 2:

Мне немного неясно, что именно "Даты должны быть в формате базы данных".значит в Oracle документы.Если типом является xs:date, то их сериализация в формат базы данных наверняка будет означать, что он больше не является xs:date?

Тем не менее, есть некоторые вещи, которые вы пытаетесь в этом отношении:

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

Вы уверены, что эти параметры *IsSpecified отсутствуют?Чтобы использовать мой класс Contact выше в качестве примера, minOccurs=0 для свойства BirthDate даст классу Contact дополнительное свойство с именем BirthDateIsSpecified.

.
0 голосов
/ 31 января 2013

Хотя я считаю, что ответ nick_w достаточно хорошо охватывает вопрос (и я присуждаю ему награду), я предоставляю решение, которое собираюсь использовать в моем конкретном случае, где просто использование XmlSerializer не довольно. В конце я думаю, что я собираюсь пойти с расширением, которое преобразует DateTime объекты в строку, используя специальный спецификатор формата.

public static class SoapUtils
{
    public static string ToOraDate( this DateTime? dt )
    {
        return dt != null ? dt.Value.ToString("dd-MMM-yyyy",
                                              CultureInfo.InvariantCulture) : 
    }
}

// Calling a service
someDate = DateTime.Now;
service.SomeMethod( someDate.ToOraDate() );
0 голосов
/ 25 января 2013

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

Поскольку ваши собственные классы (например, Address) обрабатываются правильно, вымог бы создать простую обертку вокруг Date класса, который вы бы включили в свой проект и схему.Класс будет иметь только свойство или поле Date и получатель к нему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...