簡體   English   中英

無法讀取原始數據,因為 actionContext.Request.Content 在 Web API 的 Action 屬性中始終為空

[英]Cannot read raw data as actionContext.Request.Content always empty in Action attribute in Web API

我需要通過屬性讀取通過 post/put 發送到我的 Web API 的內容以執行一些額外的驗證,但內容值始終為空,即使我可以看到context-size設置了一個值,即 2067 和content-type設置為application/json

我嘗試了不同的方法,但似乎都沒有奏效:

  • 讀取異步
  • ReadAsByteArrayAsync
  • ReadAsStringAsync
  • ETC...

我的最后一次嘗試如下所示:

public async override void OnActionExecuting(HttpActionContext actionContext)
{
    using (MemoryStream ms = new MemoryStream())
    {
        await actionContext.Request.Content.CopyToAsync(ms)
                           .ConfigureAwait(false);
        var str = System.Text.UTF8Encoding.
                  UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length);
    }
}

我嘗試使用 CopyTo 的原因是我注意到,當我調用上述一些函數時,即使它們返回一個空字符串,我也可以在谷歌搜索后進行一次調用,我相信這是設計使然。

底線是我需要訪問我的請求的正文/內容,以便我可以檢查發送的 json。

謝謝。

這里的問題是執行 controller 操作的中間件讀取請求正文並因此在過程中消耗它,從而剝奪了任何后續中間件訪問它的機會。 這就是為什么您在嘗試解析 stream 時得到一個空字符串的原因,因為您正在有效地讀取長度為零的 stream 。

看起來 Action Filter 中間件是在 controller 中間件之后運行的,這在管道過程中已經太遲了。 一種解決方案是設置一個在 controller 中間件之前執行的自定義中間件,並僅當前操作端點使用給定屬性注釋時解析請求正文 stream。

此處提供的解決方案是為 ASP.NET Core 3.0 編寫的,因此您可能需要進行一些調整才能使其在您的特定項目中工作。

Startup.cs中:

public void Configure(IApplicationBuilder app)
{
   app.UseRouting();   // Routes middleware


   // Request body-reading middleware must be put after UseRouting()

   app.Use(async (ctx, next) =>
   {
      var endpoint = ctx.GetEndpoint();

      if (endpoint != null)
      {
         var attribute = endpoint.Metadata.GetMetadata<ThierryAttribute>();

         if (attribute != null)
         {
            ctx.Request.EnableBuffering();

            using (var sr = new StreamReader(ctx.Request.Body, Encoding.UTF8, false, 1024, true))
            {
               var str = await sr.ReadToEndAsync();   // Store request body JSON string
            }

            ctx.Request.Body.Position = 0;
         }
      }

      await next();
   });

   app.UseEndpoints(erb => erb.MapControllers());   // Controller middleware
}

並將您的屬性設置為空標記屬性:

[AttributeUsage(AttributeTargets.Method)]
public class ThierryAttribute : Attribute { }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM