目标服务是https://svcs.paypal.com/RiskAssessment/SetTransactionContext?wsdl
里面的SetTransactionContext方法要求添加SOAPheader
三个参数分别是
X-PAYPAL-SECURITY-USERID
X-PAYPAL-SECURITY-PASSWORD
X-PAYPAL-SECURITY-SIGNATURE
看了好多例子都是直接设置属性名然后赋值就可以了
可是这三参数里面带破折号。C#的属性名称不允许出现破折号。
现在想的是可不可以用二维数组或者Dictionary<string,string>添加key和value来实现?
我这边查了资料没有发现这样的例子。求大家帮帮忙!
主要问题是属性名不允许出现 - 破折号,可是文档里面要求的header标签是带 - 破折号的。想怎么避开解决这个问题!
header本身就是一个字典,直接对字典赋值就好。
从你的需求看,问题应该也是要求给http请求数据的header添加内容的。
header的设置,是不是用属性名的方式设置的,可以用字典来控制,字典,难道不允许用破折号?
@519740105: 就是不知道怎么用字典来控制呢。。。
没找到相关的例子
可以给出示例么。麻烦你了!
@lpyedge: 把你的贴出来,我看看。
@519740105:
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.17929")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://svcs.paypal.com/services")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://svcs.paypal.com/services", IsNullable = false)] public partial class MyHeader : System.Web.Services.Protocols.SoapHeader { /// <remarks/> public System.Collections.Generic.Dictionary<string,string> headers { get; set; } }
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.17929")] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name = "RiskAssessmentSOAP11Binding", Namespace = "http://svcs.paypal.com/services")] public partial class RiskAssessment : System.Web.Services.Protocols.SoapHttpClientProtocol { public MyHeader shead { get; set; } private System.Threading.SendOrPostCallback SetTransactionContextOperationCompleted; /// <remarks/> public RiskAssessment() { this.Url = "https://svcs.paypal.com/RiskAssessment"; } /// <remarks/> public event SetTransactionContextCompletedEventHandler SetTransactionContextCompleted; /// <remarks/> [System.Web.Services.Protocols.SoapHeaderAttribute("shead")] [System.Web.Services.Protocols.SoapDocumentMethodAttribute("urn:SetTransactionContext", RequestElementName = "SetTransactionContextRequest", RequestNamespace = "http://svcs.paypal.com/types/pt", ResponseNamespace = "http://svcs.paypal.com/types/pt", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] [return: System.Xml.Serialization.XmlElementAttribute("responseEnvelope", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] public ResponseEnvelope SetTransactionContext([System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] RequestEnvelope requestEnvelope, [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] ref string trackingId, [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] ref Account senderAccount, [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] ref Account receiverAccount, [System.Xml.Serialization.XmlArrayAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.Xml.Serialization.XmlArrayItemAttribute("subOrder", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable = false)] ref SubOrder[] subOrders, [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] ref Device device, [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] ref IpAddress ipAddress, [System.Xml.Serialization.XmlArrayAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] [System.Xml.Serialization.XmlArrayItemAttribute("pair", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable = false)] ref Pair[] additionalData) { object[] results = this.Invoke("SetTransactionContext", new object[] { requestEnvelope, trackingId, senderAccount, receiverAccount, subOrders, device, ipAddress, additionalData}); trackingId = ((string)(results[1])); senderAccount = ((Account)(results[2])); receiverAccount = ((Account)(results[3])); subOrders = ((SubOrder[])(results[4])); device = ((Device)(results[5])); ipAddress = ((IpAddress)(results[6])); additionalData = ((Pair[])(results[7])); return ((ResponseEnvelope)(results[0])); }
我用的Dictionary。可是运行的时候报错:
无法序列化 System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 类型的成员 Payments.PaypalExpress+PaypalSetTransactionContext+MyHeader.headers,因为它实现 IDictionary。
@lpyedge: 好久没弄WebService了,这个还真的~~~
我是直接在项目里添加服务引用的,发现代码并非象你这样,因此也没办法验证。
我强制性的把你的部分代码放进去,在调用的时候,也没发现有提交SoapHeader的内容(Fiddler2跟踪)。
给你个建议:
对于属性名为非C#规范的,可以通过强制设置属性名来实现,如:
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.17929")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://svcs.paypal.com/services")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://svcs.paypal.com/services", IsNullable = false)] public partial class MyHeader : System.Web.Services.Protocols.SoapHeader { /// <remarks/> [System.Xml.Serialization.SoapAttribute("X-PAYPAL-SECURITY-USERID")] public string X_PAYPAL_SECURITY_USERID { get; set; } [System.Xml.Serialization.SoapAttribute("X-PAYPAL-SECURITY-PASSWORD")] public string X_PAYPAL_SECURITY_PASSWORD { get; set; } [System.Xml.Serialization.SoapAttribute("X-PAYPAL-SECURITY-SIGNATURE")] public string X_PAYPAL_SECURITY_SIGNATURE { get; set; } }
@519740105:
还是不行,我用Fiddler2跟踪,发送的SoapHeader内容如下:
<soap:Header> <MyHeader xmlns="http://svcs.paypal.com/services"> <X_PAYPAL_SECURITY_USERID>*****************</X_PAYPAL_SECURITY_USERID> <X_PAYPAL_SECURITY_PASSWORD>*****************</X_PAYPAL_SECURITY_PASSWORD> <X_PAYPAL_SECURITY_SIGNATURE>*****************</X_PAYPAL_SECURITY_SIGNATURE> </MyHeader> </soap:Header>
首先多了个MyHeader的标签?然后是序列化的时候强制设置属性名没有效果!
@lpyedge:
1、下划线的问题,可以换其它的特性(system.xml.serialization名称空间里以xml开头的)试下
2、至于myheader节点,这个要看你的实际需求(咨询对方)了,应该定义成什么样子:
2.1、如果你是希望把MyHeader节点的名字换一个,那么在定义MyHeader类的时候可以指定(好像是XmlRoot特性),好像也可以在你定义 MyHeader shead 的地方对这个变量进行指定(这个未验证过)
2.2、如果是希望把x-系列的数据直接放置在soap:Header下,那么:
2.2.1、每个x-参数要单独定义一个变量在调用类里,然后对这个变量(属性)通过2.1的方案指定XML节点名达到目的
2.2.2、至于内容,你可以随意定义一个属性,比如Value、MyValue之类的,把属性的Xml特性定义为XmlContent。
public class MyHeader : SoapHeader { [XmlContent] public string Value{get;set;} } public class RiskAssement: xx { [XmlProperty("X-aaa-ddd")] public X_aaa_ddd{get;set;} }
@lpyedge: 刚把你的代码复制,实验了一下:
1、如果你希望MyHeader继续出现,只是名字不同的话,可以通过对MyHeader类定义XmlRoot来解决。
2、如果你希望x-系列属性也要放到SoapHeader下,那就~~~需要对每个属性单独定义类,再使用XmlRoot来定义,并且在定义的类里,使用XmlText来只能属性的值是内容。
@519740105: 终于按照我的理解实现功能了
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.17929")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(Namespace = "")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "X-PAYPAL-SECURITY-SIGNATURE")] public partial class X_PAYPAL_SECURITY_SIGNATURE : System.Web.Services.Protocols.SoapHeader { [System.Xml.Serialization.XmlText()] public string Value { get; set; } }
可是结果发送过去还是报错,后来和paypal那边的技术一沟通,那边说是要在SoapHttpClientProtocol的http Header里面加上这三个参数。郁闷死了。
大侠再求助一下,怎么给SoapHttpClientProtocol动态添加http header啊?没有发现对应的方法和属性呢?
@lpyedge: 找!在你执行Invoke的时候,想办法获取HTTP请求对象(一般类型是HttpRequest或WebRequest之类的),有了这个,就能发现有一个集合属性Headers了,而这个Headers不过是一个字典而已(至少是一个可以当字典使用的集合)。