Установка HttpRequestMessage.Content (json) для поста SendAsync приводит к непредвиденной ошибке символа - PullRequest
0 голосов
/ 06 сентября 2018

Настройка:

  1. (сервер) .Net Core 2 API

  2. (клиент) Лямбда-функция AWS, закодированная в C # (задает способ генерации JWT).

  3. IDS3 с использованием JWT (важно для способа отправки запроса)

Часть 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 - строка json, передаваемая обработчику функции AWS.

actualResponse содержит ошибку: Unexpected character encountered while parsing value: {. Path '', line 1, position 1.\"]

Я проверил генерируемый StringContent, и он абсолютно правильный.

Что происходит на стороне API, так это то, что JWT оказался очень правильным, конструктор Controller запущен, действие никогда не выполняется, якобы потому, что полезная нагрузка данных (eventStr) не присоединена к HttpRequestMessage правильно.

Подпись метода для действия API:

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

Если это не то место, то что?

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Проблема не в json.

Таким образом, лямбда-функция AWS отправляется анонимным типом AWS.В основном просто быстрый и свободный объект.

Мне нужно из-за POST, чтобы отправить это как строку через переменную StringContent.Однако, если я сериализую его, контроллер Core API скажет: «Эй, я знаю это! Это JSON. Давайте десериализовать его».И так оно и есть.

Учитывая, что действие ожидает строку, контроллер говорит: «Нет действий, которые принимают этот объект, который у меня есть. Это неверный запрос».

Если, однако, я отправляюэто как чистая строка (например, «{key1: value1»} вместо «{\» key1 \ »: \« value1 \ »}») без кавычек вокруг ключей и значений, контроллер и действие говорят «HEY!Это строка. Я получил это. "

Проблема в том, что в этот момент это не валидный json, просто что-то вроде JSON.И поэтому это не правильно обрабатывается внутренностями действия.

На данный момент и без дополнительных знаний и исследований, обходное решение состоит в том, чтобы изменить сигнатуру действия для ожидания параметра типа Object и специально его десериализовать.в рамках метода.

Хотя это работает, это не похоже на правильное решение, потому что я сейчас по сути открываю этот вызов для любого типа объекта вместо того, что мы действительно хотим, чтобы оно было.Это имеет смысл, поскольку функция AWS Lambda получает анонимный тип (т. Е. Объект).

Обновление: https://weblog.west -wind.com / posts / 2017 / Sep / 14 / Принятие необработанных запросов-содержимого-содержимого-в-ASPNET-Core-API-контроллерах

В этой статье рассматриваются типы решений, которые можно использовать для устранения этой проблемы.Суть в том, что Core API не знает, что делать со строкой.Существует несколько решений автора списков.Единственное, что я выбрал для реализации, - расширение входного форматера.Я кратко описал некоторые процессы здесь:

Новый класс -> RawRequestBodyFormatter : InputFormatter

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

override Boolean CanRead

override async Task<InputFormatterResult> ReadRequestBodyAsync

Проверьте context.HttpContext.Request.ContentType, чтобы увидеть, содержит ли он ваш text/plain модификатор.

При запуске добавьте следующее:

services.AddMvc(o => o.InputFormatters.Insert(0, new RawRequestBodyFormatter()));
0 голосов
/ 06 сентября 2018

Я бы предложил вам использовать библиотеку Flurl , это сэкономит вам много времени.

Таким образом, вы можете переключить свой код следующим образом (обратите внимание, что я прокомментировал некоторые строки, вы можете удалить эти строки в зависимости от использования запроса):

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;
}

С классом MyHttpClientFactory:

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;

    }
}

Надеюсь, вы найдете это полезным.

...