Обработка исключений сериализации в ServiceStack - PullRequest
4 голосов
/ 18 ноября 2011

Я использую ServiceStack для создания службы, которая принимает запрос и HTML-форму (POSTed).Одним из свойств DTO является Enum, и когда входные данные не соответствуют членам Enum, я получаю следующее исключение:

Error occured while Processing Request: KeyValueDataContractDeserializer: Error converting to type: Requested value 'MyValue' was not found.
System.Runtime.Serialization.SerializationException: KeyValueDataContractDeserializer: Error converting to type: Requested value 'MyValue' was not found. ---> System.ArgumentException: Requested value 'MyValue' was not found.
   at System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)
   at System.Enum.Parse(Type enumType, String value, Boolean ignoreCase)
   at ServiceStack.ServiceModel.Serialization.StringMapTypeDeserializer.PopulateFromMap(Object instance, IDictionary`2 keyValuePairs) 

Как я могу перехватить это исключение и обработать его самостоятельно в своем сервисном коде

1 Ответ

3 голосов
/ 18 ноября 2011

Есть несколько способов справиться с этой ситуацией:

Вы можете сделать свойство DTO Enum строкой (поскольку все может успешно десериализоваться в строку :), а затем преобразовать это самостоятельно, т.е.

using ServiceStack.Common; //ToEnum<> is an extension method

public class RequestDto
{
    public string EnumString { get; set; } 
}

public override object OnGet(RequestDto request)
{
    MyEnum defaultValue = MyEnum.None;
    try {
        defaultValue = request.EnumString.ToEnum<MyEnum>();
    } catch {}
}

Другая альтернатива - полностью удалить его из запроса DTO и вручную получить значение из контекста IHttpRequest, например:

public class RequestDto {}
public override object OnGet(RequestDto request)
{
    MyEnum enumValue = MyEnum.DefaultValue;
    try {
        var enumStr = base.RequestContext.Get<IHttpRequest>().QueryString["EnumString"];
        enumValue = enumStr.ToEnum<MyEnum>();
    } catch {}
}

Как правило, я не рекомендую использовать перечисления в DTO по многим причинам, основной из которых является конечная точка XML / SOAP, XSD рассматривает их как ограниченный набор значений, что является проблемой при итеративной попытке развить ваши веб-службы по мере того, как вы потребуется повторно зарегистрировать клиентов, чтобы добавить новое значение.

По соглашению я имею в виду, что все перечисления являются строками, но предоставляют некоторые метаданные в DTO, которые указывают на целевой тип (что помогает в инструментах навигации и метаданных VS.NET/R#).

public class RequestDto
{
    [References(typeof(MyEnum))]
    public string EnumString { get; set; } 
}
...