문제

What is the best practice for Wcf service, in case we need to send fail/success result?

For example: We have Wcf service, behind service we have some BussinesLogic. Our service have one operation contract:

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

Possible scenarios:

  1. Operation complete, all successful.
  2. Bitmap arguments are incorrect (wrong size or number of bitmaps).
  3. BussinesLogic is in "bad" state. Logic is in error state and we dont know when it will avalible for work again.

Should i make custom fault? In wich case? Should i use generic fault? Should i make enum OperationResult? Or maby in case of success any result is like overkill? Number of possible scenarios will be constant.

도움이 되었습니까?

해결책

I like to use this approach:

[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; }
}

Also I have some extensions:

  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;
  }

The extensions make possible to return error with the one line of code:

return retValue.WithError(ErrorCodes.RequestError);

From my wcf service I never throw an exception.

Sorry for the wall of code


Caller's code is something like that. But it all depends on your requirements

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

if(!res.Success)
{
    if(res.Errors.Any(x => ErrorCodes.UsernameTaken)
    {
       // show error for taken username
    }
    ...
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top