小范筆記:ASP.NET Core API 基礎知識與Axios前端提交數據

跟同事合做先後端分離項目,本身對 WebApi 的不少知識不夠全,雖然說沒必要要學全棧,但是也要了解基礎知識,才能合理設計接口、API,方便與前端交接。html

晚上回到宿舍後,對 WebApi 的知識查漏補缺,主要補充了 WebAPi 的一些方法、特性等如何與前端契合,如何利用工具測試 API 、Axios 請求接口。前端

本文主要寫 WebApi 前端請求數據到 API 、後端返回處理結果,不涉及登陸、跨域請求、前端 UI 等。(難一點我不會了。。。看張隊的公衆號,篇篇都看不懂。。。)ios

前提:會一點點 VUE、會一點 Axios、會一點點 Asp.net Core。git

工具:Visual Studio 2019(或者其它版本) + Visual Studio Code + Swagger +Postmangithub

因爲 Visual Studio 2019 寫 ASP.NET Core 頁面時,沒有 Vue 的智能提示,因此須要使用 VSCode 來寫前端頁面。web

本文 代碼 已發佈到 GitHub https://github.com/whuanle/CZGL.IKonwWebApishell

 

一. 微軟WebApi

特性 綁定源
[FromBody] 請求正文
[FromForm] 請求正文中的表單數據
[FromHeader] 請求標頭
[FromQuery] 請求查詢字符串參數
[FromRoute] 當前請求中的路由數據
[FromServices] 做爲操做參數插入的請求服務

來一張 Postman 的圖片:

HTTP 請求中,會攜帶不少參數,這些參數能夠在前端設置,例如表單、Header、文件、Cookie、Session、Token等。

那麼,上面的表格正是用來從 HTTP 請求中獲取數據的 「方法」 或者說 「手段」。HttpContext 等對象不在本文討論範圍。

Microsoft.AspNetCore.Mvc 命名空間提供不少用於配置Web API 控制器的行爲和操做方法的屬性:

特性 說明
[Route] 指定控制器或操做的 URL 模式。
[Bind] 指定要包含的前綴和屬性,以進行模型綁定。
[Consumes] 指定某個操做接受的數據類型。
[Produces] 指定某個操做返回的數據類型。
[HttpGet] 標識支持 HTTP GET 方法的操做。
[HttpPost] 標識支持 HTTP POST 方法的操做。
... ... ... ... ... ...

WebApi 應用

首先建立一個 Asp.Net Core MVC 應用,而後在 Controllers 目錄添加一個 API 控制器 DefaultController.cs。(這裏不建立 WebApi 而是 建立 MVC,經過 MVC 建立 API 控制器)。

建立後默認代碼:

[Route("api/[controller]")] [ApiController] public class DefaultController : ControllerBase { }
1. 安裝 Swagger

在 Nuget 中搜索 Swashbuckle.AspNetCore,或打開 程序包管理器控制檯 -> 程序包管理器控制檯 ,輸入如下命令進行安裝

Install-Package Swashbuckle.AspNetCore -Version 5.0.0-rc2

打開 Startup 文件,添加引用

using Microsoft.OpenApi.Models;

在 ConfigureServices 中添加服務,雙引號文字內容隨便改。

            services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); });

添加中間件

            app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); // 添加下面的內容 app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); });

訪問 /swagger 能夠訪問到 Swagger 的 UI 界面。

爲了便於查看輸出和固定端口,打開 Progarm,cs ,修改內容

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseUrls("https://*:5123") .UseStartup<Startup>();

1562163847(1)

不要使用 IIS 託管運行。

注意:本文所有使用 [HttpPost] ;全局使用 JsonResult 做爲返回類型。

二. 數據綁定與獲取

1,默認不加

直接寫 action,不使用特性

        [HttpPost("aaa")] public async Task<JsonResult> AAA(int? a, int? b) { if (a == null || b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 2000, result = a + "|" + b }); }

打開 https://localhost:5123/swagger/index.html 查看 UI 界面 1562138960(1)

也就是說,建立一個 action ,什麼都不加,默認是 query

經過 Postman 提交數據、測試接口

1562139085(1)

對於 Query 的 action 來講, axios 的寫法

    postaaa: function () { axios.post('/api/default/aaa?a=111&b=222' ) .then(res => { console.log(res.data) console.log(res.data.code) console.log(res.data.result) }) .catch(err => { console.error(err); }) }

在網上查找資料時,發現有人說經過 params 添加數據也能夠,不過筆者測試,貌似不行。

講道理,別人能夠,爲啥我不行。。。

axios 代碼:

  postaaa: function () { axios.post('/api/default/aaa', { params: { a: 123, b: 234 } } ) .then(res => { console.log(res.data) console.log(res.data.code) console.log(res.data.result) }) .catch(err => { console.error(err); }) }

包括下面的,都試過了,不行。

axios.post('/api/default/aaa', {
                            a:1234,
                            b:1122
                    }
                    
                    
    axios.post('/api/default/aaa', {
                        data:{
                            a:1234,
                            b:1122
                        }
                    }

把 [HttpPost] 改爲 [HttpGet] ,則可使用

axios.post('/api/default/aaa', { params: { a: 123, b: 234 } } ... ...

提示:

		... ... .then(res => { console.log(res.data) console.log(res.data.code) console.log(res.data.result) }) .catch(err => { console.error(err); })

.then 當請求成功時觸發,請求失敗時觸發 catch 。res 是請求成功後返回的信息,res.data 是請求成功後服務器返回的信息。便是 action 處理數據後返回的信息。

在瀏覽器,按下 F12 打開控制檯,點擊 Console ,每次請求後,這裏會打印請求結果和數據。

2, [FromBody]

官方文檔解釋:請求正文。[FromBody] 針對複雜類型參數進行推斷。 [FromBody] 不適用於具備特殊含義的任何複雜的內置類型,如 IFormCollection 和 CancellationToken。 綁定源推理代碼將忽略這些特殊類型。

算了,看得一頭霧水,手動實際試試。

剛剛開始的時候,我這樣使用:

        public async Task<JsonResult> BBB([FromBody]int? a, [FromBody]int? b)

結果編譯時就報錯,提示只能使用一個 [FromBody],因而改爲

        [HttpPost("bbb")] public async Task<JsonResult> BBB([FromBody]int? a, int? b) { if (a == null || b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 2000, result = a + "|" + b }); }

打開 Swagger UI 界面,刷新一下

1562139375(1)

從圖片中發現,只有 b,沒有 a,並且右上角有下拉框,說明了加 [FromBody] 是 json 上傳。

那麼說明 [FromBody] 修飾得應當是對象,而不是 字段。

修改程序以下:

	// 增長一個類型 public class AppJson { public int? a { get; set; } public int? b { get; set; } } [HttpPost("bbb")] public async Task<JsonResult> BBB([FromBody]AppJson ss) { if (ss.a == null || ss.b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 2000, result = ss.a + "|" + ss.b }); }

再看看微軟的文檔:[FromBody] 針對複雜類型參數進行推斷。,這下可理解了。。。

便是不該該對 int、string 等類型使用 [FromBody] ,而應該使用一個 複雜類型

並且,一個 action 中,應該只能使用一個 [FromBody] 。

打開 Swagger 界面(有修改須要刷新下界面,下面再也不贅述)。

1562139627(1)

這樣纔是咱們要的結果嘛,前端提交的是 Json 對象。

用 Postman 測試下

1562139749(1)

證明了猜測,嘿嘿,嘿嘿嘿。

前端提交的是 Json 對象,遵循 Json 的格式規範,那麼 [FromBody] 把它轉爲 Object 對象。

前端 axios 寫法:

            methods: {
                postaaa: function () { axios.post('/api/default/bbb', { "a": 4444, "b": 5555 }) .then(res => { console.log(res.data) console.log(res.data.code) console.log(res.data.result) }) .catch(err => { console.error(err); }) } }
3, [FromForm]
        [HttpPost("ccc")] public async Task<JsonResult> CCC([FromForm]int? a, [FromForm]int? b) { if (a == null || b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 200, result = a + "|" + b }); }

固然,這樣寫也行,多個字段或者對象均可以

        [HttpPost("ccc")] public async Task<JsonResult> CCC([FromForm]AppJson ss) { if (ss.a == null || ss.b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 200, result = ss.a + "|" + ss.b }); }

1562141896(1)

根據提示,使用 Postman 進行測試

0187f3234bb69a6eea144a3a16ee5d8

事實上,這樣也行 ↓

form-data 和 x-www.form-urlencoded 都是鍵值形式,文件 form-data 能夠用來上傳文件。具體的區別請自行查詢。

df8a45f6c95af394ae2fdbb269f9ae2

axios 寫法(把 Content-Type 字段修改爲 form-data 或 x-www.form-urlencoded )

 postccc: function () { let fromData = new FormData() fromData.append('a', 111) fromData.append('b', 222) axios.post('/api/default/ccc', fromData, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) .then(res => { console.log(res.data) console.log(res.data.code) console.log(res.data.result) }) .catch(err => { console.error(err); }) }
4, [FromHeader]

[FromHeader] 不以表單形式上傳,而是跟隨 Header 傳遞參數。

        [HttpPost("ddd")] public async Task<JsonResult> DDD([FromHeader]int? a, [FromHeader]int? b) { if (a == null || b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 200, result = a + "|" + b }); }

1562144122(1)

axios 寫法

postddd: function () { axios.post('/api/default/ddd', {}, { headers: { a: 123, b: 133 } }) .then(res => { console.log(res.data) console.log(res.data.code) console.log(res.data.result) }) .catch(err => { console.error(err); }) }

須要注意的是,headers 的參數,必須放在第三位。沒有要提交的表單數據,第二位就使用 {} 代替。

params 跟隨 url 一塊兒在第一位,json 或表單數據等參數放在第二位,headers 放在第三位。

因爲筆者對前端不太熟,這裏有說錯,麻煩大神評論指出啦。

5, [FromQuery]

前面已經說了,Action 參數不加修飾,默認就是 [FromQuery] ,參考第一小節。

有個地方須要記住, Action 參數不加修飾。默認就是 [FromQuery] ,有時幾種參數並在一塊兒放到 Action 裏,會忽略掉,調試時忘記了,形成麻煩。

6, [FromRoute]

獲取路由規則,這個跟前端上傳的參數無關;跟 URL 能夠說有關,又能夠說無關。

        [HttpPost("fff")] public async Task<JsonResult> FFFxxx(int a,int b, [FromRoute]string controller, [FromRoute]string action) { // 這裏就不處理 a和 b了 return new JsonResult(new { code = 200, result = controller+"|"+action }); }

1562147096

[FromRoute] 是根據路由模板獲取的,上面 API 的兩個參數和路由模板的名稱是對應的:

[FromRoute]string controller, [FromRoute]string action
            app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });

固然,還能夠加個 [FromRoute]int? id

[FromRoute] 和 [FromQuery] 區別

以此 URL 爲例

https://localhost:5123/api/Default/fff?a=111&b=22

Route 會查到 controller = Default ,action = FFFxxx 。查詢到的是代碼裏的真實名稱。

Query 會查詢到 a = 111 和 b = 22

那麼,若是路由規則裏,不在 URL 裏出現呢?

        [HttpPost("/ooo")] public async Task<JsonResult> FFFooo(int a, int b, [FromRoute]string controller, [FromRoute]string action) { // 這裏就不處理 a和 b了 return new JsonResult(new { code = 200, result = controller + "|" + action }); }

那麼,訪問地址變成 https://localhost:5123/ooo

經過 Postman ,測試

df8a45f6c95af394ae2fdbb269f9ae2

說明了 [FromRoute] 獲取的是代碼裏的 Controller 和 Action 名稱,跟 URL 無關,根據測試結果推斷跟路由表規則也無關。

7, [FromService]

參考 https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.2

這個是與依賴注入容器有關,跟 URL 、路由等無關。

新建一個接口、一個類

    public interface ITest { string GGG { get; } } public class Test : ITest { public string GGG { get { return DateTime.Now.ToLongDateString(); } } }

在 ConfigureServices 中 注入

            services.AddSingleton<ITest, Test>();

在 DefaultController 中,建立構造函數,而後

        private readonly ITest ggg; public DefaultController(ITest ttt) { ggg = ttt; }

添加一個 API

        [HttpPost("ggg")] public async Task<JsonResult> GGG([FromServices]ITest t) { return new JsonResult(new { code = 200, result = t.GGG }); }

訪問時,什麼參數都不須要加,直接訪問此 API 便可。

1562148774(1)

[FromService] 跟後端的代碼有關,跟 Controller 、Action 、URL、表單數據等無關。

小結:

特性能夠幾種放在一塊兒用,不過儘可能每一個 API 的參數只使用一種特性。

優先取值 Form > Route > Query

IFromFile 因爲文件的上傳,本文就不談這個了。

關於數據綁定,更詳細的內容請參考:

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/model-binding?view=aspnetcore-2.2

三. action 特性方法

Microsoft.AspNetCore.Mvc 命名空間提供可用於配置 Web API 控制器的行爲和操做方法的屬性。

下表是針對於 Controller 或 Action 的特性.

特性 說明
[Route] 指定控制器或操做的 URL 模式。
[Bind] 指定要包含的前綴和屬性,以進行模型綁定。
[Consumes] 指定某個操做接受的數據類型。
[Produces] 指定某個操做返回的數據類型。
[HttpGet] 標識支持 HTTP GET 方法的操做。
... ...

下面使用這些屬性來指定 Controller 或 Action 接受的 HTTP 方法、返回的數據類型或狀態代碼。

1, [Route]

在微軟文檔中,把這個特性稱爲 屬性路由 ,定義:屬性路由使用一組屬性將操做直接映射到路由模板。

請教了大神,大神解釋說,ASP.NET Core 有路由規則表,路由表是全局性、惟一性的,在程序運行時,會把全部路由規則收集起來。

MVC 應用中設置路由的方法有多種,例如

            app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
 [Route("Home/Index")] public IActionResult Index() { return View(); }
    [Route("api/[controller]")] [ApiController] public class DefaultController : ControllerBase { }

路由是全局惟一的,能夠經過不一樣形式使用,可是規則不能發生衝突,程序會在編譯時把路由表收集起來。

根據筆者經驗,發生衝突,應該就是在編譯階段直接報錯了。(注:筆者不敢肯定)

關於路由,請參考 :

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/routing?view=aspnetcore-2.2#token-replacement-in-route-templates-controller-action-area

2, [Bind]

筆者知道這個是綁定模型的,可是對原理不太清楚。ASP.NET Core 自動生成的可讀寫的 Controller ,默認都是使用 [Bind] 來綁定數據。

文檔定義:用於對複雜類型的模型綁定。

有下面幾種相近的特性:

  • [BindRequired]
  • [BindNever]
  • [Bind]

微軟文檔提示:若是發佈的表單數據是值的源,則這些屬性會影響模型綁定。

就是說,上面的特性是針對類、接口等複雜類型(下面統稱模型),對於 int、string 這些類型,可能出毛病。

[BindRequired] 、[BindNever] 只能應用於模型的屬性,如

    public class TestB { [BindNever] public int ID { get; set; } [BindRequired] public string Name { get; set; } }

可是 [BindRequired] 、[BindNever] 不在討論範圍內,這裏只說 [Bind]。

[Bind] 用於類或方法(Controller、Action),指定模型綁定中應包含的模型屬性。

在微軟官方文檔,對於[Bind] 的解釋:

  • [Bind] 屬性可用於防止「建立」方案中的過多發佈狀況 。 因爲排除的屬性設置爲 NULL 或默認值,而不是保持不變,所以它在編輯方案中沒法很好地工做;
  • 由於 Bind 特性將清除未在 某個 參數中列出的字段中的任何之前存在的數據。

一臉懵逼。

下面是個人踩坑過程,不感興趣的話直接跳過吧。筆記筆記,記得固然是本身以爲要記的哈哈哈。

新建一個類

    public class TestBind { public string A { get; set; } public string B { get; set; } public string C { get; set; } public string D { get; set; } public string E { get; set; } public string F { get; set; } public string G { get; set; } }

新建 API

        [HttpPost("hhh")] public async Task<JsonResult> HHH([Bind("A,B,C")] TestBind test) { if (ModelState.IsValid == true) return new JsonResult(test); return new JsonResult(new { Code = 0, Result = "驗證不經過" }); }

15622028717670

使用 Postman 進行,測試,發現必須使用 Json 形式,才能訪問到這個 Action ,其它方式會直接 返回 錯誤。

{
    "errors": { "": [ "A non-empty request body is required." ] }, "title": "One or more validation errors occurred.", "status": 400, "traceId": "0HLO03IFQFTQU:00000007" }

經過兩次 Postman 進行測試

15622032271015

15622037112944

通過測試,我猜測

ModelState.IsValid 跟模型裏的驗證規則有關係,跟 [Bind] 不要緊(儘管用於測試的 TestB 類中沒有寫驗證規則),所以不能使用 ModelState.IsValid 驗證 [Bind] 是否符合規則。

Action 的參數:[Bind("A,B,C")] TestBind test,剛開始的時候我覺得請求的數據中必須包含 A、B、C。

測試後發現不是。。。再認真看了文檔 :由於 Bind 特性將清除未在 某個 參數中列出的字段中的任何之前存在的數據。

我修改一下:

        [HttpPost("hhh")] public async Task<JsonResult> HHH( string D, string E,[Bind("A,B,C")] TestBind test) { if (ModelState.IsValid == true) return new JsonResult(new { data1 = test, data2 = D, data3 = E }); return new JsonResult(new { Code = 0, Result = "驗證不經過" }); }

參數變成了 string D, string E,[Bind("A,B,C")] TestBind test

使用 Swagger 進行測試:

15622043721294返回結果

{
  "data1": { "a": "string", "b": "string", "c": "string", "d": "string", "e": "string", "f": "string", "g": "string" }, "data2": null, "data3": null }

改爲

        [HttpPost("hhh")] public async Task<JsonResult> HHH([Bind("A,B,C")] TestBind test, string J, string Q) { if (ModelState.IsValid == true) return new JsonResult(new { data1 = test, data2 = J, data3 = Q }); return new JsonResult(new { Code = 0, Result = "驗證不經過" }); }

返回結果

{
  "data1": { "a": "string", "b": "string", "c": "string", "d": "string", "e": "string", "f": "string", "g": "string" }, "data2": null, "data3": null }

文檔中對 [Bind] 描述最多的是:防止過多發佈。

經過上面的測試,首先確定的是一個 Action 裏,有多個參數 如

[Bind("A,B,C")] TestBind test, string D, string E string J, string Q

注意,下面的結論是錯的!

那麼 D、E 由於於 除了 Test, J、Q就會無效,經過百度,[Bind] 修飾的 Action ,前端請求的數據只有 Test 裏面的數據有效,其它 Query等形式一併上傳的數據都會失效,防止黑客在提交數據時摻雜其它特殊參數。應該就是這樣理解吧。

上面是一開始個人結論,直到屢次測試,我發現是錯的。

但是有一個地方不明白,

[Bind("A,B,C")]
[Bind("A,B,C,D,E,F,G")]

這二者的區別是是什麼。仍是沒搞清楚。

忽然想到 Query,當字段沒有使用特性修飾時,默認爲 Query 。

最終踩坑測試代碼

模型類

    public class TestBind { public string A { get; set; } public string B { get; set; } public string C { get; set; } public string D { get; set; } public string E { get; set; } public string F { get; set; } public string G { get; set; } }

Action

        [HttpPost("hhh")] public async Task<JsonResult> HHH( string A, string B, string E, string F, string G, [Bind("A,B,C,D")] TestBind test, string C, string D, string J, string Q) { if (ModelState.IsValid == true) return new JsonResult(new { data1 = test, dataA = A, dataB = B, dataC = C, dataD = D, dataE = E, dataF = F, dataG = G, dataJ = J, dataQ = Q }); return new JsonResult(new { Code = 0, Result = "驗證不經過" }); }

Swagger 測試

15622129564070

Postman 測試

15622126298494

15622126493775

{
    "data1": { "a": "111", "b": "111", "c": "111", "d": "111", "e": "111", "f": "111", "g": "111" }, "dataA": "222", "dataB": "222", "dataC": "222", "dataD": "222", "dataE": "222", "dataF": "222", "dataG": "222", "dataJ": "222", "dataQ": "222" }

再在 Swagger 或 Postman ,換着法子嘗試各類不一樣組合的輸入。

我懵逼了。試了半天試不出什麼。

實在不理解 [Bind] 裏,「防止過多發佈」 是什麼意思

[Bind("A,B,C")] 
[Bind("A,B,C,D,E,F,G")] 

這二者的區別是是什麼。仍是沒搞清楚。算了,不踩了。

我再到 stackoverflow 提問題,地址 https://stackoverflow.com/questions/56884876/asp-net-core-bind-how-to-use-it/56885153#56885153

得到一個回答:

What's the difference between [Bind("A,B,C")] and [Bind("A,B,C,D,E,F,G")]?

The former tells the model binder to include only the properties of TestBind named A, B and C. The latter tells the model binder to include those same properties plus D, E, F and G.

Are you testing by posting data for all properties of your model? You should notice that the values you post for the excluded properties are not bound.

算了,嘿嘿,測試不出來,放棄。

3, [Consumes]、[Produces]
        [Consumes("application/json")] [Produces("application/json")] [Produces("application/xml")] [Produces("text/html")] ... ...

目前只瞭解到 [Consumes]、[Produces] 是篩選器,用來表示 Controller 或 Action 所能接受的數據類型。大概就是像下面這樣使用:

[Consumes("application/json")]
    [Produces("application/json")]
    public class DefaultTestController : ControllerBase
    {

    }

可是如何實際應用呢?我找了好久,都沒有找到什麼結果。在 stackoverflow 找到一個回答:

https://stackoverflow.com/questions/41462509/adding-the-produces-filter-globally-in-asp-net-core

4, [HttpGet]、[HttpPost]、[HttpDelete]、[HttpPut]

修飾 Action ,用來標識這個 Action 可以經過什麼方式訪問、訪問名稱。

例如:

    [Route("api/[controller]")] [ApiController] public class DefaultController : ControllerBase { [HttpPost("aaa")] public async Task<JsonResult> AAA(int? a, int? b) { if (a == null | b == null) return new JsonResult(new { code = 0, result = "aaaaaaaa" }); return new JsonResult(new { code = 200, result = a + "|" + b }); } } 

訪問地址 https://localhost:5123/api/Default/aaa

使用時,會受到 Controller 和 Action 路由的影響。

但 自己亦可控制路由。以上面的控制器爲例

[HttpPost("aaa")] //相對路徑 

訪問地址 xxx:xxx/api/Default/aaa

[HttpPost("/aaa")] //絕對路徑 

訪問地址 xxx:xxx/aaa

四,返回類型

1, 查詢備忘表

Microsoft.AspNetCore.Mvc 命名空間中,包含控制 MVC 的各類操做方法和類型,筆者從命名空間中抽出與 MVC 或 API 返回類型有關的類型,生成表格:

類型 描述
AcceptedAtActionResult An ActionResult that returns a Accepted (202) response with a Location header.
AcceptedAtRouteResult An ActionResult that returns a Accepted (202) response with a Location header.
AcceptedResult An ActionResult that returns an Accepted (202) response with a Location header.
AcceptVerbsAttribute Specifies what HTTP methods an action supports.
ActionResult A default implementation of IActionResult.
ActionResult A type that wraps either an TValue instance or an ActionResult.
BadRequestObjectResult An ObjectResult that when executed will produce a Bad Request (400) response.
BadRequestResult StatusCodeResult that when executed will produce a Bad Request (400) response.
ChallengeResult An ActionResult that on execution invokes AuthenticationManager.ChallengeAsync.
ConflictObjectResult An ObjectResult that when executed will produce a Conflict (409) response.
ConflictResult StatusCodeResult that when executed will produce a Conflict (409) response.
ContentResult  
CreatedAtActionResult An ActionResult that returns a Created (201) response with a Location header.
CreatedAtRouteResult An ActionResult that returns a Created (201) response with a Location header.
CreatedResult An ActionResult that returns a Created (201) response with a Location header.
EmptyResult Represents an ActionResult that when executed will do nothing.
FileContentResult Represents an ActionResult that when executed will write a binary file to the response.
FileResult Represents an ActionResult that when executed will write a file as the response.
FileStreamResult Represents an ActionResult that when executed will write a file from a stream to the response.
ForbidResult An ActionResult that on execution invokes AuthenticationManager.ForbidAsync.
JsonResult An action result which formats the given object as JSON.
LocalRedirectResult An ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header to the supplied local URL.
NotFoundObjectResult An ObjectResult that when executed will produce a Not Found (404) response.
NotFoundResult Represents an StatusCodeResult that when executed will produce a Not Found (404) response.
OkObjectResult An ObjectResult that when executed performs content negotiation, formats the entity body, and will produce a Status200OK response if negotiation and formatting succeed.
OkResult An StatusCodeResult that when executed will produce an empty Status200OKresponse.
PartialViewResult Represents an ActionResult that renders a partial view to the response.
PhysicalFileResult FileResult on execution will write a file from disk to the response using mechanisms provided by the host.
RedirectResult An ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header to the supplied URL.
RedirectToActionResult An ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header. Targets a controller action.
RedirectToPageResult An ActionResult that returns a Found (302) or Moved Permanently (301) response with a Location header. Targets a registered route.
RedirectToRouteResult An ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header. Targets a registered route.
SignInResult An ActionResult that on execution invokes AuthenticationManager.SignInAsync.
SignOutResult An ActionResult that on execution invokes AuthenticationManager.SignOutAsync.
StatusCodeResult Represents an ActionResult that when executed will produce an HTTP response with the given response status code.
UnauthorizedObjectResult An ObjectResult that when executed will produce a Unauthorized (401) response.
UnauthorizedResult Represents an UnauthorizedResult that when executed will produce an Unauthorized (401) response.
UnprocessableEntityObjectResult An ObjectResult that when executed will produce a Unprocessable Entity (422) response.
UnprocessableEntityResult StatusCodeResult that when executed will produce a Unprocessable Entity (422) response.
UnsupportedMediaTypeResult StatusCodeResult that when executed will produce a UnsupportedMediaType (415) response.
ViewComponentResult An IActionResult which renders a view component to the response.
ViewResult Represents an ActionResult that renders a view to the response.
VirtualFileResult FileResult that on execution writes the file specified using a virtual path to the response using mechanisms provided by the host.

留着寫 WebApi 時查詢備忘嘿嘿。

那些類型主要繼承的兩個接口:

類型 描述
IActionResult Defines a contract that represents the result of an action method.
IViewComponentResult Result type of a ViewComponent.

注意的是,上面有些是抽象類,例如 FileResult,而 FileStreamResult 實現了 FileResult 。有些類是繼承關係。

2, 返回的數據類型
  1. 特定類型
  2. IActionResult 類型
  3. ActionResult 類型

Action 的 return ,返回的數據類型一定是上面三種。

3, 直接返回基元或複雜數據類型
[HttpGet]
public IEnumerable<Product> Get() { return _repository.GetProducts(); } 
4, IActionResult 類型

響應狀態碼、Json、重定向、URL 跳轉等,屬於 IActionResult。

MVC 的 Controller 與 API 的 Controller 有不少相同的地方,亦有不少不一樣的地方。

API 的 Controller 繼承 ControllerBase

MVC 的 Controller 繼承 Controller而 Controller 繼承

Controller :   ControllerBase, IActionFilter, IFilterMetadata, IAsyncActionFilter, IDisposable 

API 裏的 Controller 是最原始的。

API 裏的 返回類型須要實例化, new 一下; MVC 裏的返回類型,「不須要實例化」。

固然,有些例如 FileResult 是抽象類,不能被實例化。

API:

        [HttpGet("returnaaa")] public async Task<IActionResult> ReturnAAA() { return new ViewResult(); return new JsonResult(new { code="test"}); return new RedirectToActionResult("DefaultController","ReturnAAA",""); return new NoContentResult("666"); return new NotFoundResult(); ... } 

MVC

        public async Task<IActionResult> Test() { return View(); return Json(new { code = "test" }); return RedirectToAction("DefaultController", "ReturnAAA", ""); return NoContent("666"); return NotFound(); ... } 

MVC 中,Action 默認是 [HttpGet],不加也能夠被訪問到;

而 API 的Action,不加 [Httpxxx],則默認不能被訪問到。

相關文章
相關標籤/搜索