.net关于soap处理

 aspx有httpmodel,httphandle这些东西来预处理

asmx,webservice用什么呢

SoapExtension

msdn的原文

请参见语言筛选器.NET Framework 开发员指南 

使用 SOAP 扩展更改 SOAP 消息  [C#]

SOAP 扩展允许开发人员通过更改往返于 XML Web services 或 XML Web services 客户端的 SOAP 消息来增加 XML Web services 的功能。例如,您可以实现加密或压缩算法与现有的 XML Web services 一起运行。

若要理解 SOAP 扩展如何工作,首先理解 XML Web services 的生存期是很有用的。有关 XML Web services 生存期的概述,请参见 XML Web services 生存期剖析。然而,下图对从客户端到 XML Web services 的调用的主要阶段进行了概述。

XML Web services 生存期的剖析

正如您看到的,ASP.NET 在 XML Web services 计算机和 XML Web services 客户端计算机上的阶段中对 XML 进行序列化和反序列化。可以将 SOAP 扩展插入基础结构以在每个序列化和反序列化阶段的之前和之后检查或修改 SOAP 消息。例如,加密 SOAP 扩展可能在 ASP.NET 序列化客户端参数之后加密 SOAP 消息的 XML 部分,然后在 ASP.NET 反序列化 SOAP 消息之前在 Web 服务器上解密 SOAP 消息。这些阶段(SOAP 扩展可能在这些阶段中检查或修改 SOAP 消息)是在 SoapMessageStage 枚举中定义的。在这种情况下,在 AfterSerialize 阶段加密 SOAP 扩展,在 BeforeDeserialize 阶段解密 SOAP 扩展。

通常,当 SOAP 扩展修改 SOAP 消息的内容时,必须在客户端和服务器上都进行修改。也就是说,如果在客户端上运行了 SOAP 扩展并加密了 SOAP 消息,则相应的 SOAP 扩展必须在服务器上解密 SOAP 消息。如果未解密该 SOAP 消息,则 ASP.NET 基础结构不能将 SOAP 消息反序列化为对象。当然,不修改 SOAP 消息的 SOAP 扩展(例如仅记录 SOAP 消息的 SOAP 扩展)可以只在客户端或服务器上运行。在这种情况下,接收方接收与在 SOAP 扩展不运行并且 ASP.NET 基础结构可以反序列化 SOAP 消息的情况下相同的 SOAP 消息。另外,如果 SOAP 扩展不以一种使反序列化不能实现的方式对 SOAP 进行修改,则 SOAP 扩展不需要既运行在客户端又运行在服务器上。

现在您了解了 SOAP 扩展可以进行的操作以及它何时可以执行其功能,让我们看看如何生成 SOAP 扩展。生成 SOAP 扩展并让其使用 XML Web services 的基本步骤如下:

  • 从 SoapExtension 派生一个类。
  • 保存对表示将来 SOAP 消息的 Stream 的引用。
  • 初始化 SOAP 扩展特定的数据。
  • 在相关的 SoapMessageStage 或多个阶段中处理 SOAP 消息。
  • 配置 SOAP 扩展以使用特定的 XML Web services 方法。

从 SoapExtension 派生类

从 SoapExtension 派生的类是执行 SOAP 扩展的功能的类。也就是说,如果 SOAP 扩展是加密 SOAP 扩展,那么从 SoapExtension 派生的类执行加密和相应的解密。

保存对表示将来 SOAP 消息的流的引用

若要修改 SOAP 消息,您必须重写 ChainStream 方法,因为这是接收对流的引用的唯一机会,而流可以用来获得将来 SOAP 消息的内容。

对 Stream 的引用在任何 SoapMessageStage 之前传入 ChainStream 一次。该 Stream 是指在较低优先级(有关 SOAP 扩展优先级的详细信息,请参见配置 SOAP 扩展以运行 XML Web services 方法)的 SOAP 扩展已执行并进行了对 SOAP 消息的更改后 SOAP 消息的 XML。因此,SOAP 扩展应该将该引用保存在成员变量中,供以后 SOAP 扩展检查或修改 SOAP 消息时在 SoapMessageStage 过程中访问。

但是,传入 ChainStreamStream 不是 SOAP 扩展应该修改的那个 Stream。SOAP 扩展应该创建 Stream 的新实例,将其保存在私有成员变量中,并在 ChainStream 方法中将其返回。当 SOAP 扩展在每个 SoapMessageStage 过程中执行并修改 SOAP 消息时,SOAP 扩展应该从传入 ChainStreamStream 进行读取并为 ChainStream 写入 Stream 返回值。因此,将两个 Stream 引用保存在 ChainStream 方法中很重要。

下面的代码示例演示 ChainStream 方法的公共实现。

 

    // Save the Stream representing the SOAP request or SOAP response into
    // a local memory buffer.
    public override Stream ChainStream( Stream stream ){
        // Save the passed in Stream in a member variable.
        oldStream = stream;

        // Create a new instance of a Stream and save that in a member
        // variable.
        newStream = new MemoryStream();
        return newStream;
    }

 

初始化 SOAP 扩展特定的数据

SOAP 扩展可以根据应用它的 XML Web services 或 XML Web services 方法初始化内部数据。例如,如果某 SOAP 扩展用于记录发送到 XML Web services 方法和从 XML Web services 方法发送回的 SOAP 消息,则该 SOAP 扩展可能会初始化文件的名称以保存日志信息,初始化过程基于 SOAP 扩展正在使用的 XML Web services 或 XML Web services 方法的名称。

从 SoapExtension 派生的类有两个用来初始化数据的方法: GetInitializer 和 Initialize 。仅在第一次访问 XML Web services 或 XML Web services 方法(根据 SOAP 扩展的配置方式,SOAP 扩展被配置为与它一起运行)时才调用 GetInitializer(请参见配置 SOAP 扩展以运行 XML Web services 方法)。如果 SOAP 扩展是用属性配置的,则 ASP.NET 基础结构将基于每个 XML Web services 方法来调用 GetInitializer。如果 SOAP 扩展是在配置文件中配置的,则只在第一次访问 XML Web services 时由 ASP.NET 基础结构调用 GetInitializer。ASP.NET 基础结构对 SOAP 扩展从 GetInitializer 返回的数据进行缓存以供 SOAP 扩展以后使用。每次 SOAP 扩展在 Initialize 方法中使用该 XML Web services 或 XML Web services 方法时,都将缓存的数据传递给 SOAP 扩展。

GetInitializer 方法中 SOAP 扩展可用的信息取决于 SOAP 扩展的配置方式。如果 SOAP 扩展是使用特性配置的,则 ASP.NET 基础结构将该特性(包括与其关联的任何自定义属性)和 LogicalMethodInfo 传入 GetInitializerLogicalMethodInfo 提供有关该 XML Web services 方法的原型详细信息,例如参数的数目和它们的数据类型。如果 SOAP 扩展是使用配置文件配置的,则只将实现 XML Web services 的类的 Type 传递到 GetInitializer

下面的代码示例根据 SOAP 扩展最终配置方式以一种不同的方式初始化 GetInitializer 方法中一段缓存的数据。如果 SOAP 扩展是使用属性(在本示例中为 TraceExtensionAttribute)配置的,则缓存该属性中指定的文件名。如果 SOAP 扩展是使用配置文件配置的,则根据 XML Web services 的类型计算缓存的文件名。

 

// When the SOAP extension is accessed for the first time, the XML
// Web service method it is applied to is accessed to store the file
// name passed in, using the corresponding SoapExtensionAttribute.
public override object GetInitializer(LogicalMethodInfo methodInfo,
   SoapExtensionAttribute attribute) 
{
   return ((TraceExtensionAttribute) attribute).Filename;
}
// The extension was configured to run using a configuration file instead of
// an attribute applied to a specific XML Web service method.
public override object GetInitializer(Type WebServiceType) 
{
// Return a file name to log the trace information, based on the type.
   return "C://" + WebServiceType.FullName + ".log";}

 

处理 SOAP 消息

在从 SoapExtension 派生的类中,实现的核心部分是 SoapExtension.ProcessMessage 。ASP.NET 在 SoapMessageStage 枚举中定义的每个阶段都多次调用该方法。每次调用 SoapExtension.ProcessMessage 方法时,都在特定的阶段传入带有 SOAP 消息的 SoapMessage 或从它派生的类。如果 SOAP 扩展正在使用 XML Web services,则传入 SoapServerMessage 。如果 SOAP 扩展正在使用 XML Web services 客户端,则传入 SoapClientMessage 。

下面的代码示例是 SOAP 扩展的 ProcessStage 方法,该方法跟踪对 XML Web services 的调用。在跟踪过程中,如果 SoapMessageStage 是参数被序列化为 XML 的阶段,则将 XML 写入文件。

    public override void ProcessMessage(SoapMessage message) 
    {
        switch (message.Stage) 
        {
        case SoapMessageStage.BeforeSerialize:
            break;
        case SoapMessageStage.AfterSerialize:
            // Write the SOAP message out to a file.
            WriteOutput( message );
            break;
        case SoapMessageStage.BeforeDeserialize:
            // Write the SOAP message out to a file.
            WriteInput( message );
            break;
        case SoapMessageStage.AfterDeserialize:
            break;
        default:
            throw new Exception("invalid stage");
        }
    }

 

 

调用 SOAP 扩展方法的顺序

现在您已经了解了 SOAP 扩展必须重写的方法,让我们看看在整个 XML Web services 方法调用过程中 ASP.NET 何时调用 SOAP 扩展方法。下面的步骤假设 SOAP 扩展既运行于客户端又运行于服务器上。如果 SOAP 扩展不同时运行于客户端和服务器上,则 ASP.NET 将忽略与 SOAP 扩展运行于其中任何一个相关联的步骤。

客户端

  1. 客户端对代理类调用方法。
  2. 在客户端上创建 SOAP 扩展的新实例。
  3. 如果这是第一次在客户端上用该 XML Web services 执行该 SOAP 扩展,则对运行于客户端上的 SOAP 扩展调用 GetInitializer 方法。
  4. 调用 Initialize 方法。
  5. 调用 ChainStream 方法。
  6. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeSerialize
  7. 客户端计算机上的 ASP.NET 将 XML Web services 方法的参数序列化为 XML。
  8. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterSerialize
  9. 客户端计算机上的 ASP.NET 通过网络将 SOAP 消息发送到承载该 XML Web services 的 Web 服务器。

服务器端

  1. Web 服务器上的 ASP.NET 接收该 SOAP 消息。
  2. 在 Web 服务器上创建 SOAP 扩展的新实例。
  3. 在 Web 服务器上,如果这是第一次在服务器端使用该 XML Web services 执行该 SOAP 扩展,则对运行于服务器上的 SOAP 扩展调用 GetInitializer 方法。
  4. 调用 Initialize 方法。
  5. 调用 ChainStream 方法。
  6. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeDeserialize
  7. ASP.NET 反序列化 XML 中的参数。
  8. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterDeserialize
  9. ASP.NET 创建实现 XML Web services 的类的新实例并调用 XML Web services 方法,同时传入反序列化的参数。该对象驻留在与 Web 服务器相同的计算机上。
  10. XML Web services 方法执行其代码,最终会设置返回值和任何输出参数。
  11. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeSerialize
  12. Web 服务器上的 ASP.NET 将返回值和输出参数序列化为 XML。
  13. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterSerialize
  14. ASP.NET 通过网络将 SOAP 响应消息发送回 XML Web services 客户端。

客户端

  1. 客户端计算机上的 ASP.NET 接收 SOAP 消息。
  2. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 BeforeDeserialize
  3. ASP.NET 将 XML 反序列化为返回值和任何输出参数。
  4. 调用 ProcessMessage 方法,调用时将 SoapMessageStage 设置为 AfterDeserialize
  5. ASP.NET 将返回值和任何输出参数传递到代理类的实例。
  6. 客户端接收返回值和任何输出参数。

配置 SOAP 扩展与 XML Web services 方法一起运行

SOAP 扩展可以配置为使用自定义属性来运行,或者配置为通过修改配置文件来运行。若要使用自定义属性,请将其应用到您要 SOAP 扩展使用的每个 XML Web services 方法。当使用配置文件时,该 SOAP 扩展使用配置文件范围内的所有 XML Web services。有关配置文件的工作方式的详细信息,请参见配置应用程序

若要使用自定义属性,请从 SoapExtensionAttribute 派生一个类。SoapExtensionAttribute 具有两个属性:ExtensionTypePriority。SOAP 扩展应该在 ExtensionType 属性中返回该 SOAP 扩展的类型。Priority 属性表示该 SOAP 扩展的相对优先级,将对其进行简短的讨论。

若要指定 SOAP 扩展与配置文件范围内的所有 XML Web services 一起运行,请在适当的 App.config 或 Web.config 文件中添加项。具体地说,必须将 soapExtensionTypes XML 元素添加到配置文件的 webServices 节中。在 soapExtensionTypes XML 元素中,为要与配置文件范围内的所有 XML Web services 一起运行的每个 SOAP 扩展添加 XML 元素。add XML 元素具有以下属性:

属性说明
typeSOAP 扩展的类型以及它所驻留的程序集。
prioritySOAP 扩展在其组中的相对优先级。
groupSOAP 扩展是其成员的组。请参见该表后有关优先级的详细信息。

SOAP 扩展具有分配给它们的优先级,该优先级指示当配置多个 SOAP 扩展使用 XML Web services 方法时执行的相对顺序。SOAP 扩展的优先级越高,它的执行与通过网络发送或接收 SOAP 消息越近。SOAP 扩展在三个优先级组中的一个。在每个组内,priority 属性区别每个成员。priority 属性越低,相对优先级就越高(0 是最高的)。

SOAP 扩展的三个相对优先级组是:使用属性配置的 SOAP 扩展和配置文件中指定的 group 设置为 01 的 SOAP 扩展。使用属性配置的 SOAP 扩展是中间组的成员。使用配置文件配置的 group 设置为 0 的 SOAP 扩展具有最高的相对优先级。group 设置为 1 的 SOAP 扩展具有最低的相对优先级。

下面的代码示例是一个配置文件,它指定 Logger.LoggerExtension SOAP 扩展在相对优先级组 0 中运行并具有优先级 1

<configuration>
 <system.web>
   <webServices>
     <soapExtensionTypes>
      <add type="Logger.LoggerExtension,logger"
           priority="1"
           group="0" />
     </soapExtensionTypes>
    </webServices>
 </system.web>
</configuration>

 

下面的代码示例是一个 SOAP 扩展,该 SOAP 扩展记录发送到 XML Web services 或 XML Web services 客户端的 SOAP 消息和从 XML Web services 或 XML Web services 客户端发送回的 SOAP 消息。如果将以下 SOAP 扩展安装为与 XML Web services 一起运行,则 ASPNET 用户帐户必须具有对日志文件所写入的目录的写入权限。

 

  using System;
  using System.Web.Services;
  using System.Web.Services.Protocols;
  using System.IO;
  using System.Net;

  // Define a SOAP Extension that traces the SOAP request and SOAP
  // response for the XML Web service method the SOAP extension is
  // applied to.

  public class TraceExtension : SoapExtension 
  {
    Stream oldStream;
    Stream newStream;
    string filename;

    // Save the Stream representing the SOAP request or SOAP response into
    // a local memory buffer.
    public override Stream ChainStream( Stream stream ){
        oldStream = stream;
        newStream = new MemoryStream();
        return newStream;
    }

    // When the SOAP extension is accessed for the first time, the XML Web
    // service method it is applied to is accessed to store the file
    // name passed in, using the corresponding SoapExtensionAttribute.   
    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) 
    {
        return ((TraceExtensionAttribute) attribute).Filename;
    }

    // The SOAP extension was configured to run using a configuration file
    // instead of an attribute applied to a specific XML Web service
    // method.
    public override object GetInitializer(Type WebServiceType) 
    {
      // Return a file name to log the trace information to, based on the
      // type.
      return "C://" + WebServiceType.FullName + ".log";    
    }

    // Receive the file name stored by GetInitializer and store it in a
    // member variable for this specific instance.
    public override void Initialize(object initializer) 
    {
        filename = (string) initializer;
    }

    //  If the SoapMessageStage is such that the SoapRequest or
    //  SoapResponse is still in the SOAP format to be sent or received,
    //  save it out to a file.
    public override void ProcessMessage(SoapMessage message) 
    {
        switch (message.Stage) {
        case SoapMessageStage.BeforeSerialize:
            break;
        case SoapMessageStage.AfterSerialize:
            WriteOutput(message);
            break;
        case SoapMessageStage.BeforeDeserialize:
            WriteInput(message);
            break;
        case SoapMessageStage.AfterDeserialize:
            break;
        default:
             throw new Exception("invalid stage");
        }
    }

    public void WriteOutput(SoapMessage message){
        newStream.Position = 0;
        FileStream fs = new FileStream(filename, FileMode.Append,
                                       FileAccess.Write);
        StreamWriter w = new StreamWriter(fs);

      string soapString = (message is SoapServerMessage) ? "SoapResponse" : "SoapRequest";
        w.WriteLine("-----" + soapString + " at " + DateTime.Now);
        w.Flush();
        Copy(newStream, fs);
        w.Close();
        newStream.Position = 0;
        Copy(newStream, oldStream);
    }

    public void WriteInput(SoapMessage message){
        Copy(oldStream, newStream);
        FileStream fs = new FileStream(filename, FileMode.Append,
                                       FileAccess.Write);
        StreamWriter w = new StreamWriter(fs);

        string soapString = (message is SoapServerMessage) ?
                            "SoapRequest" : "SoapResponse";
        w.WriteLine("-----" + soapString + 
                    " at " + DateTime.Now);
        w.Flush();
        newStream.Position = 0;
        Copy(newStream, fs);
        w.Close();
        newStream.Position = 0;
    }

    void Copy(Stream from, Stream to) 
    {
        TextReader reader = new StreamReader(from);
        TextWriter writer = new StreamWriter(to);
        writer.WriteLine(reader.ReadToEnd());
        writer.Flush();
    }
  }

   // Create a SoapExtensionAttribute for the SOAP Extension that can be
   // applied to an XML Web service method.
  [AttributeUsage(AttributeTargets.Method)]
  public class TraceExtensionAttribute : SoapExtensionAttribute {

    private string filename = "c://log.txt";
    private int priority;

    public override Type ExtensionType {
        get { return typeof(TraceExtension); }
    }

    public override int Priority {
        get { return priority; }
        set { priority = value; }
    }

    public string Filename {
        get {
            return filename;
        }
        set {
            filename = value;
        }
    }
  }

 

请参见

SoapExtension | SoapExtensionAttribute | SoapMessageStage | LogicalMethodInfo | XML Web services 生存期剖析 | 配置应用程序 | 使用 ASP.NET 生成 XML Web services | 生成 XML Web services 客户端

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值