Почему элемент XSD типа s: date становится строкой при создании ссылки на службу?

Я пытаюсь создать новую ссылку на службу из 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>

The type of BirthDate is s:date, but the generated type (in Reference.cs) is a string.

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

    [OptionalField]
    private string EmailField;

    private string BirthDateField;
}

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


person Nick    schedule 29.06.2010    source источник
comment
ты когда-нибудь в этом догадывался? У меня такая же проблема.   -  person WowtaH    schedule 31.10.2011
comment
Кажется, WCF не поддерживает тип xs:date. Я назначаю вознаграждение по этому вопросу за решение.   -  person Alex    schedule 25.01.2013
comment
Я не могу исправить проблему; какая часть отмеченного ответа сработала для вас?   -  person techspider    schedule 22.04.2016


Ответы (3)


В этих вопросах есть полезная информация: Как сгенерировать xs: Date in Параметр 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 и так далее. Если эти классы важны для вашего взаимодействия со службой, мой подход может не сработать для вас.

Изменить:

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

Чтобы получить свойство, допускающее значение NULL, в сгенерированном прокси-классе, необходимо установить поле 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 значения должны быть yyyy-mm-dd с дополнительной информацией о часовом поясе (w3.org). Если Oracle ожидает даты в другом формате, мне интересно, как они вообще могут быть xs:date значениями.

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

Изменить 2:

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

Тем не менее, вы можете попробовать кое-что в этом отношении:

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

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

person nick_w    schedule 28.01.2013
comment
Спасибо, это действительно создает поле DateTime. Я был немного удивлен тем, что он не генерирует Nullable<DateTime> для параметров метода с minOccurs="0". Есть идеи, как с этим справиться? - person Alex; 29.01.2013
comment
Кроме того, я пытаюсь использовать службу Oracle, и Oracle, похоже, ожидает другого формата для xs:date параметров - dd-MMM-yyyy вместо yyyy-MM-dd. Я считаю, что здесь виноват Oracle, но есть ли способ принудительно изменить формат дат в клиенте? - person Alex; 29.01.2013
comment
Спасибо, насчет типов, допускающих значение NULL - тогда я думаю, мне нужно вызывать службу по-другому. Потому что я использую класс *PortTypeClient, а его методы не имеют свойства IsSpecified в качестве параметра. Я использую следующие службы Oracle: Собственная база данных Oracle XML Веб-службы. В таблице 33-1 указано, что даты должны быть в формате базы данных ... - person Alex; 30.01.2013
comment
*IsSpecified параметров там точно нет. Возможно, проблема в том, что я вызываю хранимые процедуры, которые принимают параметры простого типа. Итак, никаких объектов нет. Просто функции с параметрами простого типа (целые числа, строки, даты и т. Д.). - person Alex; 30.01.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() );
person Alex    schedule 31.01.2013

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

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

person Dariusz    schedule 25.01.2013
comment
Предположим, что схема (WSDL) не может быть изменена. Меня интересует чисто клиентское решение. - person Alex; 25.01.2013