0

特定のケースで .NET Core 2.1 API が JSON 本体を無視しているように見える奇妙なバグに直面しています。

  • 他にも多くの質問にアドバイスしましたが (たとえば、これ自体が他のものを参照しています)、問題を解決できませんでした。

次の API メソッドのようなものがあります。

[Route("api/v1/accounting")]
public class AccountingController
{                                            sometimes it's null
                                                       ||
    [HttpPost("invoice/{invoiceId}/send")]             ||
    public async Task<int?> SendInvoice(               \/
         [FromRoute] int invoiceId, [FromBody] JObject body
    ) 
    {
        // ...                                                                   
    }
}

関連する構成は次のとおりです。

public IServiceProvider ConfigureServices(IServiceCollection services)
{
     services
       .AddMvcCore()
       .AddJsonOptions(options =>
        {
           options.SerializerSettings.Converters.Add(new TestJsonConverter());
        })
       .AddJsonFormatters()
       .AddApiExplorer();
     
     // ...
}

TestJsonConverterなぜ物事が期待どおりに機能しないのかをテストするために作成した単純なコンバーターはどこにありますか。それは簡単です。

public class TestJsonConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        return token;
    }
    public override bool CanRead
    {
        get { return true; }
    }
    public override bool CanConvert(Type objectType)
    {
        return true;
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary (would be neccesary if used for serialization)");
    }
}

CanConvertPostman を使用した api メソッドの呼び出しは機能します。つまり、JSON コンバーターの、CanRead、を通過し、解析された jsonを含むReadJsonにルーティングされます。SendInvoicebody

ただし、 HttpWebRequestを使用して api メソッドを呼び出すと(問題がある場合は .NET Framework 4 から)のみが通過しCanConvert、 nullにルーティングさSendInvoiceれます。body

リクエストの本文は、次のような単純な json です。

{
    "customerId": 1234,
    "externalId": 5678
}

本文を直接読み取ると、両方のケースで期待値が得られます。

using (var reader = new StreamReader(context.Request.Body))
{
   var requestBody = await reader.ReadToEndAsync(); // works
   var parsed = JObject.Parse(requestBody);
}

2 種類のリクエストに意味のある違いは見当たりません。左側は Postman のリクエスト、右側は HttpWebRequest です。

ここに画像の説明を入力

確かに、Content-Typeヘッダーは に設定されていapplication/jsonます。また、FWIW、HttpWebRequest本体は次のように設定されています。

using(var requestStream = httpWebRequest.GetRequestStream())
{
    JsonSerializer.Serialize(payload, requestStream);
}

そして、次のように呼び出します。

var response = (HttpWebResponse)request.GetResponse();   

質問

bodyで使用すると null になるのはなぜHttpWebRequestですか? このような場合、JSON コンバーターの読み取りメソッドがスキップされるのはなぜですか?

4

1 に答える 1