为发布SendAsync设置HttpRequestMessage.Content(json)会导致意外的字符错误

问题描述 投票:0回答:2

设置:

  1. (服务器).Net Core 2 API
  2. (客户端)用C#编码的AWS Lambda函数(设置JWT必须生成的方式)。
  3. 使用JWT的IDS3(对于发送请求的方法很重要)

IDS3和JWT部分工作正常。拨打电话并点击.Net Core 2 API控制器工作正常。

问题是我收到以下错误:

解析值时遇到意外的字符:{。路径'',第1行,第1位。\“]

代码,附有解释:

StringContent stringContent = new StringContent(eventStr, Encoding.UTF8, "application/json"); 
using (HttpClient client = new HttpClient()) {
    HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, myApiURL);
    requestMessage.Content = stringContent;
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwtToken);
    HttpResponseMessage thing = client.SendAsync(requestMessage).Result;
    string actualResponse = thing.Content.ReadAsStringAsync().Result;        
}

eventStr是AWS传递给函数处理程序的json字符串。

qazxsw poi包含错误:qazxsw poi

我检查了正在生成的StringContent,这是绝对正确的。

在API方面发生的事情是发现JWT非常正确,触发Controller构造函数,动作永远不会被命中,表面上是因为数据有效负载(eventStr)未正确附加到actualResponse

API操作的方法签名:

Unexpected character encountered while parsing value: {. Path '', line 1, position 1.\"]

如果那不是正确的地方,那是什么?

c# httprequest asp.net-core-2.0 dotnet-httpclient
2个回答
0
投票

我建议你使用HttpRequestMessage库它会节省你很多时间。

因此,您可以将代码切换为以下内容(请注意,我对某些行进行了注释,您可以根据请求使用情况删除这些行):

          public async Task<ActionResult> Post([FromBody] string Message)

使用MyHttpClientFactory类:

Flurl

希望你会发现这很有用。


0
投票

问题不在于json。

因此,AWS lambda函数由AWS发送匿名类型。基本上只是一个快速和松散的对象。

由于POST,我需要通过StringContent变量将其作为字符串发送。但是,如果我对它进行序列化,那么Core API控制器会说“嘿,我知道这个!它是JSON。让我们反序列化它。”它确实如此。

鉴于该操作期望一个字符串,控制器说“没有接受我在这里的对象的动作。这是一个错误的请求。”

但是,如果我将其作为纯字符串发送(例如“{key1:value1”}而不是“{\”key1 \“:\”value1 \“}”),并且键和值周围没有引号,则控制器并且行动说“嘿!这是一根绳子。我得到了这个。”

那么问题是它在那时不是有效的json,只是像JSON那样。因此行动的胆量并没有正确对待它。

目前并且缺乏进一步的知识和研究,解决方法的解决方案是更改操作签名以期望try { //Needed if request sent over Https ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; //OPTIONAL: set certificates validation, from a static container of global configuration Flurl.Configure(settings => { settings.HttpClientFactory = new MyHttpClientFactory(); }); var result = await myApiUrl .WithHeader("Authorization", $"Bearer {jwtToken}") .PostJsonAsync(requestMessage) .ReceiveString(); //For response as string .ReceiveJson<MyClass>(); // to map a json result to an object } catch(FlurlHttpException ex) { throw ex.InnerException; } 类型的参数并在方法中特别反序列化它。

虽然这有效,但它并不是正确的解决方案,因为我现在基本上打开了对任何对象类型的调用,而不是我们真正想要的那种。由于AWS Lambda函数被传递为匿名类型(即:object),因此这是有道理的。

更新:public class MyHttpClientFactoryDev : DefaultHttpClientFactory { public override HttpMessageHandler CreateMessageHandler() { //If you want to validate all certs return new HttpClientHandler { ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyError) => true }; //If you need to verify certificate signature var handler = new HttpClientHandler(); handler.ClientCertificates.Add(X509Certificate.CreateFromCertFile("path to cert")); return handler; } }

本文介绍了可用于解决此问题的解决方案类型。缺点是Core API并不真正知道如何处理字符串。作者列出了几种解决方案。我选择实现的是扩展输入格式化程序。我将在这里总结一些过程:

新课 - > Object

维多利亚 - > https://weblog.west-wind.com/posts/2017/Sep/14/Accepting-Raw-Request-Body-Content-in-ASPNET-Core-API-Controllers

RawRequestBodyFormatter : InputFormatter

SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));

检查override Boolean CanRead,看它是否包含你的override async Task<InputFormatterResult> ReadRequestBodyAsync修饰符。

在启动时,添加以下内容:

context.HttpContext.Request.ContentType
© www.soinside.com 2019 - 2024. All rights reserved.