【问题标题】:I keep getting WCF service is in faulted state on the client side. How should I catch WCF exceptions, without breaking my WCF service?我不断收到 WCF 服务在客户端处于故障状态。我应该如何在不破坏 WCF 服务的情况下捕获 WCF 异常?
【发布时间】:2012-01-01 04:28:33
【问题描述】:

我有多个 UI 使用的 WCF 服务。当用户无法访问数据库时,我从数据库中得到未经授权的异常。我没有在服务器端捕获异常并将其发送给客户端。

在客户端(asp.net 网页)上,我看到异常 - 用户无法访问数据库,登录失败。 这一切都很好。 但是......如果我再次调用 WCF 服务,我会得到服务处于故障状态的异常。唯一打开就是重启整个WCF服务。 WCF 服务作为 Windows 服务托管。

在不中断服务的情况下,捕获异常、在服务器端记录异常、将异常详细信息发送回客户端的最佳方法是什么?谢谢

【问题讨论】:

  • 尝试使用 faultcontract。

标签: c# asp.net wcf


【解决方案1】:

未处理的异常会使通信通道出错。正如其他人指出的那样,必须通过调用 Abort() 中止出现故障的通道 - 它不能关闭,也不能再次使用。

要解决您问题的另一部分,“捕获异常的最佳方法,在服务器端记录异常,在不中断服务的情况下将异常详细信息发送回客户端?”,您需要使用FaultException Class .

此外,您可以使用IErrorHandler Interface 连接您的服务主机以捕获任何未被捕获的异常(即全局错误处理程序)。网上有很多关于如何执行此操作的示例 - 只需 google 即可获得 WCF IErrorHandler。

这是一对:

WCF Exception Handling with IErrorHandler

WCF Extensibility – IErrorHandler

【讨论】:

  • 谢谢。我什么时候应该捕获异常并抛出错误异常?在操作合同或创建服务主机对象的 Windows 服务 onstart 代码中?
  • 你会在服务中捕获异常,将其序列化为错误契约,然后客户端(或 Windows 服务)可以在 try-catch 块中捕获错误异常。
【解决方案2】:

您可以使用此代码创建一个能够正确处理 WCF 异常的包装类:

public class ServiceProxyHelper<TProxy, TChannel> : IDisposable
    where TProxy : ClientBase<TChannel>, new()
    where TChannel : class
{
    ///
    /// Private instance of the WCF service proxy.
    ///
    private TProxy _proxy;

    ///
    /// Gets the WCF service proxy wrapped by this instance.
    ///
    public TProxy Proxy
    {
        get
        {
            if (_proxy != null)
            {
                return _proxy;
            }
            else
            {
                throw new ObjectDisposedException("ServiceProxyHelper");
            }
        }
    }

    public TChannel Channel { get; private set; }

    ///
    /// Constructs an instance.
    ///
    public ServiceProxyHelper()
    {
        _proxy = new TProxy();
    }

    ///
    /// Disposes of this instance.
    ///
    public void Dispose()
    {
        try
        {
            if (_proxy != null)
            {
                if (_proxy.State != CommunicationState.Faulted)
                {
                    _proxy.Close();
                }
                else
                {
                    _proxy.Abort();
                }
            }
        }
        catch (CommunicationException)
        {
            _proxy.Abort();
        }
        catch (TimeoutException)
        {
            _proxy.Abort();
        }
        catch (Exception)
        {
            _proxy.Abort();
            throw;
        }
        finally
        {
            _proxy = null;
        }
    }
}

然后您可以像这样调用服务:

using (ServiceProxyHelper<EmailServiceClient, EmailService> svc =
   new ServiceProxyHelper<EmailServiceClient, EmailService>())
{
   svc.Proxy.SendMail(fromAddress, fromName, toEmail, toName, message);
}

【讨论】:

    【解决方案3】:

    请参阅以下链接,其中讨论了 WCF 客户端应如何捕获错误/异常以及您在 C# 中使用“using”语句可能遇到的潜在问题:

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

    基本上,您需要在客户端代理上调用 Abort()。这将立即将代理的状态设置为已关闭。

    【讨论】:

    • 哦,太好了。你认为从 wcf 服务向客户端抛出异常可以吗?
    • 我认为这实际上取决于您正在构建的应用程序的类型以及您的整体异常处理策略是什么。话虽如此,如果这是一个面向最终用户的应用程序,您可能希望让他们知道出了点问题。
    猜你喜欢
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 2011-04-16
    • 1970-01-01
    • 2014-09-22
    相关资源
    最近更新 更多