We receive as customer requirement to have all output field name camel case. We are handling this using DataMember attribute (Name property).
All our ResponseDTOs use ResponseStatus/IHasResponseStatus(to leverage the SS feature that fills it automatically in case of error) so we need to make also the ResponseStatus properties camel case.
The only way I figure out so far is:
-
create a custom MyResponseStatus with exactly the same fields as ResponseStatus.
-
use DataMemeber for MyResponseStatus fields.
-
create an extension/custom version of DtoUtils (MyDtoUtils) that basically uses our custom MyResponseStatus instead of ResponseStatus
-
invoke MyDtoUtils within the hook(ServiceExceptionHandler) in the AppHost
On the server side everything seems fine.
On the client side, I assume we are loosing the built-in feature related to ResponseStatus for exception management.
Do you have any suggestion to customize ResponseStatus (make fields camel case and eventually add some new fields) reducing as much as possible any custom development as we did?
That’s so far my version of MyDtoUtils(copied and adjusted from SS source code)
public static class MyDtoUtils
{
private static readonly ILog Log = LogManager.GetLogger(typeof(MyDtoUtils));
public static object CreateErrorResponse(object request, Exception ex)
{
if (HostContext.Config.ReturnsInnerException
&& ex.InnerException != null && !(ex is IHttpError))
{
ex = ex.InnerException;
}
var serviceStackResponseStatus = ex.ToResponseStatus();
if (HostContext.DebugMode)
{
// View stack trace in tests and on the client
serviceStackResponseStatus.StackTrace = DtoUtils.GetRequestErrorBody(request) + "\n" + ex;
}
Log.Error("ServiceBase<TRequest>::Service Exception", ex);
HostContext.OnExceptionTypeFilter(ex, serviceStackResponseStatus);
var responseStatus = AutoMappingUtils.ConvertTo<MyResponseStatus>(serviceStackResponseStatus);
var errorResponse = CreateErrorResponse(request, ex, responseStatus);
return errorResponse;
}
public static object CreateErrorResponse(object request, Exception ex, MyResponseStatus responseStatus)
{
object responseDto = CreateResponseDto(request, responseStatus);
IHttpError httpError = ex as IHttpError;
if (httpError != null)
{
if (responseDto != null)
httpError.Response = responseDto;
return (object)httpError;
}
string errorCode = ex.GetType().Name;
string errorMessage = ex.Message;
if (responseStatus != null)
{
errorCode = responseStatus.ErrorCode ?? errorCode;
errorMessage = responseStatus.Message ?? errorMessage;
}
return (object)new HttpError(responseDto, HttpRequestExtensions.ToStatusCode(ex), errorCode, errorMessage, ex);
}
private static object CreateResponseDto(object request, MyResponseStatus responseStatus)
{
Type errorResponseDtoType = WebRequestUtils.GetErrorResponseDtoType(request);
object instance = ReflectionExtensions.CreateInstance(errorResponseDtoType);
if (instance == null)
return (object)null;
IHasMyResponseStatus hasResponseStatus = instance as IHasMyResponseStatus;
if (hasResponseStatus != null)
{
hasResponseStatus.ResponseStatus = responseStatus;
}
else
{
PropertyInfo property = errorResponseDtoType.GetProperty("ResponseStatus");
if (property != (PropertyInfo)null)
AutoMappingUtils.SetProperty(property, instance, (object)responseStatus);
}
return instance;
}
}