Неопределенные значения перечисления в службе WCF - PullRequest
4 голосов
/ 09 апреля 2009

У нас есть служба WCF, которая предоставляет тип «Клиент», т.е.

[DataContract(Name = "CustomerData", Namespace = "http://www.testing.com")]
public partial class Customer
{   
    [DataMember]
    public CustomerLevel Level
    {
        get;
        set;
    }   
}

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

[IgnoreCoverage]
[DataContract(Namespace = "http://www.testing.com"")]
public enum CustomerLevel : int
{

    [EnumMember(Value = "Platinum")]
    Platinum = 1,

    [EnumMember(Value = "Gold")]
    Gold = 2,

    [EnumMember(Value = "Silver")]
    Silver = 3,

    [EnumMember(Value = "Bronze")]
    Bronze = 4,
}

Служба работает нормально, пока сервер отправляет действительное перечисление для каждого возвращаемого клиента. Однако, если служба возвращает CustomerLevel, который не определен в перечислении, время ожидания вызова службы.

Пример неверного значения CustomerLevel может быть:

customer.Level = (CustomerLevel)0;

Служба также отключается, если клиент пытается отправить неопределенное значение.

Есть ли способ разрешить прохождение неопределенного значения как клиенту, так и серверу, и позволить каждому из них самостоятельно обрабатывать неверное значение?

Ответы [ 5 ]

3 голосов
/ 09 апреля 2009

Я не думаю, что вы получите фиктивные перечисления на работу. Во что они будут десериализоваться? Если вы хотите, чтобы клиент отправлял целые числа, измените тип на int и конвертируйте его в enum самостоятельно (с вашей собственной обработкой ошибок).

Что касается времени ожидания клиента, сообщите нам, какого типа клиент вы используете. Кроме того, я рекомендую вам посмотреть на сетевой трафик и посмотреть, как служба отреагировала, если вообще. Также посмотрите в журналах событий Windows, чтобы увидеть, жаловалась ли служба вообще. Наконец, вы можете включить трассировку WCF, чтобы увидеть, как служба реагирует на это.

2 голосов
/ 18 декабря 2014

Ответом на вопрос, по крайней мере для меня, была установка IsRequired = false. Как это:

[DataMember(IsRequired = false)]
Nullable<MyEnum> Prop {get;set;}

Это правильно добавляет nillble = "true" в wsdl ...

2 голосов
/ 14 августа 2012

Это можно сделать с помощью пользовательского IDataContractSurrogate, чтобы отобразить перечисление в int, а затем обратно в перечисление.

Документация по созданию таких суррогатов находится здесь: http://msdn.microsoft.com/en-us/library/ms733064.aspx

Вот общая версия, которую я разработал, которая может обрабатывать список типов Enum. Вы указываете это в конструкторе для вашего DataContractSerializer. Для получения дополнительной информации см. Мой блог здесь: http://www.shulerent.com/2012/08/13/handling-invalid-enum-values-in-a-datacontractserializer/

/// <summary>
/// IDataContractSurrogate to map Enum to int for handling invalid values
/// </summary>
public class InvalidEnumContractSurrogate : IDataContractSurrogate
{
    private HashSet<Type> typelist;

    /// <summary>
    /// Create new Data Contract Surrogate to handle the specified Enum type
    /// </summary>
    /// <param name="type">Enum Type</param>
    public InvalidEnumContractSurrogate(Type type)
    {
        typelist = new HashSet<Type>();
        if (!type.IsEnum) throw new ArgumentException(type.Name + " is not an enum","type");
        typelist.Add(type);
    }

    /// <summary>
    /// Create new Data Contract Surrogate to handle the specified Enum types
    /// </summary>
    /// <param name="types">IEnumerable of Enum Types</param>
    public InvalidEnumContractSurrogate(IEnumerable<Type> types)
    {
        typelist = new HashSet<Type>();
        foreach (var type in types)
        {
            if (!type.IsEnum) throw new ArgumentException(type.Name + " is not an enum", "type");
            typelist.Add(type);
        }
    }

    #region Interface Implementation

    public Type GetDataContractType(Type type)
    {
        //If the provided type is in the list, tell the serializer it is an int
        if (typelist.Contains(type)) return typeof(int);
        return type;
    }

    public object GetObjectToSerialize(object obj, Type targetType)
    {
        //If the type of the object being serialized is in the list, case it to an int
        if (typelist.Contains(obj.GetType())) return (int)obj;
        return obj;
    }

    public object GetDeserializedObject(object obj, Type targetType)
    {
        //If the target type is in the list, convert the value (we are assuming it to be int) to the enum
        if (typelist.Contains(targetType)) return Enum.ToObject(targetType, obj);
        return obj;
    }

    public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
    {
        //not used
        return;
    }

    public object GetCustomDataToExport(Type clrType, Type dataContractType)
    {
        //Not used
        return null;
    }

    public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
    {
        //not used
        return null;
    }

    public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
    {
        //not used
        return null;
    }

    public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
    {
        //not used
        return typeDeclaration;
    }

    #endregion
}
1 голос
/ 09 апреля 2009

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

Для распространения исключений вы можете попробовать включить «IncludeExceptionDetailsInFaults» - подробности см. В документации MSDN .

Что я обычно делаю, так это реализую серверную часть IErrorHandler, которая регистрирует исключения и продвигает исключения к сбоям - на сайте IDesign есть некоторые полезные вещи .

0 голосов
/ 09 апреля 2009

Попробуйте удалить атрибуты EnumMember из значений перечисления.

Также вам не нужно отмечать ваше перечисление как DataContract, так как DataContractSerializer автоматически сериализует все перечисления, которые вы используете в существующих DataContracts.


То, что я написал выше, не работает. Я не думаю, что можно использовать DataContractSerializer для сериализации недопустимых значений перечисления.

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