【问题标题】:Is there a way to get the raw SOAP request from within a ASP.NET WebMethod?有没有办法从 ASP.NET WebMethod 中获取原始 SOAP 请求?
【发布时间】:2011-02-04 23:42:43
【问题描述】:

例子:

public class Service1 : System.Web.Services.WebService
{
   [WebMethod]
   public int Add(int x, int y)
   {
       string request = getRawSOAPRequest();//How could you implement this part?
       //.. do something with complete soap request

       int sum = x + y;
       return sum;
   }
}

【问题讨论】:

    标签: c# .net web-services soap asmx


    【解决方案1】:

    我假设您想要记录 SOAP 请求以进行跟踪;也许您的服务的消费者告诉您他们正在向您发送良好的 SOAP,但您不相信他们,是吗?

    在这种情况下,您应该(暂时)enable trace logging on your service

    如果您尝试进行通用日志记录,请不要打扰 SOAP 数据包,因为它很重;您的日志会迅速膨胀。只需记录重要的东西,例如“添加调用,X=foo,Y=bar”。

    【讨论】:

    • 不幸的是它需要是永久的,所以我不能暂时启用跟踪。
    • @bangoker:虽然您找到了满足您当前需求的解决方案,但我建议您重新考虑您的课程。记录每个 SOAP 请求非常繁重且非常不必要。
    【解决方案2】:

    是的,您可以使用 SoapExtensions 来实现。这是贯穿整个过程的nice article

    【讨论】:

      【解决方案3】:

      SoapExtensions 的替代方法是实现 IHttpModule 并在输入流进入时抓取它。

      public class LogModule : IHttpModule
      {
          public void Init(HttpApplication context)
          {
              context.BeginRequest += this.OnBegin;
          }
      
          private void OnBegin(object sender, EventArgs e)
          {
              HttpApplication app = (HttpApplication)sender;
              HttpContext context = app.Context;
      
              byte[] buffer = new byte[context.Request.InputStream.Length];
              context.Request.InputStream.Read(buffer, 0, buffer.Length);
              context.Request.InputStream.Position = 0;
      
              string soapMessage = Encoding.ASCII.GetString(buffer);
      
              // Do something with soapMessage
          }
      
          public void Dispose()
          {
              throw new NotImplementedException();
          }
      }
      

      【讨论】:

      • 可能很明显,但您可能需要在 web.config 中注册 IHttpModule
      【解决方案4】:

      您也可以阅读contents of the Request.InputStream

      这种方式更有用,例如当您希望根据输入内容在 WebMethod 中执行验证或其他操作时。

      using System;
      using System.Collections.Generic;
      using System.Web;
      using System.Xml;
      using System.IO;
      using System.Text;
      using System.Web.Services;
      using System.Web.Services.Protocols;
      
      namespace SoapRequestEcho
      {
        [WebService(
        Namespace = "http://soap.request.echo.com/",
        Name = "SoapRequestEcho")]
        public class EchoWebService : WebService
        {
      
          [WebMethod(Description = "Echo Soap Request")]
          public XmlDocument EchoSoapRequest(int input)
          {
            // Initialize soap request XML
            XmlDocument xmlSoapRequest = new XmlDocument();
      
            // Get raw request body
            Stream receiveStream = HttpContext.Current.Request.InputStream
      
            // Move to begining of input stream and read
            receiveStream.Position = 0;
            using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
            {
              // Load into XML document
              xmlSoapRequest.Load(readStream);
            }
      
            // Return
            return xmlSoapRequest;
          }
        }
      }
      

      注意:已更新以反映下面 Johns 的评论。

      【讨论】:

      • 你试过这个代码吗?除其他外,我认为您不应该拥有using 块,因为您没有创建StreamStreamReader 也不应该在 using 块中,因为处理它也会关闭流,并且流不属于您。我还质疑这是否会与以后可能配置的任何SoapExtension 互操作。
      • 是的,我试过并且工作正常(尝试点击链接),至于使用或不使用,它只是你想要如何构建代码的程序员选择。
      • @Steven:在这种情况下,您对 using 的看法是错误的。如果是using (var x = new StreamReader()),那将是一个选择——StreamReader 属于你,因为你创建了它。在这种情况下,Stream 属于 Request 对象 - 你没有创建它,所以你不应该在它上面调用 Dispose - 永远。
      • @Steven:很有趣。我原以为反序列化已经将流读到最后。也许这不是原始流,而是请求缓冲内容上的新 MemoryStream。众所周知,ASMX 服务很难处理大量请求,因为内存中保留了请求的副本数量。也许这是其中一个副本的流。否则,我希望它会干扰 SoapExtensions、序列化或过滤器。
      • 当然,您可能就在处理对象,但此时不太可能需要使用流。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2022-10-25
      相关资源
      最近更新 更多