【问题标题】:How To Pass Soap Header When WSDL Doesn't Define It?WSDL 未定义时如何传递 Soap 标头?
【发布时间】:2009-02-14 05:57:12
【问题描述】:
我有一个正在调用的 Web 服务,他们发布的 WSDL 实际上并没有定义大部分服务,其中 3/4 必须在之后手动构建。
我遇到的问题是他们需要一个包含一些特定信息的 SoapHeader,但我没有任何办法。我为该服务拥有的唯一真实的东西是创建的代理方法(MyMethod),我可以将消息传递给它。我怎样才能设置/发送一个肥皂头呢?
我拥有的所有服务,我已经能够使用 Visual Studio 中的自动绑定项。
【问题讨论】:
标签:
.net
web-services
soap
【解决方案1】:
我可以通过手动修改自动生成的代理代码并简单地注入一个继承“SoapHeader”并将属性添加到方法的类来完成此操作!
我无法重新生成或重新刷新代理,但它完成了工作,只用了 15 分钟。
【解决方案2】:
相当老的帖子,但对其他人有用。
在 Visual Studio 中集成 WSDL 时,您会在新命名空间中获得一个派生自 SoapHttpClientProtocol 的新类。
幸运的是,这个类是部分的,这意味着您可以在代码中扩展它,这样当您从 WSDL 刷新时所做的修改不会被覆盖。
我的 WSDL 生成的类是:
namespace TheServiceNameSpace {
public partial class TheClassName : System.Web.Services.Protocols.SoapHttpClientProtocol {
//Class Code
}
}
为了添加自定义标题,我向我的项目添加了一个新的 cs 文件,其中包含以下内容:
namespace TheServiceNameSpace
{
public partial class SecurityHeader : SoapHeader
{
public String username { get; set; }
public String password { get; set; }
public String apikey { get; set; }
}
public partial class TheClassName
{
public SecurityHeader SEC = new SecurityHeader() { username = "xxxx", password = "xxxx", apikey = "xxxx" };
protected override XmlWriter GetWriterForMessage(SoapClientMessage message, int bufferSize)
{
message.Headers.Add(SEC);
return base.GetWriterForMessage(message, bufferSize);
}
}
}
它的作用是:
- 1 - 创建包含预期变量的自定义 SOAP 标头
- 2 - 扩展生成的类以添加对新标头的引用
- 3 - 覆盖 GetWriterForMessage 方法,以便我可以在将发送到服务的请求中添加我的标头。
【讨论】:
-
当我这样做时,我得到如下内容,但我似乎无法获得 wsse 前缀。我错过了什么? localhost:80....."> dfgsfdsdfgsfd:标题>
【解决方案4】:
如果您需要精细控制soap 标头xml 的呈现方式(在与用java 编写的Web 服务交互时发生),您始终可以通过实现IXmlSerializable 覆盖所有呈现
[XmlRoot("customHeader", Namespace = "http://somecompany.com/webservices/security/2012/topSecret")]
public class customHeader: SoapHeader, IXmlSerializable
{
public customHeader()
{
Actor = "http://schemas.xmlsoap.org/soap/actor/next";
MustUnderstand = false;
}
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
//throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
//throw new NotImplementedException();
}
public void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("soap:actor", Actor);
writer.WriteAttributeString("soap:mustUnderstand", MustUnderstand ? "1" : "0");
writer.WriteRaw("some encrypted data");
//get it exactly the way you want it in here without mucking with Xml* property attributes for hours on end
//writer.WriteElement(...);
}
}