Enums И WCF - Значимая Ошибка? - PullRequest
       13

Enums И WCF - Значимая Ошибка?

0 голосов
/ 12 сентября 2009

Я пытаюсь преодолеть проблему с WCF и перечислениями, где я пытаюсь передать объект с сервера клиенту (или другому серверу), который содержит перечисление. Перечисление начинается с 1, специально. Все идет хорошо, когда enum инициализируется и когда значение определено в нем, но когда оно не определено в enum, я получаю это замечательное (и очень описательное (...)) сообщение об ошибке:

"Базовое соединение было закрыто: соединение было неожиданно закрыто."

То, чего я пытаюсь добиться, - это когда я получаю этот сценарий, либо из поврежденных данных в базе данных (которые в любом случае преобразуются в enum, что довольно странно), либо когда разработчик забыл установить значение enum при запуске объект, чтобы получить осмысленное сообщение, что-то вроде «Недопустимое значение Enum, введите: {0}, значение: {1}».

Я попытался использовать «Enum.IsDefined» на установщике и получателе перечисления в классе и выдать значимое исключение клиенту (или другому серверу), но все еще получил «соединение закрыто» ошибка (при отладке сервера я получаю осмысленное сообщение, но только на стороне сервера).

Вот фрагмент установщика и получателя перечисления:

    private TestEnum m_TestEnum;

    [DataMember]
    public TestEnum TestEnum 
    {
        get
        {
            if (Enum.IsDefined(typeof(TestEnum), m_TestEnum))
            {
                return m_TestEnum;
            }
            else
            {
                throw new ApplicationException("Enum value is not valid: " + m_TestEnum);
            }
        }
        set
        {
            if (Enum.IsDefined(typeof(TestEnum), value))
            {
                m_TestEnum = value;
            }
            else
            {
                throw new ApplicationException("Enum value is not valid: " + value);
            }
        }
    }

Начало перечисления с 0 (со значением "Неизвестно") недостаточно, поскольку я все еще могу получить значения, которых нет в перечислении. Я могу объединить оба решения, где я проверяю «IsDefined» и устанавливаю для перечисления значение «Неизвестно», но все же - это не идеальное решение, так как мы хотим знать об этих случаях, чтобы решать их в цикле разработки .

Что вы говорите? Спасибо, Nir.

Ответы [ 2 ]

5 голосов
/ 12 сентября 2009

При отправке перечислений через WCF отправляется строковое представление значения перечисления, а не числовое значение. Это позволяет обеим сторонам отображать одну и ту же метку перечисления на разные номера.

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

Таким образом, только то, что метка enum действительна на стороне отправителя, не означает, что клиент обязательно это поймет.

Используете ли вы одно и то же определение класса для отправителя и получателя?

Чтобы продолжить отладку этой проблемы, вы должны включить трассировку службы на клиенте и сервере (это верно для многих проблем с WCF. Это поможет вам определить источник проблемы, если в противном случае у вас нет никаких указаний.

Добавьте следующий XML-файл в файл App.config (как на клиенте, так и на сервере):

<configuration>
   <system.diagnostics>
      <sources>
            <source name="System.ServiceModel" 
                    switchValue="Information, ActivityTracing"
                    propagateActivity="true">
            <listeners>
               <add name="traceListener" 
                   type="System.Diagnostics.XmlWriterTraceListener" 
                   initializeData= "WcfTrace.svclog" />
            </listeners>
         </source>
      </sources>
   </system.diagnostics>
</configuration>

Есть несколько опций для этой конфигурации .

После добавления этой конфигурации вы создадите файл .svclog, который можно просмотреть с помощью Service Trace Viewer Tool . Этот журнал содержит много информации обо всем, что происходит, включая предупреждения и ошибки.

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


Обратите внимание, что вы можете указать различные строковые значения для элементов enum, которые будут использоваться в проводе.

Например, следующие два перечисления эквивалентны WCF:

public enum CarCondition
{
    New,
    Used,
    Rental,
    [NonSerialized]
    Lost
}    

[DataContract(Name = "CarCondition")]
public enum CarConditionWithDifferentNames
{
    [EnumMember(Value = "New")]
    BrandNew,
    [EnumMember(Value = "Used")]
    PreviouslyOwned,
    [EnumMember]
    Rental
} 

Вы можете прочитать более подробную информацию об использовании перечислений поверх WCF здесь .

1 голос
/ 25 февраля 2010

Ну, проблема в том, что сериализация не может сериализовать значение, которое не определено в перечислении, и это включает значение (по умолчанию) 0.

Например:

enum E
{
    New = 1,
    Used
}


[OperationContract]
public E Method()
{
    E e;
    return e;
}

Вызов метода не удастся, поскольку «e» инициализируется как «e = (E) 0». Когда сериализация пытается выполнить свою работу, она не находит в E поле, которое соответствует 0, поэтому происходит сбой (или генерируется XML-файл, который не соответствует wsdl, который ограничивает значения членами enum).

Таким образом, мы должны убедиться, что наш сервисный метод всегда возвращает допустимые значения (согласно определению enum).

Я не видел, чтобы об этом говорили в MSDN, так что это мой собственный вывод после моих тестов.

Надеюсь, это поможет, Хосе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...