我有一个简单的WCF,可获取两个值。这是我的代码:
[ServiceContract]
public interface IService
{
[OperationContract]
List<string> comunicarAreaContencaoResponse(string Result, string Obs);
}
还有一个:
public class Service : IService
{
public List<string> comunicarAreaContencaoResponse(string Result, string
Obs)
{
List<string> ListResultados = new List<string>();
if (Result != null)
{
ListResultados.Add(Result);
}
if (Obs != null)
{
ListResultados.Add(Obs);
}
return ListResultados;
}
}
在SoapUi中,我得到了这个结果
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:comunicarAreaContencaoResponse>
<!--Optional:-->
<tem:Result>?</tem:Result>
<!--Optional:-->
<tem:Obs>?</tem:Obs>
</tem:comunicarAreaContencaoResponse>
</soapenv:Body>
</soapenv:Envelope>
但是我需要这样:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:comunicarAreaContencaoResponse
xmlns="http://www.outsystems.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<tem:Result>false</tem:Result>
<tem:Obs />
</tem:comunicarAreaContencaoResponse>
</soapenv:Body>
</soapenv:Envelope>
之所以需要如此具体,是因为此消息在发送到目的地之前先经过中间件。但是我似乎找不到一种在消息中插入这些名称空间的方法。如果我做不到,则不会发送。你能帮我吗?
答案 0 :(得分:0)
根据您的描述,我认为您可以使用WCF消息检查器。在客户端发送消息之前。我们可以自定义消息正文。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/message-inspectors
根据您的代码,我进行了演示以添加名称空间属性。这是客户端代码。我已经向当前项目添加了服务引用,因此该项目中已经生成了服务合同。
客户端。
static void Main(string[] args)
{
ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
try
{
var result = client.comunicarAreaContencaoResponse("Hello","World");
foreach (var item in result)
{
Console.WriteLine(item);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
string result = $"server reply message:\n{reply}\n";
Console.WriteLine(result);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
// Read reply payload
XmlDocument doc = new XmlDocument();
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms);
request.WriteMessage(writer);
writer.Flush();
ms.Position = 0;
doc.Load(ms);
// Change Body logic
ChangeMessage(doc);
// Write the reply payload
ms.SetLength(0);
writer = XmlWriter.Create(ms);
doc.WriteTo(writer);
writer.Flush();
ms.Position = 0;
XmlReader reader = XmlReader.Create(ms);
request = System.ServiceModel.Channels.Message.CreateMessage(reader, int.MaxValue, request.Version);
string result = $"client ready to send message:\n{request}\n";
Console.WriteLine(result);
return null;
}
void ChangeMessage(XmlDocument doc)
{
XmlElement element = (XmlElement)doc.GetElementsByTagName("comunicarAreaContencaoResponse").Item(0);
if (element!=null)
{
element.SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
element.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
element.Attributes.RemoveNamedItem("xmlns:i");
}
}
}
public class CustContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
{
public Type TargetContract => typeof(IService);
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
return;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
return;
}
}
将属性添加到服务合同中。
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IService")]
[CustContractBehavior]
public interface IService {
}
结果。