我正在尝试从WSDL创建一个新的服务引用,并且我希望所有的属性都是DateTime而不是string。
例如,联系人的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。
答案 0 :(得分:5)
这些问题有一些很好的信息:How to generate xs:Date in WCF OperationContract parameter和Best practices for DateTime serialization in .NET 3.5。
正如Alex在对该问题的评论中所述,WCF不支持xs:date
类型。但是,可能更准确地说默认DataContractSerializer
不支持该类型,而上述问题表明XmlSerializer
可以处理它。
请参阅此link,了解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
,{{1 }} 等等。如果这些类在您与服务的交互中很重要,我的方法可能对您不起作用。
修改强>
就可空属性而言,这个问题有一些很好的信息:svcutil.exe - Proxy generated not allowing for nullable fields
要在生成的代理类中获取可为空的属性,需要在WSDL中设置WebMethodNameReponseBody
字段。所以像这样:
nillable
会在代理类中生成一个名为<s:element minOccurs="0" maxOccurs="1" name="SomeProperty" type="s:date" nillable="true" />
的属性。
但是在您的情况下,您可以使用public System.Nullable<System.DateTime> SomeProperty
属性来指示属性的存在与否。当您拥有SomePropertySpecified
时会生成这些类型的属性。
就日期格式而言,我不确定。 minOccurs="0"
值应为yyyy-mm-dd,并带有可选的时区信息(w3.org)。如果Oracle期望使用不同格式的日期,那么我想知道它们是如何成为xs:date
值的。
您是否可以提供有关您尝试使用的服务的任何文档或其他信息?
编辑2:
我有点不清楚“日期必须是数据库格式”。意味着在Oracle文档中。如果类型是xs:date
,那么将它们序列化为数据库格式肯定意味着它不再是xs:date
?
不过,你在这方面还有一些尝试:
您可能只需要尝试向网络服务发送一些查询,以了解此日期业务对事物的影响。
您确定那些xs:date
参数不存在吗?要使用上面的*IsSpecified
类作为示例,Contact
属性上的minOccurs=0
会为BirthDate
类提供一个名为Contact
的额外属性。
答案 1 :(得分:0)
虽然这不是一个真正的解决方案,但我认为它可以作为一种解决方法。 它很脏又丑,我知道,但它可能比你的代码中有String更好。
由于您自己的类(如Address
)已正确处理,因此您可以构建一个包含在项目和模式中的Date
类的简单包装器。该类只有Date
属性或字段和getter。
答案 2 :(得分:0)
虽然我相信nick_w的答案很好地涵盖了这个问题(而且我正在授予他赏金),但我提供了我将在我的特定情况下使用的解决方案,其中只使用XmlSerializer
isn够了。最后,我想我将使用自定义格式说明符将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() );