C# 客户端未处理.NET远程处理异常

C# 客户端未处理.NET远程处理异常,c#,.net,exception-handling,remoting,C#,.net,Exception Handling,Remoting,我检查了其余的远程处理问题,而这个具体案例似乎没有得到解决 我已经安装了.NET远程处理服务器/客户端。在服务器端,我有一个对象和一个方法,该方法可以引发异常,还有一个客户端将尝试调用该方法 服务器: public bool MyEquals(Guid myGuid, string a, string b) { if (CheckAuthentication(myGuid)) { logger.Debug("Request for \"" + a + "\".Eq

我检查了其余的远程处理问题,而这个具体案例似乎没有得到解决

我已经安装了.NET远程处理服务器/客户端。在服务器端,我有一个对象和一个方法,该方法可以引发异常,还有一个客户端将尝试调用该方法

服务器:

public bool MyEquals(Guid myGuid, string a, string b)
{
    if (CheckAuthentication(myGuid))
    {
        logger.Debug("Request for \"" + a + "\".Equals(\"" + b + "\")");
        return a.Equals(b);
    }
    else
    {
        throw new AuthenticationException(UserRegistryService.USER_NOT_REGISTERED_EXCEPTION_TEXT);
    }
}
客户:

try
{
    bool result = RemotedObject.MyEquals(myGuid, "cat", "dog");
}
catch (Services.Exceptions.AuthenticationException e)
{
    Console.WriteLine("You do not have permission to execute that action");
}
当我使用导致CheckAuthentication返回false的Guid调用MyEquals时,.NET尝试抛出异常并表示AuthenticationException未处理。这种情况发生在服务器端。异常从未被封送到客户端,我也不知道为什么。我所看到的所有问题都解决了客户端处理异常的问题,但它不是自定义异常,而是基类型。在我的情况下,我甚至不能得到任何异常来跨越远程处理边界到客户端。这是AuthenticationException的副本。它位于服务器和客户端之间的共享库中

[Serializable]
public class AuthenticationException : ApplicationException, ISerializable
{

    public AuthenticationException(string message)
        : base(message)
    {
    }

    public AuthenticationException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }

    #region ISerializable Members

    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
    }

    #endregion
}
尝试在客户端捕获(异常),并检查捕获的异常类型以及任何内部异常。这可能会提供一些线索

其他一些评论:

  • ApplicationException已弃用。您通常应该从System.Exception派生

  • 我通常会将[Serializable]属性添加到自定义异常中。不确定这是否重要

  • 通常应该重写System.Exception.GetObjectData,而不是显式实现ISerializable.GetObjectData。在您的情况下,您没有序列化任何其他数据,因此我既不会覆盖它,也不会显式地实现它。同样,我不确定这是否会有任何影响

我的可序列化自定义异常模板如下所示,并且我在远程连接上的序列化方面没有遇到任何问题

[Serializable]
public class CustomException : Exception
{

/// <summary>
/// Initializes a new instance of the <see cref="CustomException"/> class.
/// </summary>
public CustomException()
{
}

/// <summary>
/// Initializes a new instance of the <see cref="CustomException"/> class with
/// a specified error message.
/// </summary>
public CustomException(string message) : base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CustomException"/> class with
/// a specified error message and a reference to the inner exception that is a cause
/// of this exception.
/// </summary>
public CustomException(string message, Exception inner) : base(message, inner)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CustomException"/> class with
/// serialized data.
/// </summary>
protected CustomException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}

}
[可序列化]
公共类CustomException:异常
{
/// 
///初始化类的新实例。
/// 
公共自定义例外()
{
}
/// 
///使用初始化类的新实例
///指定的错误消息。
/// 
公共自定义异常(字符串消息):基本(消息)
{
}
/// 
///使用初始化类的新实例
///指定的错误消息和对内部异常的引用是原因
///这是一个例外。
/// 
公共CustomException(字符串消息,内部异常):基本(消息,内部)
{
}
/// 
///使用初始化类的新实例
///序列化数据。
/// 
受保护的CustomException(SerializationInfo,StreamingContext上下文):基本(信息,上下文)
{
}
}
更新

此外,如果您在IIS中托管服务器代码,则需要在web.config中执行以下操作,以允许异常传播到客户端:

  <system.web>
    ...
    <customErrors mode="Off" /> 
    ...

...
...
首先。这个建议已经存在了一段时间,我相信FxCop会自动生成一条关于这个的消息


接下来,您通常应该使用
[Serializable]
属性来修饰自定义异常。我认为这是您的主要问题,因为我在方法调用中遇到了一个异常,表示AuthenticationException未标记为可序列化。

此错误有不同的原因,您提到的不止一个

我注意到这个错误的另一个原因;此时远程调用的远程对象的构造函数抛出异常。由于对象本身当时未初始化,因此未序列化异常。我认为您应该避免任何可能导致在远程对象的构造函数中抛出自定义异常的代码。如果在构造函数内执行代码期间引发了系统异常,则应将其作为系统错误(未知)处理,并使用文件系统或其他方式构建一种机制来存储该异常的详细信息


net远程处理在过去听起来确实很吸引人,但是项目越大,代码中引入的概念越多,这项技术暴露出的弱点就越多。这是一项很好的技术,但您需要大量的经验才能从中生成一个强大的解决方案。

啊,是的。以下是FxCop的消息:警告:CA1058:Microsoft。设计:更改“AuthenticationException”的基本类型,使其不再扩展“ApplicationException”。此基本异常类型不为框架类提供任何附加值。改为扩展“System.Exception”或现有的未密封异常类型。不要创建新的异常基类型,除非在为整个异常类启用捕获处理程序时有特定的值。Ah。我很抱歉。我抄课时忘了写那一行。我确实用[Serializable]装饰了我的异常。我正在阅读你在上面对Joe的评论,关于没有在客户端捕获异常。我已经快速组装了一个快速远程服务器和客户端工具,它每次都被客户端捕获,而不是在服务器上。我会问几个更符合条件的问题,希望能引导我们解决这个谜#1:保存MyEquals的类是MarshalByRefObject的后代吗?如果不是,则应该这样做,以便正确地通过远程处理对其进行编组#2:你是如何托管服务器的?IIS、Windows服务或只是一个要测试的独立应用程序?对您的问题的回答(感谢您耐心等待,甚至还准备了一个测试应用程序)#1:是的,MyEquals属于MarshallByRefObject派生的类。它是那个物体的孙子,但我猜这不会引起问题#2:我正在使用一个独立的测试应用程序。但是,此控制台应用程序在另一个dll程序集中构造远程对象,因此可以在以后将远程对象绑定到Windows服务。此外,我自己构建了一个测试应用程序,我也有同样的问题。在服务器端,我有一个抛出