2017-11-01 7 views
-2

Azure Appサービスに配備されたAspNetCoreにWebApiがあります。 WebApiは、オブジェクトの配列をポストするためにのみ使用できます。オブジェクトには多くのプロパティ(100+)と3つのオブジェクト配列が含まれています。 (それは建物を表す)。オブジェクト配列には、それぞれ300個以上のオブジェクトを含めることができます。大きなリクエストでAzure接続設定のWeb APIが失敗する

ビジュアルスタジオ2017(15.4.1)でデバッグしているとき、apiは正常に動作し、すべての要求を受け入れます。 Azureにデプロイされると、ほとんどの要求を受け入れます。しかし、いくつかは空白に消えます。それによって私は何の応答も全くないことを意味する。間違った要求には、配列の1つに多くのオブジェクトがあります。オブジェクトの量を特定の数に減らすことによって、要求が受け入れられます。つまり、ビジュアルスタジオではすべてのリクエストが受け入れられています。データ送信は確実です。

私はテストコントローラを作成しましたが、同じインターフェイスを使用しましたが、論理はなく、応答 "succes"のみでした!このインタフェースでは、要求も失敗します(同じ動作)。 Newtonsoft(10.0.3)は両方のコントローラでデシリアライズに使用されます。

これらの要求とのこの動作の違いを引き起こす原因は何ですか?

コントローラのコード:

public class TestController : Controller 
{  
    [HttpPost] 
    [RequireHttps] 
    public IActionResult Post([FromBody] Buildings Buildings) 
    { 
     enumActionResult status = enumActionResult.success; 
     try 
     { 
      if (Buildings == null) 
       throw new Exception("No valid buildings posted!"); 

      if (Buildings.items == null) 
       throw new Exception("No valid building items posted!"); 

      if (Buildings.items.Count == 0) 
       throw new Exception("Zero building items posted!"); 


      return Json(new response() { status = status.ToString(), Buildings = list 
     } 

     catch (Exception ex) 
     { 
      return Json(new ErrorResponseFormat() { message = ex.Message, status = enumActionResult.error, data = new ErrorResponse(ex) }); 
     } 
    } 
} 

アップデート(2017年12月19日): という問題が依然としてあるが、SSLに絞り込まれます。私は失敗したURLにhttpsで要求を行う、と私はそれがsuccesfullのあるHTTPのURLでまったく同じ要求を発射した場合

public class EchoController : Controller 
    { 
     [HttpPost]   
     public IActionResult Post() 
     { 
      return new FileStreamResult(Request.Body, Request.ContentType); 
     } 
    } 

:私は要求を返す新しいコントローラを作成しました。これは、デバッガから取得したのと同じ動作です。これは、httpのみを使用するためです。したがって、デバッガと紺碧のクラウド環境との違いの代わりに、httpとhttpsの問題があるように見えます。 (ブルース・チェンにより示唆されるように)私は設定で実装ところで

<system.webServer> 
     <security> 
      <requestFiltering> 
      <!-- Measured in Bytes --> 
      <requestLimits maxAllowedContentLength="4000000000" maxQueryString="100000000"/>   
      <!-- 1 GB, Byte in size, up to 2GB--> 
      </requestFiltering> 
     <access sslFlags="Ssl, SslRequireCert"/>   
     </security> 
     </system.webServer> 

および.NET 4.6.2にアップグレード。この時点ではまだ解決策はありませんが、問題は絞り込まれているようです。

更新(20-12-2017): 私は、次の面白いことを見つけました:私はそれが失われた(https)をAPIに「大」要求を送信します。しかし、小さなリクエストが先行すると、両方のリクエストが受け入れられます。だから、大規模な要求を伴う接続設定が失敗するようです。

webapiはカスタムドメインhttpsとIPホワイトリストを使用しています。クライアントは、クライアント証明書で認証する必要があります。完全なWebapiの設定(はい、前のrequestLimitsエントリを削除しました):

configuration> 
    <connectionStrings> 
    ... 
    </connectionStrings> 
    <system.webServer> 
    <security>  
     <access sslFlags="Ssl, SslRequireCert"/> 
    </security> 
    </system.webServer> 
    <runtime> 
     <gcServer enabled="true"/> 
    </runtime> 
</configuration> 

クライアントは証明書を使用して郵便番号です。何かご意見は?

+1

私たちは、いくつかのコード、ログ、または何かを見たりする必要があります。ちょうど推測するつもりです... – Milney

+0

ここで誰も何らかのコードを投稿する必要がある精神病者はいません。 POSTリクエストを使用していると確信しています。GETではなく、切り捨てられている可能性があります。あなたはnewsoftが非直列化に使用されていることを意味しますか?カスタムモデルバインダーを持っていますか?JSON –

+0

をコードで更新して送信していますか?カスタムモデルバインダーは使用されていません – Martijn

答えて

0

最後にmsnのブログでawnserが見つかりました。

https://blogs.msdn.microsoft.com/waws/2017/04/03/posting-a-large-file-can-fail-if-you-enable-client-certificates/

クライアントは、.NETアプリケーションではありませんので、当社のソリューションは、最初のオプションです。カンニングのような感じですが、うまくいきます。

(私は保存のため、リンクからテキストをコピーし、それを見つけることは本当に難しいですので、下に):

概要

あなたはクライアント証明書を必要とし、POSTまたは大量に置く場合のデータがないと、リクエストが失敗する可能性があります。これは少なくとも10年間IISに存在していた問題です(IISを使用しているため、WindowsプラットフォームのAzure App Servicesにも適用されます)。これに関する多くの情報はありませんので、このブログはこの問題を明確にするのに役立ちます。ソリューションは信じられないほど簡単です!

問題

は、HTTPS(TCP)のための基礎となるプロトコルは、複数のフレームに大きなデータパケットを分割します。通常、これはアプリケーションにとって問題ではなく、クライアントとサーバーの両方に対して透過的です。クライアント証明書を必要とする一部のアプリケーションは、最初のデータが複数のフレームでプッシュされ、IISサーバーがクライアント証明書を要求してから続行するときに、この問題が発生する可能性があります。データがクライアントからサーバーに流れ始めると(Server Helloの最初のSSLハンドシェイクの後)、データの最初のパケットが送信されると、実際にネットワークトレースでこれを見ることができます。サーバー応答はクライアント証明書の要求の開始であり、クライアントからの次のパケットにはさらに多くのデータが含まれています。この時点で、サーバーは、ワイヤー上の次のデータがクライアント証明書であると予想したため、エラーをスローします。全体POST要求またはPUTが完了したので、これはデータの小さなパケットでは発生しないと、サーバーが取得する次のことは、クライアント証明書のハンドシェークとPUSHからではない追加データISまたはPUT

解像度

は、この問題を解決するために、あなたは、単にこれら二つの技術の一つを利用する必要があります:設定しHEADリクエスト

  • で最初の接続を確立し

    • を期待:100-引き続きリクエストのヘッダーを

    オプション1:最初にHEADリクエストで接続を確立する 次のオプションと同じくらい好きではありませんが、正常に機能しました。概念は、HEAD要求が全くデータを持たず、問題なしにSSL接続を確立することです。次に、HTTPライブラリの基本的な実装を利用してこの接続を再利用します。ほとんどの場合、SSLハンドシェイクはもう発生しません。

    オプション2:for:Expect:100-continueヘッダーをforリクエスト これは最適なオプションです。 RFCによると、これが実際に存在するのはこのためです!簡単に言えば、サーバーが要求の準備ができたら(この場合はSSL交渉の後に)、100ステータスが戻され、データをPOSTまたはPUTし続けることができます。すべてのHTTPクライアントライブラリはこれを実装しています(RFCの一部であるため)。これは簡単で、動作することが保証されています。 以下は、HttpWebRequest(またはそれらの派生物)を使用しているときに.NETでこれを設定するサンプルです。コードでHTTPリクエストを作成する前に、コード内でこれを一度行います(global.asaxやStartup.csのように) ServicePointManager.Expect100Continue = true;参照:ServicePointManager.Expect100Continueプロパティ 新しいHttpClientクラスを使用している場合は、これが自動的に追加されますこれは10年以上問題になっているが(明白な理由のために)。

    概要 はテキストを強調し、これはヘッダを期待するので、最も可能性の高いパブリック面するドキュメント(への道を発見したことはありませんがためのベストプラクティスです私たちの古い学校のタイプ、新しいクラスやライブラリにはデフォルトでこのヘッダがすべて含まれています)

  • 0

    私の理解しているところでは、あなたの要求はIISの制限に達する可能性があります。

    はバイト単位で、要求のコンテンツの最大長を指定します。次のように説明requestLimitsためmaxAllowedContentLength属性として

    デフォルト値は、私は次のようにあなたがmaxAllowedContentLengthを高めることができると仮定30000000

    です:

    <security> 
        <requestFiltering> 
        <!-- Measured in Bytes --> 
        <requestLimits maxAllowedContentLength="1073741824" /> <!-- 1 GB, Byte in size, up to 2GB--> 
        </requestFiltering> 
    </security> 
    

    私はあなたがあなたのリクエストボディのサイズを確認し、しよう推薦maxAllowedContentLengthを増やしてこの問題を絞り込みます。さらに、ASP.NETコア2.0.0で要求サイズの制限について語っているissueが見つかりました。また、同様の問題があります。hereを参照してください。

    +0

    JSONリクエストはそれほど大きくありません。 134,977文字(+/- 136.95 KB)のJSONリクエストが失敗します。私は何の応答も得ていない.2分後の郵便配達人からのタイムアウトのみ。開発環境では、応答は0.5秒以内です。私はあなたの提案を適用しましたが、行動に変化はありません – Martijn

    関連する問題