为什么在生成服务引用时,s:date 类型的 XSD 元素会变成字符串?

发布于 2024-09-07 22:50:46 字数 966 浏览 3 评论 0原文

我正在尝试从 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;
}

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

I'm trying to create a new Service Reference from a WSDL and all of the properties I expect to be DateTime instead of string.

For example, this xsd definition for Contact:

<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;
}

If i create a web project and add it as a Web Reference instead of a Service Reference, it correctly becomes a DateTime. I assume that has something to do with the way wsdl.exe and svcutil.exe work behind the scenes, but regardless, I'm stuck on trying to figure out how to correctly get Visual Studio to recognize that this property should be a DateTime.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

毁梦 2024-09-14 22:50:46

这些问题中有一些很好的信息:如何生成 xs:Date in WCF OperationContract 参数.NET 3.5 中日期时间序列化的最佳实践

正如 Alex 在对该问题的评论中所述,WCF 不支持 xs:date 类型。不过,也许更准确的说法是默认的 DataContractSerializer 不支持该类型,而上述问题表明 XmlSerializer 可以处理它。

请参阅此链接 用于将 DataContractSerializerXmlSerializer 进行比较。

如果我运行:

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();

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

编辑:

就可为空属性而言,此问题中有一些很好的信息:svcutil.exe - 生成的代理不允许可为空字段

要在生成的代理类中获取可为空的属性,需要设置 nillable 字段在 WSDL 中。所以像这样:

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

会生成一个名为 public System.Nullable的属性代理类中的 SomeProperty

但是,在您的情况下,您可以使用 SomePropertySpecified 属性来指示该属性是否存在。当您拥有 minOccurs="0" 时,就会生成这些类型的属性。

在日期格式方面我不确定。 xs:date 值旨在为 yyyy-mm-dd 以及可选时区信息 (w3.org)。如果 Oracle 期望日期采用不同的格式,那么我想知道它们怎么可能是 xs:date 值。

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

编辑2:

我有点不清楚“日期必须采用数据库格式”到底是什么。 Oracle 文档中的意思。如果类型是 xs:date ,那么将它们序列化为数据库格式肯定意味着它不再是 xs:date

尽管如此,您在这方面仍然可以尝试一些方法:

您可能需要简单地尝试发送一些查询到网络服务来了解该日期业务如何影响事物。

您确定那些 *IsSpecified 参数不存在吗?以上面的 Contact 类为例,BirthDate 属性上的 minOccurs=0 将给出 Contact 类一个名为 BirthDateIsSpecified 的额外属性。

There is some good info in these questions: How to generate xs:Date in WCF OperationContract parameter and Best practices for DateTime serialization in .NET 3.5.

As Alex states in his comment to the question, WCF does not support xs:date types. However, it is perhaps more accurate to say that the default DataContractSerializer does not support that type, while the above questions indicate that the XmlSerializer can handle it.

See this link for a DataContractSerializer against XmlSerializer comparison.

If I run:

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

Then a WSDL fragment like this:

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

Has this class generated:

/// <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;
        }
    }
}

That svcutil invocation produces two files: Service1.cs and output.config. If I include the code file in the project and add the system.serviceModel bits into the configuration file (i.e., web.config or app.config) I can then call the service as normal. For example:

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

This approach is not without disadvantages. The Service1.cs file is markedly different if generated without the /ser:XmlSerializer parameter, where you will get additional classes such as WebMethodNameRequest, WebMethodNameRequestBody, WebMethodNameReponse, WebMethodNameReponseBody and so on. If these classes are important in your interactions with the service, my approach may not work for you.

Edit:

In terms of nullable properties, there is some good information in this question: svcutil.exe - Proxy generated not allowing for nullable fields

To get a property nullable in the generated proxy class, the nillable field needs to be set in the WSDL. So something like this:

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

Would generate a property called public System.Nullable<System.DateTime> SomeProperty in the proxy class.

However in your case you can use the SomePropertySpecified property to indicate the presence or absence of the property. These kinds of properties are generated when you have minOccurs="0".

In terms of date formatting I'm not sure. xs:date values are intended to be yyyy-mm-dd with optional timezone information (w3.org). If Oracle is expecting dates in a different format then I wonder how they can be xs:date values at all.

Is there any documentation or other information you can provide regarding the service you are trying to consume?

Edit 2:

I am a little unclear on exactly what "Dates must be in the database format." means in the Oracle docs. If the type is an xs:date then serializing them to the database format would surely mean that it was no longer an xs:date?

Still, there are some things you try in that regard:

You may need to simply experiment sending a few queries to the web service to see just how this date business affects things.

Are you sure those *IsSpecified parameters aren't there? To use my Contact class above as the example, minOccurs=0 on the BirthDate property would give the Contact class an extra property called BirthDateIsSpecified.

国产ˉ祖宗 2024-09-14 22:50:46

虽然我相信 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() );

Although I believe nick_w's answer covers the question quite well (and I'm awarding him the bounty), I'm providing the solution I'm going to use in my specific case, where just using XmlSerializer isn't enough. In the end, I think I'm going to go with an extension that converts DateTime objects to string, using a custom format specifier.

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() );
许仙没带伞 2024-09-14 22:50:46

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

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

While this is not a real solution, I think that it may work as a workaround. It is dirty and ugly, and I know that, but it may be better than having String in your code.

Since your own classes (like Address) are properly processed, you could build a simple wrapper around Date class that you would include in your project and schema. The class would have only a Date property or a field and a getter to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文