ServiceClientBase new Authentication behaviour

I say new (in the title above), because its been many months since I examined the code of the ServiceClientBase.HandleResponseException.

Much has moved on in ServiceStack clients, which is great for many people. And now I notice that the serviceclient will retry any request it makes that responds with 401 - Unauthorized, iff it has access to any credentials (i.e. Username and password or credentials, bearerToken etc.)

I am thinking this is a good thing, now that the client supports Bearer token and even Refresh token! something it was lacking ages back.

However, we had to build all these extra things around our sub-classed version of our ServiceClient way back when they were not supported. Now, we have conflicting issues when a 401 is received. We have our own way to deal with that, and we don’t want the ServiceClient doing the re-authenticate call on its own.

I am faced with either ripping out all the stuff we had to build at a time it was missing, or find a way to turn off this conflicting behavior that is relatively new in ServiceClientBase.

I did try to override the method HandleResponseException and simply copy all the code except the stuff we don’t want, but there are some internal method calls (like: ThrowResponseTypeException<TResponse>(request, subEx, requestUri); which cant call, that seem to be critical to how it all works).

To save us a lot of rework catching up with new developments in the ServiceClientBase class, is it possible to have a simple flag in the call to for ShouldAuthenticate() that we can easily set to avoid all the code that does the re-request with credentials? Perhaps, something like AllowAutoReauthenticate? much appreciated.

Can you just maintain your own copy of ServiceClientBase? I want to avoid embedding logic in the Service Clients to serve an invisible sub class with conflicting behavior, it’s going to continually be a source of frequent issues with other changes in future.

Otherwise I don’t want to expose a public API for this, if you can send a minimally disruptive PR that uses a protected method like ShouldReauthenticate() that will work for your custom impl, which I can look at incorporating.

OK, that is fair enough.

The real issue here is that ThrowResponseTypeException is private and not protected.

Or even better (and I wont be blocked waiting for a new release), could you show me what I can do instead of calling it? (in just the one place it is called) just to replicate what it does sufficiently? then I will happily maintain my own override of ServiceClientBase.HandleResponseException.

This would be my override. It simply cuts out the reauthentication piece, and reuses the remainder.

    protected virtual bool HandleResponseException<TResponse>(Exception ex, object request, string requestUri,
            Func<WebRequest> createWebRequest, Func<WebRequest, WebResponse> getResponse, out TResponse response)
            var webEx = ex as WebException;
            if (ExceptionFilter != null && webEx?.Response != null)
                var cachedResponse = ExceptionFilter(webEx, webEx.Response, requestUri, typeof(TResponse));
                if (cachedResponse is TResponse)
                    response = (TResponse)cachedResponse;
                    return true;

            ThrowResponseTypeException<TResponse>(request, ex, requestUri); <===== what to do here?<====

            response = default(TResponse);
            return false;

I notice that the guidance in the comment for HandleResponseException gives us a recommendation for our own override, but without an example it is not clear what type to use for YourErrorResponseType in the call.

It says: ThrowWebServiceException<YourErrorResponseType> to parse the response and to throw a WebServiceException containing the parsed DTO. Then override Send to handle that exception.

I don’t have my own special exception type and I don’t want to change the way exceptions are handled. I just want the built in behavior.

Can you send a PR with the changes you need. If its minimally disruptive we can accept it.

All done, thank you guys