JsonServiceClient ResponseFilter doesn't trigger

I posed this on SO the other day but didn’t get any responses, so we’ll see if anyone here can help out.

Maybe I’m missing something simple, but I can’t for the life of me get the ResponseFilter to trigger on a JsonServiceClient (using the latest v4.0.40.0). The RequestFilter triggers every time (using it to send an API token to my SS API). I want to use the ResponseFilter to check every response anywhere in the app for a revoked token (a 401 coming back from my API). Here is a sample console app that shows the ResponseFilter never writing to the console.

static void Main(string[] args)
{
    using (var client = new JsonServiceClient())
    {
        client.ResponseFilter = httpResponse =>
        {
            Console.WriteLine("ResponseFilter: StatusCode == " + httpResponse.StatusCode);
        };

        try
        {
            System.Net.HttpWebResponse response = client.Get("https://app.asana.com/api/1.0/users/me");
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception => " + e.Message);
        }
    }
    Console.ReadLine();
}

What am I missing?

Hey @robertmiles3, I did ask if you could provide a more complete example as the code you have provided here and the code you have on SO are the same. To help you out I’ve created a simple example of the response filter example calling the TechStacks.io example site.

https://github.com/Layoric/ServiceStackResponseFilterExample

This project is a new project using the ServiceStack ASP.NET Empty template from ServiceStackVS plugin.

I then added a ServiceStack reference to TechStacks.io and called the service using the JsonServiceClient. Eg,

bool calledRepsonseFilter = false;
var jsonServiceClient = new JsonServiceClient("http://techstacks.io/");
jsonServiceClient.ResponseFilter = response =>
{
    Console.WriteLine("A response!");
    calledRepsonseFilter = true;
};
var res = jsonServiceClient.Get(new AppOverview());
Assert.That(res.TopTechnologies != null);
Assert.That(calledRepsonseFilter == true);

This is the code from the examples unit test.

Feel free to upload the code you are having trouble with so I might have a better idea how to suggest a solution.

Hope that helped.

Thanks @layoric. I’m not sure what exactly I can post to help out more because my non-working code (besides the console example) is a Xamarin iOS application that you wouldn’t be able to build/run/test without a subscription.

Now that I think about it, your example is not throwing a 401, but rather getting a successful result. That may be the big difference between yours calling the ResponseFilter and mine not. Mine is all about trying to catch 401 on a global level (via ResponseFilter) instead of having to handle it all throughout my code.

So, that begs the question, does a ResponseFilter not get executed if there’s an exception like a 401?

Ahh yes, this makes more sense :smile:

The response filter won’t be getting fired on the 401 as the JsonServiceClient will throw an exception in that case.

One alternative is to handle the exception yourself by inheriting from the JsonServiceClient and overriding HandleResponseException. Eg,

public class MyJsonServiceClient : JsonServiceClient
{
    protected override bool HandleResponseException<TResponse>(Exception ex, object request, string requestUri, Func<WebRequest> createWebRequest,
        Func<WebRequest, WebResponse> getResponse, out TResponse response)
    {
        return base.HandleResponseException(ex, request, requestUri, createWebRequest, getResponse, out response);
    }
}

This would allow you to handle response exceptions with your own logic. Hope that is more useful :smile:

Gotcha. I actually found that the other day (via this SO) and started working toward that direction. It seems to work well with this code I now have (below). I just didn’t know if that was the right way to go. Thanks for the confirmation! Sorry for the confusion!

protected override bool HandleResponseException<TResponse>(Exception ex, object request, string requestUri, Func<System.Net.WebRequest> createWebRequest, Func<System.Net.WebRequest, System.Net.WebResponse> getResponse, out TResponse response)
{
	var isHandled = false;
	response = default(TResponse);
	try
	{
		isHandled = base.HandleResponseException(ex, request, requestUri, createWebRequest, getResponse, out response);
	}
	catch (WebServiceException webServiceException)
	{
		if(webServiceException.StatusCode == 401)
		{
			// The token is now revoked, so clear it and show the login page
			App.AppManager.DeleteAPIToken();
			App.AppManager.RootPage.ShowLoginPage();
		}
	}
	return isHandled;
}

@layoric I’ve also noticed that GetAsync will bypass the HandleResponseException override. Is that to be expected? Is there a way I can use async calls and still catch the 401 globally?

If you are only using it for 401, there is also the OnAuthenticationRequired property which on a 401 will fire on both Async and Sync functions of the client.

However, this does require that the JsonServiceClient UserName and Password are populated for authentication.

Here is where the AsyncServiceClient is firing the function

Thanks. I’m not using user/pass auth, but rather a token-based authentication in the header. So, it wouldn’t really work. I worked yesterday on overriding the GetAsync and PostAsync functions to wrap them with checks for 401. Seems to work well for now.