(422)具有ServiceStack路由的不可处理实体

时间:2020-05-31 01:15:11

标签: c# servicestack

我计划使用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";
    }
}

谢谢大家的光临!

1 个答案:

答案 0 :(得分:0)

该问题是由以下问题引起的: -第三方提供商会在您的令牌之前自动添加“承载者”。

此代码段:

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

已更改为:

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

解决问题。 我最初生成的是“ Bearer Bearer(令牌)”,这就是为什么我会得到422个无法处理的实体(发送错误数据)的原因。

谢谢大家的帮助!