As validation and error handling is an essential part of developing services, ServiceStack provides a rich array of error handling options that work intuitively out-of-the-box.
Optimized for developer happiness ServiceStack allows you to idiomatically throw C# exceptions directly in your services and trivially consume them on the client with minimal effort, intuitively and conventionally - allowing the opportunity to inject generic error handling routines to handle errors for all your web services.
As a bonus the most appropriate HTTP Status code is returned based upon the C# Exception type.
Typed, Structured Exceptions end-to-end​
The error handling support works end-to-end where all errors get auto-serialized into your Response DTO and re-hydrated into a C# Exception on ServiceStack's generic Service Clients. This allows you to idiomatically treat errors like normal C# Exceptions - providing easy access to rich, structured error messages in your clients.
JavaScript support included​
To make it trivial to consume errors in JavaScript, you can use the lightweight and embedded dep-free @servicestack/client form binding library or the ss-utils.js jQuery library to trivially bind your response errors to your HTML form fields with a single line of code.
How it works​
All Error handling and validation options described below are treated in the same way - serialized into the ResponseStatus property of your Response DTO making it possible for your clients applications to generically treat all Web Service Errors in the same way.
public class Hello : IReturn<HelloResponse> {}
//Follows naming convention and is in the same namespace as 'Hello'
public class HelloResponse
{
public ResponseStatus ResponseStatus { get; set; } //Exception gets serialized here
}
If now an exception occurs in the service implementation, the exception is serialized.
Example JSON output:
{
"ResponseStatus": {
"ErrorCode": "NotSupportedException",
"Message": "..."
}
}
It's up to the client how to handle this service error.
Throw a C# Exception​
The easiest way to generate an Error in ServiceStack is to simply throw a C# Exception:
public object Post(User request)
{
if (string.IsNullOrEmpty(request.Name))
throw new ArgumentNullException("Name");
}
By Default C# Exceptions:
- Inheriting from ArgumentException are returned as a HTTP StatusCode of 400 BadRequest
- NotImplementedException is returned as a 405 MethodNotAllowed
- Other normal C# Exceptions are returned as 500 InternalServerError
All Exceptions gets injected into the ResponseStatus property of your Response DTO that is serialized into your ServiceClient's preferred Content-Type making error handling transparent regardless of your preferred format - i.e. the same C# Error handling code can be used for all ServiceClients.
try
{
var client = new JsonApiClient(BaseUri);
var response = client.Send<UserResponse>(new User());
}
catch (WebServiceException webEx)
{
/*
webEx.StatusCode = 400
webEx.ErrorCode = ArgumentNullException
webEx.Message = Value cannot be null. Parameter name: Name
webEx.StackTrace = (your Server Exception StackTrace - if DebugMode is enabled)
webEx.ResponseDto = (your populated Response DTO)
webEx.ResponseStatus = (your populated Response Status DTO)
webEx.GetFieldErrors() = (individual errors for each field if any)
*/
}
Enabling StackTraces​
By default display StackTraces in your Response DTOs are disabled, but they're a good to have for development, which you can enable with:
SetConfig(new HostConfig { DebugMode = true });
Customized Error Messages​
If you want even finer grained control of your HTTP errors you can either throw or return a HttpError letting you customize the Http Headers and Status Code and HTTP Response body to get exactly what you want on the wire:
public object Get(User request) {
throw HttpError.NotFound($"User {request.Name} does not exist");
}
the above is a short-hand for new HttpError(HttpStatusCode.NotFound, $"User {request.Name} does not exist") which returns a 404 NotFound StatusCode on the wire.