Greens
Greens

Reputation: 3067

ServiceStack Map Errors in ResponseStatus to custom Errors without Validators

Is there a way in Servicestack to Map custom request validation errors to the errors field in resposeStatus object with out using Validators.

ie. if I have a custom list of errors with a

{
    "ErrorCode": "NotEmpty",
    "FieldName": "Company",
    "Message": "'Company' should not be empty."
}

How do I map to ResponseStatus object with out Validators.

Upvotes: 2

Views: 255

Answers (1)

mythz
mythz

Reputation: 143399

ServiceStack Exceptions are just Response DTO's that have a populated ResponseStatus that are returned with a HTTP Error code. There are a number of different ways you can customize the Error Response including:

Returning a HttpError with a populated Response DTO

If you want to send a customized ResponseStatus DTO you can throw a HttpError, e.g:

var responseDto = new ErrorResponse { 
    ResponseStatus = new ResponseStatus {
        ErrorCode = typeof(ArgumentException).Name,
        Message = "Invalid Request",
        Errors = new List<ResponseError> {
            new ResponseError {
                ErrorCode = "NotEmpty",
                FieldName = "Company",
                Message = "'Company' should not be empty."
            }
        }
    }
};
throw new HttpError(HttpStatusCode.BadRequest, "ArgumentException") {
    Response = responseDto,
}; 

Overriding OnExceptionTypeFilter in your AppHost

By default when you throw an ArgumentException the built-in OnExceptionTypeFilter will automatically add a populated ResponseError for the specified ParamName, e.g:

public virtual void OnExceptionTypeFilter(
    Exception ex, ResponseStatus responseStatus)
{
    var argEx = ex as ArgumentException;
    var isValidationSummaryEx = argEx is ValidationException;
    if (argEx != null && !isValidationSummaryEx && argEx.ParamName != null)
    {
        var paramMsgIndex = argEx.Message.LastIndexOf("Parameter name:");
        var errorMsg = paramMsgIndex > 0
            ? argEx.Message.Substring(0, paramMsgIndex)
            : argEx.Message;

        responseStatus.Errors.Add(new ResponseError
        {
            ErrorCode = ex.GetType().Name,
            FieldName = argEx.ParamName,
            Message = errorMsg,
        });
    }
}

You can also override this method in your AppHost to customize the ResponseStatus of your own exceptions.

Implementing IResponseStatusConvertible

Behind the scenes the way ValidationException allows customizing the Response DTO is by having ValidationException implement the IResponseStatusConvertible interface.

E.g. Here's how to create a custom Exception that throws a populated Field Error in the Response DTO:

public class CustomFieldException : Exception, IResponseStatusConvertible
{
  ...
    public string FieldErrorCode { get; set; }
    public string FieldName { get; set; }
    public string FieldMessage { get; set; }

    public ResponseStatus ToResponseStatus()
    {
        return new ResponseStatus {
            ErrorCode = GetType().Name,
            Message = Message,
            Errors = new List<ResponseError> {
                new ResponseError {
                    ErrorCode = FieldErrorCode,
                    FieldName = FieldName,
                    Message = FieldMessage
                }
            }
        }
    }    
}

Upvotes: 1

Related Questions