0
votes

I had a plan to connect to a JSON-based API using ServceStack's Routing features for C#. It seems that I get a '422 Unprocessable Entity' when attempting to do so when, in reality I'm supposed to be getting a JSON response. This error message is interesting though, since it repeats itself multiple times over (8 times exact) with the message Could not parse Error ResponseStatus ErrorResponse System.IndexOutOfRangeException: Index was outside the bounds of the array. Full stack trace below.

I've tried many configurations, and there is one that 'works' but removes one of the key needs of the way this route is set up. In this project, I use ICacheClient to save a session key for 5 minutes, so I don't always need to call the API every time I need it. Since ServiceStack uses injection to set my instance of ICacheClient, it must be public. However, if it is public I get that 422 error, but if it isn't public I get a NullPointer because it's reference cannot be set by ServiceStack.

Here's my current setup:

AppHost.cs

public class AppHost : AppHostBase
{
    public override void Configure(Container container)
    {
        Log.Info("Starting up...");
        var stopwatch = Stopwatch.StartNew();

        // Add Plugins
        // Add Connection Strings
        container.Register<ICacheClient>(new MemoryCacheClient());
        container.RegisterAs<ApiClientWrapper, IApiClient>();

        stopwatch.Stop();
        Log.Info("Started in {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
    }
}

ApiClientWrapper.cs

public class ApiClientWrapper : IApiClient
{
    // These are set in a Web.config, and work fine.
    private string Username => HostContext.AppSettings.Get<string>("Username");
    private string Password => HostContext.AppSettings.Get<string>("Password");
    private string ApiUrl => HostContext.AppSettings.Get<string>("ApiUrl");

    // This must be public, NULL if private or internal
    public ICacheClient Cache { get; set; }

    private string GenerateAccessToken()
    {
        const string key = "ApiSessionKey";

        var sessionKey = Cache.Get<string>(key);

        if (sessionKey == null)
        {
            using(var client = new JsonServiceClient(ApiUrl))
            {
                var request = new LoginRequest
                {
                    Username = Username,
                    Password = Password
                };
                // Token provided by API
                sessionKey = client.Post(request).AccessToken;
            }
            Cache.Add(key, sessionKey, 5.Minutes());
        }

        return sessionKey;
    }

    internal JsonServiceClient Api => new JsonServiceClient(ApiUrl)
    {
        BearerToken = $"Bearer {GenerateAccessToken()}"
    };

    public List<Price> FindPrices(FindPrices request)
    {   
        /*
         * LatestPricesResponse DTO matches the expected JSON response.
         * The class has the [DataContract] tag, and each property has the [DataMember] tag.
         */
        var response = Api.Get(new LatestPricesRequest());
        response = request.MaxRows.HasValue ? response.Take(request.MaxRows.Value).ToList() : response;
        return response.ToDto();
    }

    [Route("/login", Verb.Post)]
    [DataContract]
    public class LoginRequest : IReturn<LoginResponse>, IPost
    {
        [DataMember(Name = "username")]
        public string Username { get; set; }
        [DataMember(Name = "password")]
        public string Password { get; set; }
    }

    [Route("/latest_prices", Verb.Get)]
    [DataContract]
    public class LatestPricesRequest : IReturn<List<LatestPricesResponse>>, IGet
    {
        [DataMember(Name = "show_details")]
        public string ShowDetails => "no";
    }
}

Full Stacktrace:

2020-05-29 15:52:02.5996 ERROR DEVELOPER-PC ServiceStack.ServiceClientBase.ToWebServiceException  System.Net.WebException: The remote server returned an error: (422) UNPROCESSABLE ENTITY.
   at System.Net.HttpWebRequest.GetResponse()
   at ServiceStack.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 1317  System.Net.WebException: The remote server returned an error: (422) UNPROCESSABLE ENTITY.
   at System.Net.HttpWebRequest.GetResponse()
   at ServiceStack.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 1317
2020-05-29 15:52:02.5996 DEBUG DEVELOPER-PC ServiceStack.ServiceClientBase.ToWebServiceException  Status Code : 422  
2020-05-29 15:52:02.5996 DEBUG DEVELOPER-PC ServiceStack.ServiceClientBase.ToWebServiceException  Status Description : UNPROCESSABLE ENTITY  
2020-05-29 15:52:02.6266 ERROR DEVELOPER-PC Api.AppHost.SetHostConfig  An exception was thrown on "GET" for path "/prices"  422 UNPROCESSABLE ENTITY
Code: UNPROCESSABLE ENTITY, Message: 

2020-05-29 15:52:02.6486 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70
2020-05-29 15:52:02.6486 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70
2020-05-29 15:52:02.6486 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70
2020-05-29 15:52:02.6686 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70
2020-05-29 15:52:02.6686 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70
2020-05-29 15:52:02.6686 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70
2020-05-29 15:52:02.6686 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70
2020-05-29 15:52:02.6736 DEBUG DEVELOPER-PC ServiceStack.WebServiceException.get_ResponseStatus  Could not parse Error ResponseStatus ErrorResponse  System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.ThrowHelper.ThrowIndexOutOfRangeException()
   at ServiceStack.Text.Jsv.JsvTypeSerializer.EatMapKey(ReadOnlySpan`1 value, Int32& i) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvTypeSerializer.cs:line 300
   at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(ReadOnlySpan`1 strType, TypeConfig typeConfig, EmptyCtorDelegate ctorFn, KeyValuePair`2[] typeAccessors) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeTypeRefJsv.cs:line 40
   at ServiceStack.Text.Common.DeserializeType`1.StringToTypeContext.DeserializeJsv(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Common\DeserializeType.cs:line 60
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(ReadOnlySpan`1 value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 102
   at ServiceStack.Text.Jsv.JsvReader`1.Parse(String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\Jsv\JsvReader.Generic.cs:line 81
   at ServiceStack.Text.TypeSerializer.DeserializeFromString[T](String value) in C:\BuildAgent\work\912418dcce86a188\src\ServiceStack.Text\TypeSerializer.cs:line 67
   at ServiceStack.WebServiceException.get_ResponseStatus() in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\WebServiceException.cs:line 70

Thanks for taking a look, everyone!

1
Can you upgrade to the latest v5.8.1 on MyGet and check if the issue persists, if it does can you update your question to include the full raw HTTP Response that causes this Exception, using a HTTP Packet Sniffer like Fiddler - mythz
@myth My ServiceStack version is managed on NuGet, and the latest version provided (including pre-releases) is v5.8.0. In regards to the raw HTTP response, here it is. - NoEffort
To determine if this is still an issue you’d need to upgrade to v5.8.1 on MyGet where issues similar to this have been resolved. - mythz
It looks like this only shows GET HTTP Request, not the raw HTTP Response. - mythz
You are correct, my apologies - I did send the wrong section. This is the actual HTTP JSON response. Unfortunately, my ServiceStack key (provided by my company) is not compatible with version 5.8.1 of ServiceStack - so updating is not currently an option for me. - NoEffort

1 Answers

0
votes

The problem was caused by the following issue: - The 3rd-party provider automatically adds "Bearer" before your token.

This snippet:

    internal JsonServiceClient Api => new JsonServiceClient(ApiUrl)
    {
        BearerToken = $"Bearer {GenerateAccessToken()}"
    };

Was changed to:

    internal JsonServiceClient Api => new JsonServiceClient(ApiUrl)
    {
        BearerToken = GenerateAccessToken()
    };

To solve the problem. What I was initially generating was "Bearer Bearer (token)", which is why I would get a 422 UNPROCESSABLE ENTITY (sending the wrong data).

Thanks for the help, everyone!