【问题标题】:How to check errors from asynchronous Web Services calls如何检查来自异步 Web 服务调用的错误
【发布时间】:2009-02-26 09:17:38
【问题描述】:

我正在开发 ASP.Net asmx Web 服务。而在客户端,如果对服务器的请求返回 Http 错误代码,例如 http 500,我如何从 Web 服务客户端知道(我通过添加 Web 引用使用自动生成的客户端代理)?

提前致谢, 乔治

【问题讨论】:

  • 可能值得在问题标题/描述中说明您特别询问的有关异步调用的问题
  • 遇到同样的问题,HTTP 500 响应没有抛出异常。

标签: c# web-services asynchronous error-handling


【解决方案1】:

George,由于您使用的是异步 WS 调用,因此您必须在回调方法中实现异常处理。 例如: 以下是我为演示异步委托而开发的示例代码。

public class TransformDelegateWithCallBack
{
    /// <summary>
    /// Delegate which points to AdapterTransform.ApplyFullMemoryTransformations()
    /// </summary>
    /// <param name="filename">Transformation file name</param>
    /// <param name="rawXml">Raw Xml data to be processed</param>
    /// <param name="count">Variable used to keep a track of no of async delegates</param>
    /// <returns>Transformed XML string</returns>
    public delegate string DelegateApplyTransformations(string filename, string rawXml, int count);

    public ArrayList resultArray;


    //// Declare async delegate and result
    DelegateApplyTransformations delegateApplyTransformation;
    IAsyncResult result;

    /// <summary>
    /// Constructor to initialize the async delegates, results and handles to the no of tabs in excel
    /// </summary>
    public TransformDelegateWithCallBack()
    {
        resultArray = ArrayList.Synchronized(new ArrayList());
    }


    /// <summary>
    /// Invoke the async delegates with callback model
    /// </summary>
    /// <param name="filename">Transformation file name</param>
    /// <param name="rawXml">Raw Xml data to be processed</param>
    /// <param name="count">Variable used to keep a track of no of async delegates</param>
    public void CallDelegates(string fileName, string rawXml, int count)
    {
        try
        {
            AdapterTransform adapterTrans = new AdapterTransform();
            // In the below stmt, adapterTrans.ApplyFullMemoryTransformations is the web method being called
            delegateApplyTransformation = new DelegateApplyTransformations(adapterTrans.ApplyFullMemoryTransformations);
            // The below stmt places an async call to the web method
            // Since it is an async operation control flows immediately to the next line eventually coming out of the current method. Hence exceptions in the web service if any will NOT be caught here.
            // CallBackMethod() is the method that will be called automatically after the async operation is done
            // result is an IAsyncResult which will be used in the CallBackMethod to refer to this delegate
            // result gets passed to the CallBackMethod 
            result = delegateApplyTransformation.BeginInvoke(fileName, rawXml, count, new AsyncCallback(CallBackMethod), null);
        }
        catch (CustomException ce)
        {
            throw ce;
        }
    }

    /// <summary>
    /// Callback method for async delegate
    /// </summary>
    /// <param name="o">By default o will always have the corresponding AsyncResult</param>
    public void CallBackMethod(object o)
    {

        try
        {
            AsyncResult asyncResult = (AsyncResult)o;
            // Now when you do an EndInvoke, if the web service has thrown any exceptions, they will be caught
            // resultString is the value the web method has returned. (Return parameter of the web method)
            string resultString = ((DelegateApplyTransformations)asyncResult.AsyncDelegate).EndInvoke((IAsyncResult)asyncResult);

            lock (this.resultArray.SyncRoot)
            {
                this.resultArray.Add(resultString);
            }
        }
        catch (Exception ex)
        {
            // Handle ex
        }
    }

}

如果您的 WS 调用抛出异常,它只会在您对 AsynResult 执行 EndInvoke 时被捕获。如果您使用的是异步 WS 调用的触发和忘记机制,您将不会调用 EndInvoke,因此将丢失异常。所以当你需要捕获异常时,总是使用回调机制 希望这会有所帮助:)

如果您还有任何疑问,请告诉我。

【讨论】:

  • 谢谢 Rashmi,对不起,我有一个非常愚蠢的问题,您代码中的哪个方法用作我们调用的 Web 方法?
  • “如果你的 WS 调用抛出异常,它只会在你对 AsynResult 执行 EndInvoke 时才会被捕获”——很困惑。我想在使用异步 Web 服务调用时,底层的 Web 服务栈会自动帮助我调用 Begin/EndInvoke,所以不需要再次调用?
  • delegateApplyTransformation = new DelegateApplyTransformations(adapterTrans.ApplyFullMemoryTransformations); adapterTrans.ApplyFullMemoryTransformations 是正在调用的 Web 方法。
  • George,我已经编辑了上面的代码以添加适当的 cmets,因为 cmets 部分没有足够的空间。
  • @RashmiPandit,有没有办法使用 Visual Studio 生成的标准 SoapClient 获取 HTTP 500 错误异常?下面的代码使用原始 XML,并且想知道 EndInvoke 是否也可以与 SoapClient 代理一起使用。
【解决方案2】:

您可以为您的 Web 服务设置跟踪,下面是 MSDN 中的操作方法:

http://msdn.microsoft.com/en-us/library/bb885203.aspx

如果您也可以访问服务器,您可以设置 HealthMonitoring,例如,它将记录服务器端发生的任何错误,例如您发布 500 内部服务器错误。

健康监测 - http://msdn.microsoft.com/en-us/library/ms998306.aspx

如果您可以远程或登录到服务器,您还可以使用非常有用的事件查看器。

希望这会有所帮助:

安德鲁

【讨论】:

  • 您好 Andrew,您的解决方案是在服务器端,但我想在客户端进行跟踪。
【解决方案3】:

您可以从 e.Response.GetResponseStream() 获取信息。如前所述,您可能需要查看服务器端以获得更完整的信息。

【讨论】:

  • 好主意!但是由于我使用的是异步 Web 服务调用,所以在完整的事件处理程序中,我如何获取 Response 对象?
【解决方案4】:

这是一个经常遇到的问题,因为 Web 服务往往只会在遇到未处理的异常时向您发送 HTTP 500(内部服务器错误)消息。我使用了很久以前发现的一个技巧。基本上,您需要使用 StreamReader 深入研究 WebException 以确定异常的根本原因。

示例代码:(抱歉,手头没有任何 C# 代码。请使用转换器)

Try
  'Hit the webservice.
Catch ex As WebException
  Dim r As HttpWebResponse = CType(ex.Response(), HttpWebResponse)
  Using sr As StreamReader = New StreamReader(r.GetResponseStream())
    Dim err As String = sr.ReadToEnd()
    'Log the error contained in the "err" variable.
  End Using
  Return Nothing
Finally
  'Clean up  
End Try

可以使用DeveloperFusion converter 进行转换,我强烈推荐。

【讨论】:

  • 你的代码非常非常酷!但是由于我使用的是异步 Web 服务调用,所以在完整的事件处理程序中,我如何获取 Response 对象?
  • Response 对象是从被捕获的 Exception 中提取出来的。你收到异常了吗? P.S:如果答案很酷,请投票! ;-)
  • 我所能得到的只是来自客户端的 ArgumentNullException。内容为,[System.ArgumentNullException] = {"Value cannot be null.\r\nParameter name: stream"}
  • 我认为发生这种异常是因为服务器向客户端发送了无效的 SOAP 响应格式(它发送用户友好的 html 消息)?如果我能得到用户友好的 html 消息的内容,那就太好了!有什么想法吗?
【解决方案5】:

查看上一个问题,easy-way-to-catch-all-unhandled-exceptions-in-c-net

对于在 IIS 下运行的 Web 服务,您似乎需要通过实现 UnhandledExceptionModule 来捕获所有线程中的异常。

【讨论】:

  • 解决方案是针对服务器端错误处理,我的问题是关于如何从客户端获取错误,更具体地说是基于 Web 服务代理的客户端应用程序。 :-)
【解决方案6】:

假设您有 Visual Studio 导入 web 服务并且您使用 Microsoft Web Services Enhancement 3.0 库,它可能看起来像这样:

 private void DoWebService()
 {
      try
      {
           MyWebService.MyWebserviceWSE WSE = new MyWebService.MyWebserviceWSE.MyWebserviceWSE();

           WSE.DoSomethingCompleted += new MyWebService.DoSomethingCompletedEventHandler(WSE_DoSomethingCompleted);

           WSE.DoSomethingAsync(/* pass arguments to webservice */);            
      }
      catch (Exception ex)
      {
           // Handle errors
      }
 }

 private void WSE_DoSomethingCompleted(object o, MyWebService.DoSomethingCompletedEventArgs args)
 {
      if (args.Error != null)
      {
           // The following gets the error and shows it in a msg box
           StringBuilder sb = new StringBuilder();

           sb.AppendLine(args.Error.ToString());

           if (args.Error.InnerException != null)
           {
               sb.AppendLine(args.Error.ToString());
           }

           MessageBox.Show(sb.ToString());
      }
      else
      {
           // Do something with the results
      }
 }

任何错误都将在“MyWebService.DoSomethingCompletedEventArgs”对象中返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    • 2012-12-05
    相关资源
    最近更新 更多