可能重复:
WCF: Data contract being converted to message contract
我有一个通用的WCF代理,对于那些不熟悉的人来说,它是一个带有以下OperationContract方法的类。
[OperationContract(Action = "*", ReplyAction = "*")]
void Proxy(Message requestMessage);
最近出现的一个要求是,我需要将Message中IP类型的所有属性替换为提供请求消息的IPAddress值。
即。像,
public void Proxy(Message requestMessage)
{
try
{
// Client IP address, not currently used!
IPAddress clientIP = IPAddress.Parse((requestMessage
.Properties[RemoteEndpointMessageProperty.Name]
as RemoteEndpointMessageProperty).Address);
var factory = new ChannelFactory<IDmzProxy>("client");
IDmzProxy dmzProxy = factory.CreateChannel();
dmzProxy.Proxy(requestMessage);
factory.Close();
}
// No leakage of data! Any exceptions still return void!
catch (Exception exception)
{
Log.Fatal(
"Exception occurred on proxying the request",
exception);
return;
}
}
现在的问题是如何将requestMessage类型IPAddress中的元素设置为我检索到的clientIP?
修改1
我尝试过的事情都失败了,
requestMessage.GetBodyAttribute("ipAddress", "http://schemas.datacontract.org/2004/07/System.Net")
修改2
一种方法似乎正在取代MessageBody的XML。这对我来说似乎有些过分(WCF的重点是什么呢?)。
它也不是特别容易,因为MessageBody需要通过其属性名称而不是元素名称来匹配元素。
<ipAddress xmlns:a="http://schemas.datacontract.org/2004/07/System.Net" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:m_Address>3772007081</a:m_Address>
<a:m_Family>InterNetwork</a:m_Family>
<a:m_HashCode>0</a:m_HashCode>
<a:m_Numbers xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<b:unsignedShort>0</b:unsignedShort>
<b:unsignedShort>0</b:unsignedShort>
<b:unsignedShort>0</b:unsignedShort>
<b:unsignedShort>0</b:unsignedShort>
<b:unsignedShort>0</b:unsignedShort>
<b:unsignedShort>0</b:unsignedShort>
<b:unsignedShort>0</b:unsignedShort>
<b:unsignedShort>0</b:unsignedShort>
</a:m_Numbers>
<a:m_ScopeId>0</a:m_ScopeId>
</ipAddress>
编辑3
当然不是重复,这是大致有效的东西,还需要一些工作来替换我所追求的节点,
public void Proxy(Message requestMessage)
{
try
{
Log.Info("Received request");
requestMessage = SourceNATMessage(requestMessage);
// Check if there is an accepted action we have to catch
// If the Accepted Action is set, and the action is not the same
// then just return);)
if (!String.IsNullOrEmpty(AcceptedAction) &&
!requestMessage.Headers.Action.EndsWith(AcceptedAction))
{
Log.WarnFormat(
"Invalid request received with the following action {0}\n" +
"expected action ending with {1}",
requestMessage.Headers.Action,
AcceptedAction);
return;
}
// otherwise, let's proxy the request
Log.Debug("Proceeding with forwarding the request");
var factory = new ChannelFactory<IDmzProxy>("client");
IDmzProxy dmzProxy = factory.CreateChannel();
dmzProxy.Proxy(requestMessage);
factory.Close();
}
// No leakage of data! Any exceptions still return void!
catch (Exception exception)
{
Log.Fatal(
"Exception occurred on proxying the request",
exception);
return;
}
}
private static Message SourceNATMessage(Message message)
{
IPAddress clientIp =
IPAddress.Parse(
((RemoteEndpointMessageProperty)
message.Properties[
RemoteEndpointMessageProperty.Name]).Address);
Log.DebugFormat("Retrieved client IP address {0}", clientIp);
var stringBuilder = new StringBuilder();
XDocument document;
using (XmlWriter writer = XmlWriter.Create(stringBuilder))
{
message.WriteBody(writer);
writer.Flush();
document = XDocument.Parse(stringBuilder.ToString());
}
var deserializer = new DataContractSerializer(typeof(IPAddress));
foreach (XElement element in
from element in document.DescendantNodes().OfType<XElement>()
let aNameSpace = element.GetNamespaceOfPrefix("a")
let iNameSpace = element.GetNamespaceOfPrefix("i")
where
aNameSpace != null &&
aNameSpace.NamespaceName.Equals(SystemNetNameSpace) &&
iNameSpace != null &&
iNameSpace.NamespaceName.Equals(XmlSchemaNameSpace) &&
deserializer.ReadObject(element.CreateReader(), false) is IPAddress
select element)
{
element.ReplaceWith(new XElement(element.Name, deserializer.WriteObject());
}
return Message.CreateMessage(message.Version,
message.Headers.Action,
document.CreateReader());
}
编辑4
感兴趣的人的工作代码不能在问题结束时作为答案发布。
private static Message SourceNatMessage(Message message)
{
IPAddress clientIp =
IPAddress.Parse(
((RemoteEndpointMessageProperty)
message.Properties[
RemoteEndpointMessageProperty.Name]).Address);
Log.DebugFormat("Retrieved client IP address {0}", clientIp);
var stringBuilder = new StringBuilder();
XDocument document;
using (XmlWriter writer = XmlWriter.Create(stringBuilder))
using (XmlDictionaryWriter dictionaryWriter =
XmlDictionaryWriter.CreateDictionaryWriter(writer))
{
message.WriteBodyContents(dictionaryWriter);
dictionaryWriter.Flush();
document = XDocument.Parse(stringBuilder.ToString());
}
var deserializer = new DataContractSerializer(typeof(IPAddress));
var clientIpXml = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(clientIpXml))
{
deserializer.WriteObject(xmlWriter, clientIp);
xmlWriter.Flush();
}
var clientElement = XElement.Parse(clientIpXml.ToString());
foreach (XElement element in
from element in document.DescendantNodes().OfType<XElement>()
let aNameSpace = element.GetNamespaceOfPrefix("a")
let iNameSpace = element.GetNamespaceOfPrefix("i")
where
aNameSpace != null &&
aNameSpace.NamespaceName.Equals(SystemNetNameSpace) &&
iNameSpace != null &&
iNameSpace.NamespaceName.Equals(XmlSchemaNameSpace) &&
element.NodeType == XmlNodeType.Element
select element)
{
try
{
deserializer.ReadObject(element.CreateReader(), false);
element.ReplaceNodes(clientElement);
}
catch (SerializationException) { }
}
Message sourceNatMessage = Message.CreateMessage(message.Version,
null,
document.CreateReader());
sourceNatMessage.Headers.CopyHeadersFrom(message);
sourceNatMessage.Properties.CopyProperties(message.Properties);
return sourceNatMessage;
}
答案 0 :(得分:0)
使用自定义寻址标头注释您的SOAP消息。
答案 1 :(得分:0)
在正常情况下,您不必做任何类似的事情。您的消息已包含您要查找的信息。
OperationContext context = OperationContext.Current;
MessageProperties messageProperties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpointProperty = messageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
在endpointProperty.Address属性上找到客户端IP地址,并在endpointProperty.Port属性上找到该端口。