How to customize ServiceStack.ResponseStatus

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

If you want to change to use camelCase you can just specify it in AppHost.Configure() with:

JsConfig.EmitCamelCaseNames = true;

Thanks for the hint! Works great for json output. What about soap12? We need to support same behavior for soap as well…

That’s not going to work for SOAP since it uses .NET’s XML Serializer which AFAICT doesn’t provide any way to modify the structure of a type defined in a different assembly, so the only option would be to use a custom build of SS with a refactored ResponseStatus - but that’s not something I’d recommend.

I agree with you… that will be my very last option…

I figure out that solution that seems to work smoothly with all tests I did so far… what do you think about it? Do you see any issue I didn’t?

All my ResponseDTO inherit from the following base class:

[DataContract]
public abstract class ResponseBase : IHasMyResponseStatus
{
	private ResponseStatus _responseStatus;

	[DataMember(Name = "responseStatus")]
	public MyResponseStatus MyResponseStatus { get; set; }

	public ResponseStatus ResponseStatus
	{
		get { return _responseStatus; }
		set
		{
			_responseStatus = value;
			MyResponseStatus = value.ToMyResponseStatus();
		}
	}
}

MyResponseStatus has custom DataMember attributes with Name property in order to make Property name camelCase during the serialization and also it contains additional properties.

the not-serializable property

public ResponseStatus ResponseStatus

will be invoked/used by current SS framework and i just have to keep my serializable property updated using the setter

the only additional realignment I had figure-out so far is in case of the use of

public override void OnExceptionTypeFilter(Exception ex, ResponseStatus responseStatus)

It looks like it will populate your custom attributed property but as this is also an uncharted customization you might run into other issues given it’s never been a supported use-case.