errorCode in HttpError.StatusDescription?

Hi there,

We are writing a Mobile app which calls a ServiceStack service (which is installed in a DMZ). This ServiceStack service calls another ServiceStack service (which is installed in the intranet).

If the service on the intranet throws an exception, then this this is packed in a WebServiceException. Elas the Message property changes from the original message to the Exceptiontype name.

We think that this is caused by HttpError class.

    public HttpError(int statusCode, string errorCode, string errorMessage, Exception innerException = null)
        : base(errorMessage ?? errorCode ?? statusCode.ToString(), innerException)
    {
        this.ErrorCode = errorCode ?? statusCode.ToString();
        this.Status = statusCode;
        this.Headers = new Dictionary<string, string>();
        this.StatusDescription = errorCode; // <<-- Why set the errorCode in the StatusDescription. Should this not be errorMessage ??
        this.Headers = new Dictionary<string, string>();
        this.Cookies = new List<Cookie>();
    }

Which is later used in ServiceClientBase.cs:

            var serviceEx = new WebServiceException(**errorResponse.StatusDescription**)
            {
                StatusCode = (int)errorResponse.StatusCode,
                StatusDescription = errorResponse.StatusDescription,
                ResponseHeaders = errorResponse.Headers
            };

Which gives the following result (see image).

The WebServiceException is then packed to the mobile (Xamarin) app and cannot show the detailed message properly (see image below).

Any suggestions to propagate the exception correctly from the intranet webservice to the mobile xamarin app?

An error message can contain any length of free text whereas the HTTP Response StatusDescription is expected to be a short textual description of the Status Code, an error code is more appropriate for this.

You can get details about the error from the WebServiceException.ResponseStatus typed DTO.

To change how Exceptions are serialized in the ResponseStatus you can override OnExceptionTypeFilter in your AppHost, e.g:

public override void OnExceptionTypeFilter(Exception ex, ResponseStatus responseStatus)
{
    var webEx = ex as WebServiceException;
    if (webEx != null) { 
        //change how WebServiceException is serialized
    }
    else {
        base.OnExceptionTypeFilter(ex, responseStatus);
    }
}

Oke, but why change the Message of the exception in something unusable?

I would prefer the following change in ServiceClientBase.cs:

From:
var serviceEx = new WebServiceException(errorResponse.StatusDescription)

To:
var serviceEx = new WebServiceException(ex.Message)

So it wil propagate the informational message (in this case) “This exception is intentional for testing purposes” instead of (in this case) “EntityNotFoundException”.

Because WebServiceException represents a server exception, a client exception is only going to show information about the exception raised on the client.

I’ll try to explain the situation in more detail.

We have:
a) NativeMobileApp with ServiceStack client
b) WebServerA with ServiceStack GetWorkflowViews service (DMZ zone)
c) WebServerB with ServiceStack GetWorkflowViews service (Intranet zone)

  1. The NativeMobileApp JSON client calls the GetWorkflowViews service on WebServerA.

  2. The WebServerA passtrough the same request to WebServerB by instantiating a new JSON client and calls the GetWorkflowViews on WebServerB.

  3. The WebServerB throws an exception. i.e.

     [Authenticate]
     public List<View> Any(GetWorkflowViews request)
     {
     	throw new EntityNotFoundException("This exception is intentional for testing purposes");
     }
    
  4. WebServerA receives the exception of WebServerB in a WebServiceException.

Note that the ErrorMessage contains the text “This exception is intentional for testing purposes” and the Message “EntityNotFoundException”.

5 . NativeApp receives the exception of WebServerA in a WebServiceException.

Note that the ErrorCode, Message, ResponseStatus.ErrorCode contains the text ‘WebServiceException’ and ErrorMessage, ResponseStatus.Message contains the text ‘EntityNotFoundException’.

The original Message (which we want to show to the user of the MobileNativeApp) “This exception is intentional for testing purposes” isn’t available anymore.

We want both the ExceptionType and Message available in the MobileNativeApp which was throwed by WebServerB.

I hope I have explained the situation well.

Do you have any suggestions?

[A workaround I found is to throw a new WebServiceException with the complete message in step 4. The message should then be available in the MobileClientApp in property ErrorMessage.]

Did you look at overriding OnExceptionTypeFilter from my initial comment? It should let you customize the returned ResponseStatus for any exception.

Anyway I’ve implemented IResponseStatusConvertible on WebServiceException in this commit which is another way to customize the returned ResponseStatus for a given Exception as seen in the commit tests.

This change is available from v4.0.55 which is now available on MyGet.

I’ve tried implementing OnExceptionTypeFilter() on WebServerB, but that didn’t work for me.

I’ve now implemented the following code on the ServiceHost of WebServerA:

public override void OnExceptionTypeFilter(Exception ex, ResponseStatus responseStatus)
	{
		var webEx = ex as WebServiceException;
		if (webEx != null)
		{
			responseStatus.Message = webEx.ErrorMessage;
			responseStatus.ErrorCode = webEx.ErrorCode;
		}
		else {
			base.OnExceptionTypeFilter(ex, responseStatus);
		}
	}

The exception on the client is now usable to display to the user.

Thanks!

ok cool, you shouldn’t need a custom OnExceptionTypeFilter for WebServiceException in the next version (that’s now on MyGet).