2014-05-08 5 views
2

Какова наилучшая практика для службы Wcf, если нам нужно отправить результат неудачи/успеха?Хорошая практика для результата работы службы wcf

Например: У нас есть служба Wcf, за обслуживанием у нас есть BussinesLogic. Наша служба имеет один контракт операции:

[OperationContract] /*SomeResult*/ SendImages(Bitmap[] images);

Возможные сценарии:

  1. операция завершена, все успешные.
  2. Аргументы растрового изображения неверны (неправильный размер или количество растровых изображений).
  3. BussinesLogic находится в «плохом состоянии». Логика находится в состоянии ошибки, и мы не знаем, когда она будет доступна для работы снова.

Должен ли я сделать обычай fault? В каком случае? Должен ли я использовать общий fault? Должен ли я делать enum OperationResult? Или мабы в случае успеха любой результат, как перебор? Число возможных сценариев будет постоянным.

+0

В любом случае вы выбираете - наиболее важным является ** быть согласованным **. Я видел много раз внешних систем, которые иногда возвращали код ошибки, а иногда и ошибки. И, возможно, в самом начале они даже смогли понять, почему они выбирают то или другое, через какое-то время никто не смог оправдать это решение, и мы, как клиент, всегда должны были работать в обоих направлениях. –

ответ

8

Мне нравится использовать этот подход:

[DataContract] 
public class OperationResult 
{ 
    public OperationResult() 
    { 
    Errors = new List<OperationError>(); 
    Success = true; 
    } 

    [DataMember] 
    public bool Success { get; set; } 

    [DataMember] 
    public IList<OperationError> Errors { get; set; } 
} 

[DataContract(Name = "OperationResultOf{0}")] 
public class OperationResult<T> : OperationResult 
{ 
    [DataMember] 
    public T Result { get; set; } 
} 

[DataContract] 
public class OperationError 
{ 
    [DataMember] 
    public string ErrorCode { get; set; } 

    [DataMember] 
    public string ErrorMessage { get; set; } 
} 

Также у меня есть несколько расширений:

public static OperationResult WithError(this OperationResult operationResult, string errorCode, 
              string error = null) 
    { 
    return operationResult.AddErrorImpl(errorCode, error); 
    } 

    public static OperationResult<T> WithError<T>(this OperationResult<T> operationResult, string errorCode, 
               string error = null) 
    { 
    return (OperationResult<T>) operationResult.AddErrorImpl(errorCode, error); 
    } 

    private static OperationResult AddErrorImpl(this OperationResult operationResult, string errorCode, 
               string error = null) 
    { 
    var operationError = new OperationError {Error = error ?? string.Empty, ErrorCode = errorCode}; 

    operationResult.Errors.Add(operationError); 
    operationResult.Success = false; 

    return operationResult; 
    } 

    public static OperationResult<T> WithResult<T>(this OperationResult<T> operationResult, T result) 
    { 
    operationResult.Result = result; 
    return operationResult; 
    } 

Расширения делают возможным вернуть ошибку с помощью одной строки кода:

return retValue.WithError(ErrorCodes.RequestError); 

С моей службы wcf я никогда не бросаю исключение.

Извините за стеной кода


код вызывающего абонента что-то в этом роде. Но все зависит от ваших требований.

OperationResult res = _service.Register(username, password); 

if(!res.Success) 
{ 
    if(res.Errors.Any(x => ErrorCodes.UsernameTaken) 
    { 
     // show error for taken username 
    } 
    ... 
} 
+0

Действительно ли вызывающие ваши службы обрабатывают список ошибок? Что они делают со списком? –

+0

@JohnSaunders, см. Обновление – Veikedo

+0

Я думаю, что вы имели в виду 'res.Errors.Any (x => x.ErrorCode ==" UsernameTaken ")' или что-то. Это похоже на беспорядок. –

Смежные вопросы