4

我正在尝试从 WSDL 和我希望是 DateTime 而不是字符串的所有属性创建一个新的服务引用。

例如,Contact 的这个 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;
}

如果我创建一个 Web 项目并将其添加为 Web 引用而不是服务引用,它会正确地变为 DateTime。我认为这与 wsdl.exe 和 svcutil.exe 在幕后工作的方式有关,但无论如何,我一直在试图弄清楚如何正确让 Visual Studio 识别该属性应该是 DateTime。

4

3 回答 3

5

这些问题中有一些很好的信息:How to generate xs:Date in WCF OperationContract parameterBest practice for DateTime serialization in .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.csoutput.config. 如果我在项目中包含代码文件并将这些system.serviceModel位添加到配置文件(即 web.config 或 app.config)中,我就可以正常调用该服务。例如:

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

这种方法并非没有缺点。如果在没有参数的情况下生成该文件,则该Service1.cs文件明显不同/ser:XmlSerializer,您将在其中获得其他类,例如WebMethodNameRequestWebMethodNameRequestBodyWebMethodNameReponseWebMethodNameReponseBody。如果这些类在您与服务的交互中很重要,那么我的方法可能不适合您。

编辑:

在可空属性方面,这个问题中有一些很好的信息:svcutil.exe - Proxy generated not allowed for nullable fields

要在生成的代理类中获取可为空的属性,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 ) 的 yyyy-mm-dd。如果 Oracle 期望日期采用不同的格式,那么我想知道它们是如何成为xs:date值的。

您是否可以提供有关您尝试使用的服务的任何文档或其他信息?

编辑2:

我不太清楚“日期必须是数据库格式”的确切含义。在 Oracle 文档中表示。如果类型是 anxs:date然后将它们序列化为数据库格式肯定意味着它不再是xs:date?

尽管如此,在这方面您还是会尝试一些事情:

您可能需要简单地尝试向 Web 服务发送一些查询,以了解此日期业务如何影响事物。

你确定那些*IsSpecified参数不存在吗?以我Contact上面的类为例,minOccurs=0BirthDate属性上会给Contact类一个额外的属性,称为BirthDateIsSpecified.

于 2013-01-28T05:05:25.823 回答
1

虽然我相信 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() );
于 2013-01-31T11:15:35.247 回答
0

虽然这不是一个真正的解决方案,但我认为它可以作为一种解决方法。它又脏又丑,我知道,但它可能比在代码中包含 String 更好。

由于您自己的类(如)已正确处理,因此您可以围绕您将包含在项目和模式中的类Address构建一个简单的包装器。Date该类将只有一个Date属性或一个字段和一个 getter。

于 2013-01-25T09:51:47.770 回答