We have been using ServiceStack for REST based services for a while now and so far it has been amazing.
All of our services have been written as:
public class MyRestService : RestService<RestServiceDto>
{
public override object OnGet(RestServiceDto request)
{
}
}
For each DTO we have Response equivalent object:
public class RestServiceDto
{
public ResponseStatus ResponseStatus {get;set;}
}
which handles all the exceptions should they get thrown.
What I noticed is if an exception is thrown in the OnGet()
or OnPost()
methods, then the http status description contains the name of the exception class where as if I threw a:
new HttpError(HttpStatus.NotFound, "Some Message");
then the http status description contains the text "Some Message".
Since some of the rest services are throwing exceptions and others are throwing new HttpError()
, I was wondering if there was a way without changing all my REST services to catch any exceptions and throw a new HttpError()?
So for example, if the OnGet()
method throws an exception, then catch it and throw a new HttpError()
?
Using Old API - inherit a custom base class
As you're using the old API to handle exceptions generically you should provide a Custom Base class and override the HandleException method, e.g:
public class MyRestServiceBase<TRequest> : RestService<TRequest>
{
public override object HandleException(TRequest request, Exception ex)
{
...
return new HttpError(..);
}
}
Then to take advantage of the custom Error handling have all your services inherit your class instead, e.g:
public class MyRestService : MyRestServiceBase<RestServiceDto>
{
public override object OnGet(RestServiceDto request)
{
}
}
Using New API - use a ServiceRunner
Otherwise if you're using ServiceStack's improved New API then you don't need to have all services inherit a base class, instead you can just tell ServiceStack to use a custom runner in your AppHost by overriding CreateServiceRunner:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(
ActionContext actionContext)
{
return new MyServiceRunner<TRequest>(this, actionContext);
}
Where MyServiceRunner is just a just custom class implementing the custom hooks you're interested in, e.g:
public class MyServiceRunner<T> : ServiceRunner<T> {
public override object HandleException(IRequestContext requestContext,
TRequest request, Exception ex) {
// Called whenever an exception is thrown in your Services Action
}
}