WCF添加命名空间属性 [英] WCF Add Namespace Attributes

查看:286
本文介绍了WCF添加命名空间属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆