【问题标题】:How do I copy a HttpRequest to another web service?如何将 HttpRequest 复制到另一个 Web 服务?
【发布时间】:2012-01-09 16:09:31
【问题描述】:

我目前在同一台 PC 上安装了两个相同的 Web 服务,用于测试目的。第一个服务收到的请求也应该转到第二个服务。我的意图是使用 HttpModule 来做到这一点。我在 application.BeginRequest 期间处理请求。

public void AsyncForwardRequest(HttpRequest request)
{
    try
    {
        // Prepare web request...
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(WSaddress);

        req.Credentials = CredentialCache.DefaultCredentials;
        req.Headers.Add("SOAPAction", request.Headers["SOAPAction"]);
        req.ContentType = request.Headers["Content-Type"];
        req.Accept = request.Headers["Accept"];
        req.Method = request.HttpMethod;

        // Send the data.
        long posStream = request.InputStream.Position;
        long len = request.InputStream.Length;
        byte[] buff = new byte[len];
        request.InputStream.Seek(0, SeekOrigin.Begin);
        if (len < int.MaxValue && request.InputStream.Read(buff, 0, (int)len) > 0)
        {
            using (Stream stm = req.GetRequestStream())
            {
                stm.Write(buff, 0, (int)len);
            }

            request.InputStream.Position = posStream;
            DebugOutputStream(request.InputStream);
            request.InputStream.Seek(0, SeekOrigin.Begin);

            IAsyncResult result = (IAsyncResult)req.BeginGetResponse(new AsyncCallback(RespCallback), req);
        }
    }
    catch (Exception ex)
    {

        App.Error2(String.Format("RequestDuplicatorModule - BeginRequest; ERROR begin request: {0}", ex.Message), ex);
    }

private static void RespCallback(IAsyncResult asynchronousResult)
{
    try
    {
        // State of request is asynchronous.
        var req = (HttpWebRequest)asynchronousResult.AsyncState;
        WebResponse resp = (HttpWebResponse)req.EndGetResponse(asynchronousResult);

        Stream responseStream = resp.GetResponseStream();
        System.IO.Stream stream = responseStream;
        Byte[] arr = new Byte[1024 * 100];
        stream.Read(arr, 0, 1024 * 100);
        if (arr.Length > 0)
        {
            string body = (new ASCIIEncoding()).GetString(arr);
            Debug.Print(body);
        }
    }
    catch (WebException ex)
    {
        App.Error2(String.Format("RequestDuplicatorModule - BeginRequest; ERROR begin request: {0}", ex.Message), ex);
    }

}

此 (HttpWebResponse)req.EndGetResponse(asynchronousResult) 抛出异常:500 Internal Server Error 并失败。原始请求顺利通过。

request.InnerStream: ...

这是否与 Web 服务地址不同有关?就我而言,它们是: http://localhost/WS/service.asmx http://localhost/WS_replicate/service.asmx

【问题讨论】:

    标签: c# asp.net web-services httpwebrequest web


    【解决方案1】:

    我至少会实现这一点,以便能够读取状态为 500 的 httpwebrequest 的内容:

    catch (WebException ex)
    {
        HttpWebResponse webResponse = (HttpWebResponse)ex.Response;
        Stream dataStream = webResponse.GetResponseStream();
    
        if (dataStream != null)
        {
            StreamReader reader = new StreamReader(dataStream);
            response = reader.ReadToEnd();
        }
    }
    

    虽然没有回答您的问题,但我建议使用一个简单的 amsx 来读取请求,并将请求发布到两个不同的 Web 服务。如果您需要一些代码,请告诉我。

    另外的优点是 asmx 将更容易为开发人员以及处理部署的人员提供支持。您可以添加配置选项以使实际 url 动态化。

    【讨论】:

    • 好主意!现在我知道我的假设是正确的。问题出在 Wsa:To 字段中,该字段当然没有指向正确的 URI。在这种情况下,它应该指向第二个 asmx。现在我必须弄清楚如何为异步请求更改它。
    • 这里是异常本身: 标头必须与 Web 服务的参与者 URI 值匹配。可以使用 ASMX 类上的 SoapActorAttribute 显式指定参与者 URI 值。在没有该属性的情况下,假定参与者 URI 等于传入消息的 HTTP 请求 URL。接收到的 标头包含“localhost/WS/Service.asmx”,而接收者期待“localhost/ws_replicate/service.asmx”。
    • 我想我解决了这个问题,但它可能不是最好的解决方案。在 WS_Replicate/Service.cs 中,我添加了 [Microsoft.Web.Services3.Messaging.SoapActor("*")] 以避免将请求 URI 与 Wsa:To 字段进行比较。复制现在可以工作了。我仍然非常希望听到有关改进此解决方案的其他意见。
    【解决方案2】:

    能够修改 AsyncForwardRequest 方法,以便我可以实际编辑 SoapEnvelope 本身:

    string buffString = System.Text.UTF8Encoding.UTF8.GetString(buff);
    
    using (Stream stm = req.GetRequestStream())
    {
        bool stmIsReadable = stm.CanRead;  //false, stream is not readable, how to get
                                           //around this?
                                           //solution: read Byte Array into a String,
                                           //modify <wsa:to>, write String back into a
                                           //Buffer, write Buffer to Stream
    
        buffString = buffString.Replace("http://localhost/WS/Service.asmx", WSaddress);
    
        //write modded string to buff
        buff = System.Text.UTF8Encoding.UTF8.GetBytes(buffString);
    
        stm.Write(buff, 0, (int)buff.Length);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-09
      • 1970-01-01
      • 1970-01-01
      • 2023-02-03
      • 2012-02-19
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多