[DataContract]
public abstract class BusMessage
{
[DataMember(Name = "encoding")]
public string Encoding { get; set; }
[DataMember(Name = "type")]
public virtual MessageType Type
{
get { return _type; }
private set { _type = value; }
}
}
[DataContract]
public class BusTextMessage : BusMessage
{
[DataMember(Name = "type")]
public override MessageType Type
{
get { return MessageType.Text; }
}
[DataMember(Name = "payload")]
public string Payload { get; set; }
}
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface ICommunicationService
{
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/SendMessage")]
string SendMessage(BusMessage jsonMessage);
}
}
当我使用Postman chrome发送请求时,如果我不将__type添加为“__type”:“BusTextMessage:#TransportModels.Messages”,该对象将无法正确序列化,因为它不知道如何实例化BusMessage类。我已经定义了Type属性,它定义了消息的类型。是否有可能覆盖__type行为,例如根据Type属性返回正确的实现?我不希望任何人手动将__type信息放到json中,因此在反序列化之前是否有选项可以编辑json,如果它不存在则手动将__type属性添加到json中?例如,我想做这样的事情:
public void BeforeDeserialization(string json)
{
if(json doesnt include __type)
{
if(json property type(my property) is MessageType.Text)
add to json "__type":"BusTextMessage:#TransportModels.Messages"
///etc
}
}
我发现了这种方法,但似乎没有用:
[OnDeserializing()]
internal void OnDeserializingMethod(StreamingContext context)
{
}
答案 0 :(得分:0)
我认为您需要将KnownType属性添加到BusMessage类。
[DataContract]
[KnownType(typeof(BusTextMessage)]
public class BusMessage
{
.
.
.
}
答案 1 :(得分:0)
这是我发现的最快的解决方案。我配置MessageInspector并处理AfterReceiveRequest。然后我检查消息格式(XML,JSON)。如果它是XML(例如从用C#编写的任何WCF客户端发送,WCF配置为使用XML发送所有内容),那么我接受该消息,因为字段__type将由WCF机制自动插入。否则我检查它是否是JSON,例如从外部客户端发送。如果它不包含属性" __ type"我检查我的属性Type并生成正确的__type值。例如,如果我的Type等于Text,我添加__type属性BusTextMessage:#TransportModels.Messages并将其插入JSON,然后重新创建消息。我无法找到更快更容易的解决方案,而且它似乎正在发挥作用。处理AfterReceiveRequest我在http://code.msdn.microsoft.com/windowsdesktop/WCF-REST-Message-Inspector-c4b6790b找到了。
public class MessageTypeInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
RecreateMessage(ref request);
return null;
}
}
private void RecreateMessage(ref Message message)
{
WebContentFormat messageFormat = this.GetMessageContentFormat(message);
var ms = new MemoryStream();
XmlDictionaryWriter writer = null;
switch (messageFormat)
{
case WebContentFormat.Default:
case WebContentFormat.Xml:
writer = XmlDictionaryWriter.CreateTextWriter(ms);
break;
case WebContentFormat.Json:
writer = JsonReaderWriterFactory.CreateJsonWriter(ms);
break;
case WebContentFormat.Raw:
this.ReadRawBody(ref message);
break;
}
message.WriteMessage(writer);
writer.Flush();
string messageBody = Encoding.UTF8.GetString(ms.ToArray());
if (messageFormat == WebContentFormat.Json && !messageBody.Contains("__type"))
messageBody = AddTypeField(messageBody);
ms.Position = 0;
ms = new MemoryStream(Encoding.UTF8.GetBytes(messageBody));
XmlDictionaryReader reader = messageFormat == WebContentFormat.Json ?
JsonReaderWriterFactory.CreateJsonReader(ms, XmlDictionaryReaderQuotas.Max) :
XmlDictionaryReader.CreateTextReader(ms, XmlDictionaryReaderQuotas.Max);
Message newMessage = Message.CreateMessage(reader, int.MaxValue, message.Version);
newMessage.Properties.CopyProperties(message.Properties);
message = newMessage;
}
private WebContentFormat GetMessageContentFormat(Message message)
{
WebContentFormat format = WebContentFormat.Default;
if (message.Properties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
WebBodyFormatMessageProperty bodyFormat;
bodyFormat = (WebBodyFormatMessageProperty)message.Properties[WebBodyFormatMessageProperty.Name];
format = bodyFormat.Format;
}
return format;
}
private string AddTypeField(string jsonReply)
{
var typeRegex = new Regex("\"type\":(?<number>[0-9]*)");
Match match = typeRegex.Match(jsonReply);
if (match.Success)
{
int number = Int32.Parse(match.Groups["number"].Value);
var type = (MessageType)number;
var nameFormat = string.Format("Bus{0}Message", type);
string format = string.Format("\"__type\":\"{0}:#TransportModels.Messages\"", nameFormat);
jsonReply = "{" + string.Format("{0},{1}", format, jsonReply.Substring(1));
return jsonReply;
}
else
{
throw new Exception("Wrong message type.");
}
}