我计划使用ServceStack的C#路由功能连接到基于JSON的API。似乎在尝试这样做时得到了“ 422无法处理的实体”,实际上我应该得到JSON响应。但是,此错误消息很有趣,因为它会重复多次(精确8次),并显示消息无法解析Error ResponseStatus ErrorResponse System.IndexOutOfRangeException:索引超出数组范围。跟踪下面。
我尝试了许多配置,其中一种可以“工作”,但消除了该路由设置方式的关键需求之一。在此项目中,我使用library(dplyr)
library(tidyr)
df %>%
pivot_longer(cols = -index) %>%
group_by(index) %>%
summarise(combn = list(combn(value, 2, toString))) %>%
unnest(combn)
# index combn
# <int> <chr>
#1 1 32, 16
#2 1 32, 29
#3 1 16, 29
#4 2 13, 50
#5 2 13, 47
#6 2 50, 47
#7 3 37, 19
#8 3 37, 18
#9 3 19, 18
保存了5分钟的会话密钥,因此我不必总是每次都需要调用API。由于ServiceStack使用注入来设置我的ICacheClient
实例,因此它必须是公共的。但是,如果它是公共的,则会出现422错误,但如果不是公共的,则会出现NullPointer,因为ServiceStack无法设置其引用。
这是我当前的设置:
AppHost.cs
ICacheClient
ApiClientWrapper.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);
}
}
完整的堆栈跟踪:
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";
}
}
谢谢大家的光临!
答案 0 :(得分:0)
该问题是由以下问题引起的: -第三方提供商会在您的令牌之前自动添加“承载者”。
此代码段:
internal JsonServiceClient Api => new JsonServiceClient(ApiUrl)
{
BearerToken = $"Bearer {GenerateAccessToken()}"
};
已更改为:
internal JsonServiceClient Api => new JsonServiceClient(ApiUrl)
{
BearerToken = GenerateAccessToken()
};
解决问题。 我最初生成的是“ Bearer Bearer(令牌)”,这就是为什么我会得到422个无法处理的实体(发送错误数据)的原因。
谢谢大家的帮助!