WCF添加命名空间属性 [英] WCF Add Namespace Attributes
问题描述
我有一个简单的WCF,可获取两个值.这是我的代码:
[ServiceContract]公共接口IService{[运营合同]List< string>comunicarAreaContencaoResponse(字符串结果,字符串Obs);}
还有一个:
公共类Service:IService{公共列表< string>comunicarAreaContencaoResponse(字符串结果,字符串Obs){List< string>ListResultados =新的List< string>();如果(结果!= null){ListResultados.Add(Result);}如果(Obs!= null){ListResultados.Add(Obs);}返回ListResultados;}}
在SoapUi中,我得到了这个结果
< soapenv:信封xmlns:soapenv ="http://schemas.xmlsoap.org/soap/envelope/"xmlns:tem ="http://tempuri.org/">< soapenv:Header/>< soapenv:Body>< tem:comunicarAreaContencaoResponse><!-可选:->< tem:Result>?</tem:Result><!-可选:->< tem:Obs>?/tem:Obs></tem:comunicarAreaContencaoResponse></soapenv:Body></soapenv:Envelope>
但是我需要这样:
< soapenv:信封xmlns:soapenv ="http://schemas.xmlsoap.org/soap/envelope/"xmlns:tem ="http://tempuri.org/">< soapenv:Header/>< soapenv:Body>< tem:comunicarAreaContencaoResponsexmlns ="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:信封>
之所以需要如此具体,是因为该消息在发送到目的地之前先经过中间件.但是我似乎找不到一种在消息中插入这些名称空间的方法.如果我做不到,则不会发送.你能帮我吗?
根据您的描述,我认为您可以使用WCF消息检查器.在客户端发送消息之前.我们可以自定义消息正文.
I have a simple WCF that fetches two values. This is my code:
[ServiceContract]
public interface IService
{
[OperationContract]
List<string> comunicarAreaContencaoResponse(string Result, string Obs);
}
And this one:
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;
}
}
In SoapUi I have this result
<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>
But I need to be like this:
<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>
The reason why it needs to be this specific, it's because this message is going through a middleware before it is sent to the destination. But I can't seem to find a way to insert those namespaces on my message. If I can't do it, this won't be sent. Could you please help me?
According to your description, I think you could use WCF Message Inspector. Before the client send the message. We could customize the message body.
https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/message-inspectors
based on your code, I have made a demo to add the namespace attribute. This is the client-side code. I have added service reference to the current project, so the service contract has generated in the project.
Client.
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;
}
}
Add the attribute to the service contract.
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IService")]
[CustContractBehavior]
public interface IService {
}
Result.
这篇关于WCF添加命名空间属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!