netcore webapi接口同時支持多種編碼請求方式

功能:netcore webapi接口支持GET和POST請求,同時支持application/x-www-form-urlencoded和application/json兩種請求方式。

背景:在以前.NET Framework寫MVC5的時候,Action的參數前端傳遞的時候默認是可以自適應的,即:以queryString、表單或者json傳遞都能夠被正確接收,而到了asp.net core中,action接收參數默認只有queryString,顯式聲明瞭FromForm或FromBody之後也只能被表單或json接受,即使是同時打上FromForm和FromBody,也只有FromForm生效,FromBody不會起作用。

一、基本介紹

 

簡介:在http協議中規定了GET、HEAD、POST、PUT、DELETE、CONNECT 等請求方式,其中比較常用的就是POST和GET,其中POST用來向服務器提交數據,POST只規定了提交的數據必須放在請求的主體中,但是並沒有規定傳輸數據的編碼方式。簡單介紹一下主流的兩種編碼方式,也是實際開發中使用最多的兩種方式:

1.application/x-www-form-urlencoded

最常見的請求方式,特別是自己在測試後端接口時,經常在前端url中直接以鍵值對的形式寫入參數的值。但是該方式默認採用URLENCODE編碼會導致消息包大,form表單默認以該方式提交,請求一般是如下的方式:

Content-Type: application/x-www-form-urlencoded

title=test&text=test

2.application/json

application/json 這個 Content-Type 也是非常常見的,越來越多的人使用該方式傳遞,該方式傳遞的是序列化後的字符串,因爲採用的是JSON格式的數據,因此支持更多複雜的類型。請求體一般如下:

{

    "id":123,

    "name":"admin",

}

二、服務端接口請求和接收方法分析

方式1:

請求地址:/?id=123&name=bob

服務端方法:void Action(int id, string name)   

這裏的所有參數都是簡單類型,都來自url

方式2:

 請求地址:/?id=123&name=bob

服務端方法:

(1)void Action([FromUri] int id, [FromUri] string name)

這個和方式1一樣

(2) void Action([FromBody] string name);

這裏[FormBody]特性顯示標明讀取整個body爲一個字符串作爲參數

方式3:

請求地址: /?id=123

類定義:

public class Customer {   // 定義的一個複雜對象類型

  public string Name { get; set; }

  public int Age { get; set; }

}

(1)服務端方法: void Action(int id, Customer c) 

參數id從query string中讀取,參數c是一個複雜Customer對象類戲,通過formatter從body中讀取

(2)服務端方法: void Action(Customer c1, Customer c2)

這裏會出錯!多個參數都是複雜類型,都試圖從body中讀取,而body只能被讀取一次

(3)服務端方法: void Action([FromUri] Customer c1, Customer c2)

這種可以!不同於上面的action,複雜類型c1將從url中讀取,c2將從body中讀取

方式4:

ModelBinder方式:

void Action([ModelBinder(MyCustomBinder)] SomeType c)

//標示使用特定的model binder來解析參數

[ModelBinder(MyCustomBinder)]

public class

SomeType { } //

通過給特定類型SomeType聲明標註[ModelBidner(MyCustomBinder)]特性使得所有SomeType類型參數應用此規則

void Action(SomeType c) // 由於c的類型爲SomeType,因而應用SomeType上的特性決定其採用model binding

/*網上有篇文章:https://masuit.org/1889?t=v3oivzkjzjeo,裏面介紹了爲ASP.NET Core實現一個自適應ModelBinder,讓Action自適應前端參數傳遞

大體介紹如下:文章的目的是替換掉FromBody的默認行爲,寫一個自定義的ModelBinder。

最終實現的方法:

Masuit.Tools.AspNetCore

安裝這個nuget包,

並加入

builder.Services.AddControllers(options => options.ModelBinderProviders.InsertBodyOrDefaultBinding());

這行代碼即可*/

通過這個方法解決了queryString、表單或者json傳遞都能夠被正確接收,但是這裏如果通過瀏覽器GET請求訪問就會出錯了,因此筆者找到了另外一種解決方式。

方式5:

直接上代碼:

 定義接收參數實體:

 [ModelBinder(BinderType = typeof(SampleClassModelBinder))]

public class ParamEntity

{

        public string id { get; set; }

        public string name{ get; set; }

}

 

public class SampleClassModelBinder : IModelBinder

    {

        public async Task BindModelAsync(ModelBindingContext bindingContext)

        {

            try

            {

                var stream = bindingContext.HttpContext.Request.Body;

                string body;

                using (var reader = new StreamReader(stream))

                {

                    body = await reader.ReadToEndAsync();

                }

                var someClass = JsonConvert.DeserializeObject<TimeCountParamEntity>(body);

 

                bindingContext.Result = ModelBindingResult.Success(someClass);

            }

            catch (Exception ex)

            {             }

        }

    }

 方法:Action([FromBody] ParamEntity data)

 通過這個方法解決了queryString、表單或者json傳遞都能夠被正確接收,並可以通過瀏覽器GET請求訪問。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章