Исключение удаленного взаимодействия .NET не обрабатывается на стороне клиента

Я проверил остальные вопросы по удаленному взаимодействию, и этот конкретный случай, похоже, не рассматривался.

У меня настроен сервер / клиент .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");
}

Когда я вызываю MyEquals с Guid, из-за чего 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
}

person Dan Joseph    schedule 30.09.2009    source источник


Ответы (3)


Прежде всего, не наследуются от ApplicationException < / а>. Этот совет существует уже некоторое время, и я считаю, что FxCop автоматически сообщит об этом.

Затем вы обычно должны украсить собственное исключение атрибутом [Serializable]. Я думаю, что это ваша основная проблема, поскольку я получаю исключение при вызове метода, в котором говорится, что AuthenticationException не помечен как сериализуемый.

person Jesse C. Slicer    schedule 30.09.2009
comment
О да. Вот сообщение FxCop: предупреждение: CA1058: Microsoft.Design: измените базовый тип AuthenticationException, чтобы он больше не расширял ApplicationException. Этот базовый тип исключения не предоставляет дополнительных значений для классов инфраструктуры. Вместо этого расширьте System.Exception или существующий незапечатанный тип исключения. Не создавайте новый базовый тип исключения, если нет особого значения в разрешении создания обработчика catch для всего класса исключений. - person Jesse C. Slicer; 30.09.2009
comment
Ах. Мне жаль. Я забыл включить эту строку при копировании моего класса. Я украсил свое исключение [Serializable]. - person Dan Joseph; 30.09.2009
comment
Я читаю ваш комментарий Джо выше относительно того, что исключение не было обнаружено на стороне клиента. Я собрал вместе быстрый сервер удаленного взаимодействия и клиентский жгут, и каждый раз он ловится на стороне клиента, а НЕ на сервере. Я задам еще пару уточняющих вопросов, которые, надеюсь, помогут нам разгадать эту загадку. №1: Является ли класс, содержащий MyEquals, потомком MarshalByRefObject? В противном случае это должно быть так, чтобы он правильно упорядочивал удаленное взаимодействие. # 2: Как вы размещаете сервер? IIS, служба Windows или просто отдельное приложение для тестирования? - person Jesse C. Slicer; 30.09.2009
comment
Ответы на ваши вопросы (кстати, спасибо за проявленное терпение и даже за создание тестового приложения) №1: Да, MyEquals находится в классе, который происходит от MarshalByRefObject. Это внук того объекта, но я полагаю, что это не вызовет проблемы. №2: Я использую автономное тестовое приложение. Однако это консольное приложение создает удаленный объект внутри другой сборки DLL, поэтому удаленный объект может быть привязан к службе Windows позже. - person Dan Joseph; 30.09.2009
comment
Кроме того, я сам создал тестовое приложение, и у меня такая же проблема. На стороне сервера у меня есть метод, который генерирует CustomException. выбросить новое CustomException (); следуя этой модели класса выше. Я по-прежнему получаю ту же ошибку, что CustomException не было обработано пользовательским кодом на сервере и ничего не было на клиенте. - person Dan Joseph; 30.09.2009
comment
Я такой тупой! Я даже не подумал об этом: у меня был отладчик Visual Studio для перехвата необработанных исключений первого экземпляра. Итак, Visual Studio вмешалась раньше, чем смог мой клиент. Отключенный отладчик Visual Studio: отлично работает! Тем не менее, спасибо за помощь. - person Dan Joseph; 30.09.2009
comment
У меня есть скрытое подозрение, что это консольное приложение создает удаленный объект внутри другой сборки dll, что может быть связано с причиной. Сконструированный объект должен быть обернут объектом, предоставляемым вашим сервером, а затем этот объект должен перехватить и повторно вызвать исключение. - person Jesse C. Slicer; 01.10.2009
comment
Хех. Тогда игнорируйте мой последний комментарий. Рад, что у вас все получилось! - person Jesse C. Slicer; 01.10.2009

Попробуйте 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" /> 
    ...
person Joe    schedule 30.09.2009
comment
Я реализовал свое исключение AuthenticationException для вашего настраиваемого шаблона исключения. Исключение по-прежнему НИКОГДА не обнаруживалось на стороне клиента. Сервер, остановленный из-за AuthenticationException, не был обработан пользовательским кодом. Должен ли я указывать серверному приложению, что есть клиент, желающий и ожидающий обработки любых возникших исключений? - person Dan Joseph; 30.09.2009
comment
Надо ли указывать серверу приложение ... - см. Обновление выше - person Joe; 01.10.2009

Есть разные причины этой ошибки, и вы, ребята, упомянули более пары.

Я заметил другую причину этой ошибки; и это когда конструктор удаленного вызываемого объекта выдает исключение и исключение. исключения не сериализуются, потому что сам объект в этот момент не был инициализирован. Я считаю, что вам следует избегать ЛЮБОГО кода, который может вызвать создание пользовательского исключения внутри конструктора удаленного объекта. и если во время выполнения кода внутри конструктора возникло системное исключение, вы должны обработать его как системную ошибку (неизвестную) и создать механизм для хранения деталей этого исключения, используя файловую систему или что-то еще.

В те дни удаленное взаимодействие .net казалось действительно привлекательным, но чем больше становится ваш проект и чем больше концепций вы вводите в свой код, тем больше слабостей обнаруживает эта технология. это хорошая технология, но вам нужен большой опыт, чтобы сделать из нее надежное решение.

person lilmoe    schedule 25.04.2010