我检查了其余的远程问题,这个具体案例似乎没有得到解决。
我有一个.NET Remoting服务器/客户端设置。在服务器端,我有一个对象,它有一个可以抛出异常的方法,以及一个试图调用该方法的客户端。
服务器:
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");
}
当我使用Guid调用MyEquals导致CheckAuthentication返回false时,.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
}
答案 0 :(得分:1)
在客户端尝试catch(Exception),并检查被捕获的异常的类型以及任何内部异常。它可能会提供一些线索。
其他一些评论:
不推荐使用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)
{
}
}
<强>更新强>
此外,如果您在IIS中托管服务器代码,则需要在web.config中使用以下内容以允许异常传播到客户端:
<system.web>
...
<customErrors mode="Off" />
...
答案 1 :(得分:1)
首先,do not inherit from ApplicationException。这个建议已经存在了一段时间,我相信FxCop会自动生成一条消息。
接下来,您通常应使用[Serializable]
属性修饰自定义异常。我认为这是你的主要问题,因为我在方法调用上得到一个异常,说AuthenticationException没有被标记为可序列化。
答案 2 :(得分:0)
这个错误有不同的原因,你们提到的不仅仅是一对。
我注意到了这个错误的另一个原因;那就是远程调用远程对象的构造函数抛出异常的时候。异常没有被序列化,因为对象本身在那时没有被初始化。我相信你应该避免任何可能导致自定义异常被抛入远程对象的构造函数中的代码。如果在构造函数内部执行代码期间抛出了系统异常,则应将其作为系统错误(未知)处理,并构建一种机制来使用文件系统或其他任何方式存储该异常的详细信息。
.net remoting在这些日子里听起来真的很吸引人,但是你的项目越大,你引入代码的概念就越多,这项技术就会显示出越多的弱点。这是一项很好的技术,但你需要很多经验来制定一个强大的解决方案。