我得到了一个wsdl,我必须按照它的规范创建一个web服务;我正在使用visual studio 2010。除此之外,还有这种复杂类型的定义:
<xsd:complexType name="Person">
<xsd:sequence>
<xsd:element name="surname" type="xsd:string"/>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="birthDate" nillable="true" type="xsd:dateTime"/>
</xsd:sequence>
</xsd:complexType>
使用VS,我得到了以下cs(我不记得我是怎么做的,但我遵循了网上的说明):
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://XXX/Submitter/")]
public partial class Person {
private string surnameField;
private string nameField;
private System.Nullable<System.DateTime> birthDateField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string surname {
get {
return this.surnameField;
}
set {
this.surnameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
public System.Nullable<System.DateTime> birthDate {
get {
return this.birthDateField;
}
set {
this.birthDateField = value;
}
}
一切都是正确的:它编译、运行并给出预期的结果;唯一的问题是,给我wsdl的另一方在调用我的web服务时,希望将出生日期字段作为
2013-02-15T17:28:00+01:00
使用时区信息,而他们收到的结果就像
2015-11-17T18:30:11
没有时区。
我的问题是,我有一个DateTime?
类型,这就是我传递给从类实例化的对象的类型;我应该重写序列化还是有其他最常见的解决方案?感谢
不幸的是,XSD与.NET在SOAP web服务中支持的内容严重不匹配。
.NET对于这类信息只有两种类型——DateTime
和DateTimeOffset
。从技术上讲,最好将xs:datetime
映射到DateTimeOffset
,但这不是它的工作方式。相反,xs:datetime
被映射到DateTime
,并且在很大程度上依赖于值的Kind
属性来确定它的序列化方式。
-
当
DateTime.Kind
是DateTimeKind.Unspecified
时,不传递偏移信息。 -
当
DateTime.Kind
为DateTimeKind.Utc
时,则通过Z
,与+00:00
相同。 -
当
DateTime.Kind
是DateTimeKind.Local
时,则通过与给定日期相对应的本地偏移。
您可以使用DateTime.SpecifyKind
应用种类,或者如果您想在过程中转换值,可以使用.ToUniversalTime()
或.ToLocalTime()
。或者,如果您知道这些值属于特定时区,则可以使用TimeZoneInfo
对象的转换方法。只要得到的种类是Unspecified
以外的任何东西,它就会包括偏移。
不幸的是,没有指定任意偏移的选项。这将需要DateTimeOffset
类型,而SOAP服务不支持这种类型。
另外,考虑一下xs:datetime
类型实际上是错误的出生日期类型。它应该使用xs:date
,只是一个日期,例如"2013-02-15"
。目前在.NET中还没有支持这一点的类型,尽管很快就会有一个类型,如corefxlab包中System.Time包中的Date
。这对类似的场景很有用,但我们是否可以返回并修复SOAP序列化程序以使用它们还有待观察。
实际上,最好的想法是不使用XML和SOAP。而是围绕JSON和REST来设计web服务。在那里你可以完全控制这样的事情。
您可能想看看Jon Skeet的答案。他提出了这样一个结构:
public struct DateTimeWithZone
{
private readonly DateTime utcDateTime;
private readonly TimeZoneInfo timeZone;
public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone)
{
utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZone);
this.timeZone = timeZone;
}
public DateTime UniversalTime { get { return utcDateTime; } }
public TimeZoneInfo TimeZone { get { return timeZone; } }
public DateTime LocalTime
{
get
{
return TimeZoneInfo.ConvertTime(utcDateTime, timeZone);
}
}
}