一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - Asp.Net Core控制器如何接收原始請求正文內容詳解

Asp.Net Core控制器如何接收原始請求正文內容詳解

2020-06-01 14:38范存威 ASP.NET教程

這篇文章主要給大家介紹了關于Asp.Net Core控制器如何接收原始請求正文內容的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

主要目標

在Asp.net Core控制器中,通過自定義格式化程序來映射自定義處理控制器中的“未知”內容。本文將給大家詳細介紹關于Asp.Net Core控制器接收原始請求正文內容的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧

簡單案例

為了演示這個問題,我們用VS2017創(chuàng)建一個默認的Asp.net Core Web Api項目。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase{
[HttpGet]
public ActionResult<string> Get() {
 return "ok";
}
 
[HttpPost]
[Route("PostX")]
public ActionResult<string> Post([FromBody] string value)
{
 return value;
}
}

Json請求

我們從最常見的json輸入請求開始。

?
1
2
3
4
User-Agent: Fiddler
Host: localhost:5000
Content-Type: application/json
Content-Length: 16

請求body:

?
1
{"123456"}

通過后臺調試和fiddler抓包,我們可以看到請求輸入和返回。

Asp.Net Core控制器如何接收原始請求正文內容詳解

后臺調試,查看請求輸入結果

Asp.Net Core控制器如何接收原始請求正文內容詳解

fiddler查看請求header

Asp.Net Core控制器如何接收原始請求正文內容詳解

fiddler查看返回結果

注意!!

別忘了[FromBody],有時候會忘的。
后臺action接收類型為string的時候,請求body只能是字符串,不能傳json對象。我演示這個例子時,被這點坑了。如果接收對象是一個類的時候,才可以傳json對象。

沒有JSON

雖然傳輸json數據是最常用的,但有時候我們需要支持普通的文本或者二進制信息。我們將Content-Type改為
text/plain

?
1
2
3
4
User-Agent: Fiddler
Host: localhost:5000
Content-Type:text/plain
Content-Length: 16

請求body:

?
1
{"123456"}

悲劇的事情來,報404!

Asp.Net Core控制器如何接收原始請求正文內容詳解
不支持text/plain

事情到此就變得稍微復雜了一些,因為asp.netcore只處理它認識的類型,如json和formdata。默認情況下,原始數據不能直接映射到控制器參數。這是個小坑,不知你踩到過沒有?仔細想想,這是有道理的。MVC具有特定內容類型的映射,如果您傳遞的數據不符合這些內容類型,則無法轉換數據,因此它假定沒有匹配的端點可以處理請求。
那么怎么支持原始的請求映射呢?

支持原始正文請求

不幸的是,ASP.NET Core不允許您僅通過方法參數以任何有意義的方式捕獲“原始”數據。無論如何,您需要對其進行一些自定義處理Request.Body以獲取原始數據,然后對其進行反序列化。

您可以捕獲原始數據Request.Body并從中直接讀取原始緩沖區(qū)。

最簡單,最不易侵入,但不那么明顯的方法是使用一個方法接受沒有參數的 POST或PUT數據,然后從Request.Body以下位置讀取原始數據:

讀取字符串緩沖區(qū)

?
1
2
3
4
5
6
7
8
9
[HttpPost]
[Route("PostText")]
public async Task<string> PostText()
{
 using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
 {
 return await reader.ReadToEndAsync();
 }
}

這適用于一下Http和文本

?
1
2
3
4
User-Agent: Fiddler
Host: localhost:5000
Content-Type: text/plain
Content-Length: 6

要讀取二進制數據,你可以使用以下內容:

讀取byte緩沖區(qū)

?
1
2
3
4
5
6
7
8
9
10
[HttpPost]
[Route("PostBinary")]
public async Task<byte[]> PostBinary()
{
 using (var ms = new MemoryStream(2048))
 {
 await Request.Body.CopyToAsync(ms);
 return ms.ToArray(); // returns base64 encoded string JSON result
 }
}

查看執(zhí)行結果

Asp.Net Core控制器如何接收原始請求正文內容詳解

接收文本內容

Asp.Net Core控制器如何接收原始請求正文內容詳解

接收二進制數據

HttpRequest靜態(tài)擴展

如果你為了方便,寫了很多HttpRequest的擴展,接收參數時,可以看起來更簡潔一些。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public static class HttpRequestExtension
 {
 /// <summary>
 ///
 /// </summary>
 /// <param name="httpRequest"></param>
 /// <param name="encoding"></param>
 /// <returns></returns>
 public static async Task<string> GetRawBodyStringFormater(this HttpRequest httpRequest, Encoding encoding)
 {
  if (encoding == null)
  {
  encoding = Encoding.UTF8;
  }
 
  using (StreamReader reader = new StreamReader(httpRequest.Body, encoding))
  {
  return await reader.ReadToEndAsync();
  }
 }
 /// <summary>
 /// 二進制
 /// </summary>
 /// <param name="httpRequest"></param>
 /// <param name="encoding"></param>
 /// <returns></returns>
 public static async Task<byte[]> GetRawBodyBinaryFormater(this HttpRequest httpRequest, Encoding encoding)
 {
  if (encoding == null)
  {
  encoding = Encoding.UTF8;
  }
 
  using (StreamReader reader = new StreamReader(httpRequest.Body, encoding))
  {
  using (var ms = new MemoryStream(2048))
  {
   await httpRequest.Body.CopyToAsync(ms);
   return ms.ToArray(); // returns base64 encoded string JSON result
  }
  }
 }
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[HttpPost]
[Route("PostTextX")]
public async Task<string> PostTextX()
{
 return await Request.GetRawBodyStringAsyn();
}
/// <summary>
/// 接收
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("PostBinaryX")]
public async Task<byte[]> PostBinaryX()
{
 return await Request.GetRawBodyBinaryAsyn();
}

自動轉換文本和二進制值

上面雖然解決了原始參數轉換問題,但不夠友好。如果你打算像原生MVC那樣自動映射參數的話,你需要做一些自定義格式化適配。

創(chuàng)建一個Asp.net MVC InputFormatter

ASP.NET Core使用一種干凈且更通用的方式來處理內容的自定義格式InputFormatter。輸入格式化程序掛鉤到請求處理管道,讓您查看特定類型的內容以確定是否要處理它。然后,您可以閱讀請求正文并對入站內容執(zhí)行自己的反序列化。

InputFormatter有幾個要求

  • 您需要使用[FromBody]去獲取
  • 您必須能夠查看請求并確定是否以及如何處理內容。

在這個例子中,對于“原始內容”,我想查看具有以下類型的請求:

  • text/plain(文本)
  • appliaction/octet-stream(byte[])
    沒有內容類型(string)

要創(chuàng)建格式化程序,你可以實現IInputFormatter或者從InputFormatter繼承。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class RawRequestBodyFormatter : IInputFormatter
{
 public RawRequestBodyFormatter()
 {
 
 }
 
 public bool CanRead(InputFormatterContext context)
 {
  if (context == null) throw new ArgumentNullException("argument is Null");
  var contentType = context.HttpContext.Request.ContentType;
  if (string.IsNullOrEmpty(contentType) || contentType == "text/plain" || contentType == "application/octet-stream")
   return true;
  return false;
 }
 
 public async Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
 {
  var request = context.HttpContext.Request;
  var contentType = context.HttpContext.Request.ContentType;
  if (string.IsNullOrEmpty(contentType) || contentType.ToLower() == "text/plain")
  {
   using (StreamReader reader = new StreamReader(request.Body, Encoding.UTF8))
   {
    var content = await reader.ReadToEndAsync();
    return await InputFormatterResult.SuccessAsync(content);
   }
  }
  if (contentType == "application/octet-stream")
  {
   using (StreamReader reader = new StreamReader(request.Body, Encoding.UTF8))
   {
    using (var ms = new MemoryStream(2048))
    {
     await request.Body.CopyToAsync(ms);
     var content = ms.ToArray();
 
     return await InputFormatterResult.SuccessAsync(content);
    }
   }
  }
  return await InputFormatterResult.FailureAsync();
 }
}

格式化程序用于CanRead()檢查對內容類型的請求以支持,然后將ReadRequestBodyAsync()內容讀取和反序列化為應在控制器方法的參數中返回的結果類型。

InputFormatter必須在ConfigureServices()啟動代碼中注冊MVC :

?
1
2
3
4
public void ConfigureServices(IServiceCollection services)
 {
  services.AddMvc(o=>o.InputFormatters.Insert(0,new RawRequestBodyFormatter())).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
 }

接受原始輸入

?
1
2
3
4
5
6
[HttpPost]
[Route("PostTextPlus")]
public string PostTextPlus([FromBody] string value)
{
 return value;
}

然后你就可以發(fā)送post請求,像這樣:

?
1
2
3
User-Agent: Fiddler
Host: localhost:5000
Content-Length: 6

或者

?
1
2
3
4
User-Agent: Fiddler
Host: localhost:5000
Content-Type:text/plain
Content-Length: 6

請注意,您可以使用內容類型調用相同的控制器方法application/json并傳遞JSON字符串,這也將起作用。在RawRequestBodyFormatter 簡單地增加它支持的附加內容類型的支持。

二進制數據

?
1
2
3
4
5
6
[HttpPost]
[Route("PostBinaryPlus")]
public byte[] PostBinaryPlus([FromBody] byte[] value)
{
 return value;
}

請求內容如下:

?
1
2
3
4
User-Agent: Fiddler
Host: localhost:5000
Content-Length: 6
Content-Type: application/octet-stream

源代碼

示例代碼已上傳到 CsharpFanDemo

參考鏈接

本文包含翻譯和自己實踐。主要思路和代碼來源于以下鏈接:
Accepting Raw Request Body Content in ASP.NET Core API Controllers

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.jianshu.com/p/4a96d73428dc

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲精品有码在线观看 | 5x社区在线观看直接进入 | 四虎成人影院 | 久久九九有精品国产23百花影院 | 91亚洲一区二区在线观看不卡 | 亚洲精品www久久久久久久软件 | 国产日韩欧美综合在线 | 男男羞羞视频网站国产 | 成人在线观看免费视频 | 女人全身裸露无遮挡免费观看 | 苍井空av| 日韩欧美中文字幕出 | 摸咪网在线影院在线观看 | 精品视频网站 | 免费观看伦理片 | 俄罗斯15一16处交 | 久久99国产亚洲高清观着 | 国内精品国语自产拍在线观看55 | 日韩毛片大全免费高清 | 啪一啪日一日 | 色无月 | 欧美日韩一区二区三区在线观看 | 国产首页精品 | 91精品国产91热久久久久福利 | jiuse在线| 特黄视频免费看 | 99久久综合给久久精品 | 美女用屁股把人吞进肚子 | 午夜在线播放免费人成无 | 91极品女神久色在线播放 | 国产在线视频资源 | 腿交hd| 波多野结衣黑人系列在线观看 | 好男人社区www影院在线观看 | 国产小视频网站 | 15同性同志18 | 精品国产一区二区三区在线观看 | videojapan日本孕交孕 | 欧美人鲁交大全 | 欧美国产合集在线视频 | 奇米激情|