默认情况下,WCF 使用 DataContractJsonSerializer 将数据序列化为 JSON。不幸的是,这个序列化程序的日期格式很难被人脑解析。
"DateTime": "\/Date(1535481994306+0200)\/"
要覆盖此行为,我们需要编写自定义 IDispatchMessageFormatter。该类将接收所有应返回给请求者的数据,并根据我们的需要进行更改。
要实现端点中的操作,请添加自定义格式化程序 - ClientJsonDateFormatter:
ServiceHost host=new ServiceHost(typeof(CustomService));
host.AddServiceEndpoint(typeof(ICustomContract), new WebHttpBinding(), Consts.WebHttpAddress);
foreach (var endpoint in host.Description.Endpoints)
{
if (endpoint.Address.Uri.Scheme.StartsWith("http"))
{
foreach (var operation in endpoint.Contract.Operations)
{
operation.OperationBehaviors.Add(new ClientJsonDateFormatter());
}
endpoint.Behaviors.Add(new WebHttpBehavior());
}
}
ClientJsonDateFormatter 是一个简单的类,它只应用格式化程序 ClientJsonDateFormatter
public class ClientJsonDateFormatter : IOperationBehavior
{
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { }
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Formatter = new ResponseJsonFormatter(operationDescription);
}
public void Validate(OperationDescription operationDescription) { }
}
在格式化程序中,我们使用更改后的序列化器进行输入和序列化:
public class ResponseJsonFormatter : IDispatchMessageFormatter
{
OperationDescription Operation;
public ResponseJsonFormatter(OperationDescription operation)
{
this.Operation = operation;
}
public void DeserializeRequest(Message message, object[] parameters)
{
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
string json=Newtonsoft.Json.JsonConvert.SerializeObject(result);
byte[] bytes = Encoding.UTF8.GetBytes(json);
Message replyMessage = Message.CreateMessage(messageVersion, Operation.Messages[1].Action, new RawDataWriter(bytes));
replyMessage.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw));
return replyMessage;
}
}
为了向客户端发送信息,我们需要数据写入器 - RawDataWriter。它的实现很简单:
class RawDataWriter : BodyWriter
{
byte[] data;
public RawDataWriter(byte[] data)
: base(true)
{
this.data = data;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("Binary");
writer.WriteBase64(data, 0, data.Length);
writer.WriteEndElement();
}
}
应用所有代码会以更友好的格式返回日期:
"DateTime":"2018-08-28T20:56:48.6411976+02:00"
为了在实践中展示它,我在 github 分支 DateTimeFormatter 中创建了示例。
请检查this 答案,因为您很可能也需要它。