【发布时间】:2020-05-31 01:15:11
【问题描述】:
我计划使用 ServceStack 的 C# 路由功能连接到基于 JSON 的 API。似乎在尝试这样做时我得到了一个“422 Unprocessable Entity”,而实际上我应该得到一个 JSON 响应。不过,这个错误消息很有趣,因为它会重复多次(精确 8 次)并显示消息 Could not parse Error ResponseStatus ErrorResponse System.IndexOutOfRangeException: Index was outside the bounds of the array. 完整堆栈跟踪如下。
我尝试了许多配置,其中一种“有效”但消除了此路线设置方式的关键需求之一。在这个项目中,我使用ICacheClient来保存一个会话密钥5分钟,所以我并不总是需要在每次需要的时候调用API。由于 ServiceStack 使用注入来设置我的 ICacheClient 实例,因此它必须是公共的。但是,如果它是公开的,我会收到 422 错误,但如果它不是公开的,我会收到 NullPointer,因为它的引用无法由 ServiceStack 设置。
这是我目前的设置:
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";
}
}
完整的堆栈跟踪:
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
感谢大家观看!
【问题讨论】:
-
您能否升级到最新的v5.8.1 on MyGet 并检查问题是否仍然存在,如果确实存在,您是否可以使用 HTTP 数据包嗅探器更新您的问题以包含导致此异常的完整原始 HTTP 响应Fiddler
-
@myth 我的 ServiceStack 版本在 NuGet 上进行管理,提供的最新版本(包括预发行版)是 v5.8.0。关于原始 HTTP 响应,here it is.
-
要确定这是否仍然是一个问题,您需要upgrade to v5.8.1 on MyGet 解决类似问题的地方。
-
这似乎只显示了 GET HTTP 请求,而不是原始的 HTTP 响应。
-
你是对的,我很抱歉 - 我确实发送了错误的部分。 This 是实际的 HTTP JSON 响应。不幸的是,我的 ServiceStack 密钥(由我的公司提供)与 ServiceStack 的 5.8.1 版本不兼容 - 因此我目前无法选择更新。
标签: c# servicestack