asp.net core - core書籍推薦 - 訪問原始請求正文



asp.net core asp.net mvc (3)

我試圖在ASP.net 5中訪問一個請求的原始輸入正文/流。過去,我能夠將輸入流的位置重置為0,並將其讀入內存流,但是當我嘗試這樣做時從上下文輸入流是null或拋出一個錯誤(System.NotSupportedException =>“不支持指定的方法”)。

在下面的第一個示例中,如果我將控制器方法的參數對像類型聲明為動態,則可以訪問控制器中的原始請求。 出於各種原因,這不是一個解決方案,我需要在身份驗證過濾器中訪問原始請求主體。

這個例子有效,但不是一個合理的解決方案:

[HttpPost("requestme")]
public string GetRequestBody([FromBody] dynamic body)
{   
    return body.ToString();
}

拋出錯誤:

[HttpPost("requestme")]
public string GetRequestBody()
{
    var m = new MemoryStream();
    Request.Body.CopyTo(m);

    var contentLength = m.Length;

    var b = System.Text.Encoding.UTF8.GetString(m.ToArray());

    return b;
}

拋出錯誤:

[HttpPost("requestme")]
public string GetRequestBody()
{
    Request.Body.Position = 0;
    var input = new StreamReader(Request.Body).ReadToEnd();

    return input;
}

拋出錯誤:

[HttpPost("requestme")]
public string GetRequestBody()
{
    Request.Body.Position = 0;
    var input = new MemoryStream();
    Request.Body.CopyTo(input);

    var inputString = System.Text.Encoding.UTF8.GetString(input.ToArray());

    return inputString;
}

我需要訪問正在構建的API的每個請求的原始請求主體。

任何幫助或方向將不勝感激!

編輯:

這裡是我想讀取請求正文的代碼。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Http;

namespace API.Filters
{
    public class CustomAuthorizationAttribute : Attribute, IAuthorizationFilter
    {
        public CustomAuthorizationAttribute()
        { }

        public void OnAuthorization(AuthorizationContext context)
        {
            if (context == null)
                throw new ArgumentNullException("OnAuthorization AuthorizationContext context can not be null.");
            else
            {
                if (this.AuthorizeCore(context.HttpContext) == false)
                {
                    // Do Other Stuff To Check Auth
                }
                else
                {
                    context.Result = new HttpUnauthorizedResult();
                }
            }
        }

        protected virtual bool AuthorizeCore(HttpContext httpContext)
        {
            var result = false;

            using (System.IO.MemoryStream m = new System.IO.MemoryStream())
            {
                try
                {
                    if (httpContext.Request.Body.CanSeek == true)
                        httpContext.Request.Body.Position = 0;

                    httpContext.Request.Body.CopyTo(m);

                    var bodyString = System.Text.Encoding.UTF8.GetString(m.ToArray());

                    return CheckBody(bodyString); // Initial Auth Check returns true/false <-- Not Shown In Code Here on Stack Overflow
                }
                catch (Exception ex)
                {
                    Logger.WriteLine(ex.Message);
                }
            }
                return false;
        }
    }
}

這個代碼將在調用一個標有CustomAuthorization屬性的控制器方法時被訪問。

[Filters.CustomAuthorizationAuthorization]
[HttpPost]
public ActionResult Post([FromBody]UserModel Profile)
{
    // Process Profile
}

https://ffff65535.com


Request.Body的實現取決於控制器的操作。

如果操作包含參數,則由Microsoft.AspNet.WebUtilities.FileBufferingReadStream實現,它支持seek( Request.Body.CanSeek == true )。 這種類型也支持設置Request.Body.Position

但是,如果您的操作不包含任何參數,則由Microsoft.AspNet.Loader.IIS.FeatureModel.RequestBody實現, 支持seek( Request.Body.CanSeek == false )。 這意味著你不能調整Position屬性,你可以開始讀取流。

這種差異可能與MVC需要從請求體中提取參數值的事實有關,因此需要讀取請求。

在你的情況下,你的動作沒有任何參數。 因此,使用Microsoft.AspNet.Loader.IIS.FeatureModel.RequestBody ,如果您嘗試設置Position屬性,則會引發異常。

解決方案 :要么不要設置位置,要么檢查是否可以先設置位置:

if (Request.Body.CanSeek)
{
    // Reset the position to zero to read from the beginning.
    Request.Body.Position = 0;
}

var input = new StreamReader(Request.Body).ReadToEnd();

我剛剛有同樣的問題。 從方法簽名中刪除參數,然後讀取你想要的Request.Body流。


您需要調用Request.EnableRewind()以允許流被重繞,以便您可以讀取它。

        string bodyAsString;
        Request.EnableRewind();
        using (var streamReader = new StreamReader(Request.Body, Encoding.UTF8))
        {
            bodyAsString = streamReader.ReadToEnd();
        }




asp.net-core-webapi