C#测试SOAP服务时空日期元素反序列化报错的解决咨询
解决SOAP响应空DateTime标签反序列化失败的问题
给你几个无需修改服务端的解决办法,适配测试场景快速处理:
方案1:临时修改自动生成的实体类
找到服务引用自动生成的包含ExpirationDate的实体类,默认代码类似:
public System.DateTime ExpirationDate { get; set; }
改成可空类型并添加默认值处理:
private System.DateTime? _expirationDate; public System.DateTime ExpirationDate { get { return _expirationDate ?? default(System.DateTime); } set { _expirationDate = value; } }
同时给字段加上允许空节点的特性:
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true)] public System.DateTime? ExpirationDate { get; set; }
注意:后续更新服务引用时,这些修改会被覆盖,记得备份或改用方案2。
方案2:用分部类扩展(持久化方案)
自动生成的实体类都是partial类型,你可以单独创建一个同名分部类,自定义序列化逻辑:
public partial class YourContactResponseClass { [XmlIgnore] public System.DateTime ExpirationDate { get; set; } [XmlElement("ExpirationDate")] public string ExpirationDateString { get { return ExpirationDate.ToString("yyyy-MM-ddTHH:mm:ss"); } set { if (string.IsNullOrEmpty(value)) ExpirationDate = default(System.DateTime); else { System.DateTime.TryParse(value, out var date); ExpirationDate = date; } } } }
空标签传入时会自动赋值默认日期,且更新服务引用不会覆盖这段代码。
方案3:自定义XmlSerializer处理空节点
如果前两种方法不适用,可以编写自定义序列化器,在反序列化前修改空节点内容:
public class CustomXmlSerializer : XmlSerializer { protected override object Deserialize(XmlReader xmlReader, string encodingStyle) { var reader = new XmlNodeReader(HandleEmptyDateTimeNodes(xmlReader)); return base.Deserialize(reader); } private XmlDocument HandleEmptyDateTimeNodes(XmlReader xmlReader) { var doc = new XmlDocument(); doc.Load(xmlReader); foreach (XmlNode node in doc.SelectNodes("//ExpirationDate[text()='']")) { node.InnerText = default(System.DateTime).ToString("yyyy-MM-ddTHH:mm:ss"); } return doc; } }
调用服务时替换默认序列化器:
var client = new YourSoapServiceClient(); var serializer = new CustomXmlSerializer(typeof(YourAddContactResponse)); // 实现一个简单的IEndpointBehavior类注册自定义序列化器 client.Endpoint.Behaviors.Add(new CustomSerializerBehavior(serializer)); // 正常调用服务方法即可
方案4:全局使用WCF消息检查器
如果多个接口存在类似空DateTime问题,可通过消息检查器统一处理响应内容:
public class EmptyDateTimeMessageInspector : IClientMessageInspector { public object BeforeSendRequest(ref Message request, IClientChannel channel) { return null; } public void AfterReceiveReply(ref Message reply, object correlationState) { var buffer = reply.CreateBufferedCopy(int.MaxValue); var message = buffer.CreateMessage(); var xmlReader = message.GetReaderAtBodyContents(); var doc = new XmlDocument(); doc.Load(xmlReader); foreach (XmlNode node in doc.SelectNodes("//ExpirationDate[text()='']")) { node.InnerText = default(System.DateTime).ToString("yyyy-MM-ddTHH:mm:ss"); } var newMessage = Message.CreateMessage(reply.Version, reply.Headers.Action, new XmlNodeReader(doc)); newMessage.Headers.CopyHeadersFrom(reply.Headers); newMessage.Properties.CopyProperties(reply.Properties); reply = newMessage; buffer.Close(); } } public class CustomBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new EmptyDateTimeMessageInspector()); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } }
使用时给客户端添加该行为:
var client = new YourSoapServiceClient(); client.Endpoint.Behaviors.Add(new CustomBehavior());
以上方法都能让空的<ExpirationDate>标签反序列化为1/1/0001 12:00:00 AM,可根据测试场景选择最便捷的方案。
内容的提问来源于stack exchange,提问作者user2919960
相关产品推荐
相关产品推荐

