Xml 替换WCF消息的内容
我正在尝试设置一个路由服务,它将位于我网络的DMZ中,并允许外部人员访问一些内部托管的WCF服务。我已经准备好了一切,但当我转发MEX服务时,它会将我们的外部客户指向我们的内部地址,显然他们无法访问该地址 ,这可能会起作用,但需要我在每次服务定义更改时都创建一个新的wsdl副本,这是他们经常做的,看起来有些过分了。唯一需要更改的是mex消息中的地址Xml 替换WCF消息的内容,xml,wcf,Xml,Wcf,我正在尝试设置一个路由服务,它将位于我网络的DMZ中,并允许外部人员访问一些内部托管的WCF服务。我已经准备好了一切,但当我转发MEX服务时,它会将我们的外部客户指向我们的内部地址,显然他们无法访问该地址 ,这可能会起作用,但需要我在每次服务定义更改时都创建一个新的wsdl副本,这是他们经常做的,看起来有些过分了。唯一需要更改的是mex消息中的地址 <endpoint address="http://appsrv1:8781/ProcessManagementService/
<endpoint address="http://appsrv1:8781/ProcessManagementService/"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IProcessManagementService"
contract="IProcessManagementService" name="WSHttpBinding_IProcessManagementService" />
而且它似乎大部分都有效。但是,当我尝试创建消息时,XMLReader
抛出异常“根级别的数据无效。第1行,位置1”。我不知道从哪里开始
编辑2:
好的,现在我有了一个方法,可以将消息提取到xdocument中,然后将其发送到字符串中,然后对其进行编辑,然后将其拉回到xdocument中,当我发送回包含该已编辑消息的消息时,我会得到一个“强制关闭的连接”。糟透了
编辑3:
测试之后,只需从xdoc的回复中提取消息,然后将其加载到新消息中,就足以导致“连接强制关闭”问题。这不能是编辑邮件的正确方式。我正在寻找如何最好地解决这个问题的例子或经验 如果您使用的是.NET 4.0,您只需为您的服务配置或在代码中配置即可。我从。我的问题是我更改了字符串的长度,但没有重置MemoryStream的长度,这意味着末尾的字节没有被报告 这是一个有效的替换函数
public Message ChangeString(Message oldMessage, string from, string to)
{
MemoryStream ms = new MemoryStream();
XmlWriter xw = XmlWriter.Create(ms);
oldMessage.WriteMessage(xw);
xw.Flush();
string body = Encoding.UTF8.GetString(ms.ToArray());
xw.Close();
body = body.Replace(from, to);
ms = new MemoryStream(Encoding.UTF8.GetBytes(body));
XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(ms, new XmlDictionaryReaderQuotas());
Message newMessage = Message.CreateMessage(xdr, int.MaxValue, oldMessage.Version);
newMessage.Properties.CopyProperties(oldMessage.Properties);
return newMessage;
}
对于那些喜欢使用Linq到XML的人
private void ChangeMessage(ref Message reply)
{
Message newMessage = null;
MessageBuffer msgbuf = reply.CreateBufferedCopy(int.MaxValue);
Message tmpMessage = msgbuf.CreateMessage();
XmlDictionaryReader xdr = tmpMessage.GetReaderAtBodyContents();
XElement bodyEl = XElement.Load(xdr.ReadSubtree());
var someElement= bodyEl.Descendants().FirstOrDefault(b => b.Name.LocalName == "somename");
XElement newElement = getNewSomeElement();//private method
someElement.ReplaceWith(newElement);//replacing node into body
MemoryStream ms = new MemoryStream();
XmlWriter xw = XmlWriter.Create(ms);
bodyEl.Save(xw);
xw.Flush();
xw.Close();
ms.Position = 0;
XmlReader xr = XmlReader.Create(ms);
//create new message from modified XML document
newMessage = Message.CreateMessage(reply.Version, null, xr);
newMessage.Headers.CopyHeadersFrom(reply);
newMessage.Properties.CopyProperties(reply.Properties);
reply = newMessage;
}
我想知道更多。这是在内部服务器的服务上配置还是在路由器的服务上配置?MSDN信息缺乏关于它的作用。好吧,在玩弄了这个之后,它似乎不是答案。在路由器上应用它对MEX服务没有任何作用,而在服务器上应用它只会让我得到路由器用来访问内部服务器的任何东西,这是外部世界无法使用的。目的是将它应用于服务,而不是路由器。现在我想起来了,您可能正在使用路由器中的内部服务器名称配置服务的端点,对吗?如果是这样,您可能需要将地址设置为逻辑主机名,然后使用via属性通过内部服务器名传递消息。这样,在发出请求时,它应该将主机头正确地传递给底层服务。但是,请确保内部服务也配置为在其一侧使用该地址。我正在使用内部服务器的IP地址配置路由器的客户端端点,因为它位于不同的网络上,无法通过DNS找到它。这是什么Via属性?该属性仅帮助“动态”修改WSDL服务元。
private void ChangeMessage(ref Message reply)
{
Message newMessage = null;
MessageBuffer msgbuf = reply.CreateBufferedCopy(int.MaxValue);
Message tmpMessage = msgbuf.CreateMessage();
XmlDictionaryReader xdr = tmpMessage.GetReaderAtBodyContents();
XElement bodyEl = XElement.Load(xdr.ReadSubtree());
var someElement= bodyEl.Descendants().FirstOrDefault(b => b.Name.LocalName == "somename");
XElement newElement = getNewSomeElement();//private method
someElement.ReplaceWith(newElement);//replacing node into body
MemoryStream ms = new MemoryStream();
XmlWriter xw = XmlWriter.Create(ms);
bodyEl.Save(xw);
xw.Flush();
xw.Close();
ms.Position = 0;
XmlReader xr = XmlReader.Create(ms);
//create new message from modified XML document
newMessage = Message.CreateMessage(reply.Version, null, xr);
newMessage.Headers.CopyHeadersFrom(reply);
newMessage.Properties.CopyProperties(reply.Properties);
reply = newMessage;
}