2008-12-01 53 views
1

过去,我需要在使用导入的WSDL Web引用的C#项目中创建自定义SOAP头文件。我找到了一种方法来做到这一点,但我从来没有满意,我有理由怀疑是否有更好的方法。我所做的就是创建一个从SOAPHEADER派生的标题:是否有更好的方式来定制C#中的SOAP头文件?

[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://model.test.net")] 
[System.Xml.Serialization.XmlRootAttribute("securitytoken", Namespace = "http://model.test.net", IsNullable = false)] 
public class SpecialHeader : SoapHeader 
{ 
    [System.Xml.Serialization.XmlTextAttribute()] 
    public string aheadervalue; 
} 

我只好再修改从WSDL生成的代码和 CE添加一个参照的文新报头的实例和每个前下网络呼叫 我想包含自定义标题:

[System.Web.Services.Protocols.SoapHeaderAttribute("instancename", Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut)] 

其中“实例名称”是自定义页眉的实例变量名在生成的类。

这可以很好地工作,除了WSDL中的任何更改都要求将它全部重新完成,因为它会重新生成类。在其他语言中,头文件可以添加到生成的代码之外,所以也许我错过了在C#中完成的方式。有没有更好的方法来做到这一点?

回答

0

有一种方法可以做到这一点,它不一定非常漂亮,并且在一个非常简单的Web服务上它可能不值得这样做,但它至少可以让您不必在重新生成代码时重新添加属性。

由于发电机产生子类,您可以:

  1. 添加文件到您的项目与另一个“部分”部分(即,使用扩展了Web服务类(一个从SoapHttpClientProtocol衍生)与生成的类相同的名称空间和名称,并将其标记为“部分”)。

  2. 将您想添加标题的方法复制到生成的代码中(即,您已经添加属性的相同方法)并将其粘贴到扩展部分。

  3. 稍微重命名这些方法,以便它们不会与生成的代码中的方法发生冲突,并将传递给Invoke的名称更改为匹配。 (您可能还必须调整方法上的其他属性,以确保它们仍映射到WSDL中的正确调用。)

  4. 将自定义标头属性添加到重命名的方法,并将标题实例字段添加到您的扩展部分。

  5. 从您的代码中调用重命名的版本而不是原始版本。

只要方法签名在WSDL中不发生更改,即使重新生成,也不必更改代码中的任何内容。 (因为您只复制相对较短的方法实现,所以WSDL中的任何其他结构仍然会从生成的代码中提取出来,所以如果它们发生更改,则在重新生成时会自动获取更新后的版本。在其中有任何其他结构,这可能是有限的)

它仍然不是理想的,但试图拦截原始的XML消息,并将标题直接放入(你可能会做,但这将是讨厌的),没有任何其他选项我知道(无论如何不移动到WCF)。

3

看来你正在使用。Net 2.0和asmx Web服务。 您是否知道.Net 3.0中有一个名为WCF(Windows Communication Framework)的框架。 我知道迁移到新的框架并不容易,但是使用WCF你会获得如此多的收益。此外WCf可以用于远远超过WebServices(远程处理,msmq和更多)。这是微软未来投注的框架。 也就是说。使用MessageContracts完成肥皂头的操作。

所以答案是,在WCF中你可以用MessageContracts做到这一点。

+0

@khebbie:我是WCF的新手,并尝试设置自定义标题。消息合同听起来像是要走的路。你知道一个很好的资源,我可以在这里读到吗? – Adam 2010-04-05 21:50:12

0

今天我遇到了这个问题。我最终创建了一个从自动生成的类派生的类,并覆盖了GetWriterForMessage方法,以确保我的头文件始终存在。我会在每次调用方法时更新标题值。

2

生成的类别是部分类别。您可以在具有相同名称空间和类名的另一个文件(再次部分类)上定义它。然后你可以覆盖它的虚拟方法并定义一次。

这样可以防止重新生成的类的进一步更改不会影响您编写的类。

在新的类文件上,您可以使用“GetWriterForMessage”覆盖并向其中添加新的SOAP标题。

public partial class SampleService 
{ 
    public string MessageID { get; set; } 

    protected override System.Xml.XmlWriter GetWriterForMessage(System.Web.Services.Protocols.SoapClientMessage message, int bufferSize) 
    { 
     message.Headers.Add(new UsernameSoapHeader("Username")); 
     message.Headers.Add(new PasswordSoapHeader("Password")); 
     message.Headers.Add(new MessageIDSoapHeader(MessageID)); 
     return base.GetWriterForMessage(message, bufferSize); 
    } 
} 
相关问题