1. 程式人生 > 實用技巧 >淺談 asp.net core web api

淺談 asp.net core web api

希望通過本文能夠了解如下內容:

  1. ControllerBase
  2. Attributes
  3. Action的返回值型別

ControllerBase

當我們開始實際上專案, 真正實操 anc 時, 肯定會用到 web api 框架和 mvc 框架. 這兩個框架自動建立的 controller 繼承了不同的父類, web api 建立的 controller 自動繼承 controllerBase, mvc 建立的 controller 自動繼承 controller, 兩個區別是是否支援 views.

官網說了, 如果你的專案準備使用 web api的話, 不要建立一個繼承自 controller 的 controller, 因為 controller 是帶有一些 view 支援的. 並且 controller 本身也是繼承自 controllerbase, 既然你是 web api 的controller, 去 handle web api request, 那麼自然是不需要支援 views的, 所以直接使用 controllerbase. 但是有一種情況是例外的, 當你的controller同時想支援 web api 和 views 的時候, 那就繼承 controller.

在抽象類 ControllerBase 中, 可以看到絕大多數定義的方法都是 xxxResult 方法. 我們細數一下ControllerBase為我們提供的Result都有哪些:

Result namedes
Accepted Result 建立一個status code 為202 accepted 的result作為response返回.
AcceptedAtAction Result 建立一個status code 為202 accepted 的result作為response返回.
AcceptedAtRoute Result 建立一個status code 為202 accepted 的result作為response返回.
BadRequestObject Result Status400BadRequest
Challenge Result 返回身份認證失敗的401 unauthorized 和 許可權校驗失敗的 403 forbidden result
ConflictObject Result Status409Conflict
Conflict Result Status409Conflict
Content Result 返回指定的content string作為result
Created Result Status201Created
CreatedAtAction Result Status201Created
CreatedAtRoute Result Status201Created
VirtualFile Result Returns the file specified by virtualPath (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)
FileStream Result Returns a file in the specified fileStream (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)
FileContent Result Returns a file with the specified fileContents as content (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)
ForbidResult 許可權校驗失敗的 403 forbidden result
LocalRedirect Result Creates a Microsoft.AspNetCore.Mvc.LocalRedirectResult object that redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified local localUrl.
NoContent Result Status204NoContent
NotFoundObject Result Status404NotFound
Ok Result Status200OK
PhysicalFile Result Returns the file specified by physicalPath (Microsoft.AspNetCore.Http.StatusCodes.Status200OK)
Object Result 比較靈活, 需要後端api 開發人員手動指定 status code和問題展示細節等.
Redirect Result Creates a Microsoft.AspNetCore.Mvc.RedirectResult object that redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified url.
RedirectToAction Result Redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to an action with the same name as current one. The 'controller' and 'action' names are retrieved from the ambient values of the current request.
RedirectToPage Result Redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified pageName.
RedirectToRouteResult Redirects (Microsoft.AspNetCore.Http.StatusCodes.Status302Found) to the specified route using the specified routeName, routeValues, and fragment.
SignIn Result 使用指定的身份認證資訊建立的登入result
SignOut Result 使用指定的身份認證資訊登出系統的result
Object Result 返回指定的code和value作為result
StatusCode Result 返回指定的code作為result
UnauthorizedObject Result Status401Unauthorized
Unauthorized Result Status401Unauthorized
UnprocessableEntityObject Result Status422UnprocessableEntity

基本上很全了. 當我們實際使用時具體需要返回啥樣的result, 可以隨時去找一個對應合適的result放到response中返回去.

Attributes

除此外, 框架提供了很多 Attribute 用於定義 web api 中 controller 和 action 的行為.

[ApiController]

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

自動生成的 controller 檔案頭上面還有個標籤叫做 [ApiControllerAttribute], 它是用於啟動一些專門為了 api 設定的配置.

ApiController 可以定義的位置

  • 如果你的專案中有很多自定義的controller, 但是又不想一個一個都給打上標籤, 可以宣告一個父類controller, 在這個父類的controller上面打上[ApiController]標籤, 並且在父類中定義一些common的method, 自定義的controller可以繼承自該父類controller.

  • 除了在controller的上面定義, 還可以在 startup 中定義. 這樣做有個問題就是所有的controller都相當於定義了該標籤, 無法例外:

    [assembly: ApiController]
    namespace WebApiSample
    {
        public class Startup
        {
            ...
        }
    }
    

相當於路由的方式必須是標籤路由方式

當 controller 上頭被定義了該標籤後, 表示路由的方式必須是通過標籤定義

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

此時通過URL那種轉義方式的路由就無法work了. 即我們在 startup.cs檔案的configure方法裡面通過 seEndpoints, UseMvc, or UseMvcWithDefaultRoute 這些方法定義的預設URL的轉義會失效.

自動觸發 http 400 code 的response

當 model validation 失敗後, 會自動觸發 http 400 code 的response, 所以下面的程式碼在一個 API 的 action 中是多餘的:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

如何禁用這一預設行為? 可以在 startup.cs中按照如下進行配置:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
            options.SuppressConsumesConstraintForFormFileParameters = true;
            options.SuppressInferBindingSourcesForParameters = true;
            options.SuppressModelStateInvalidFilter = true;
            options.SuppressMapClientErrors = true;
            options.ClientErrorMapping[404].Link =
                "https://httpstatuses.com/404";
    });

使用[FromBody]引數標籤對引數的資料來源進行繫結 - model binding

可以在 action 的引數中使用一些引數標籤來確定引數的來源.這種操作被稱為 model binding, 可以作為 model binding 的引數標籤如下:

AttributeBinding source
[FromBody] 從http Request body中獲取引數值. 不要在一個action中使用多餘一個FromBody標籤, 不支援這種操作.
[FromForm] 從httprequest body的form欄位中獲取引數值.
[FromHeader] 從 http headers 中獲取引數值.
[FromQuery] 從query string中獲取引數引數值. 但是支援持簡單型別的資料獲取
[FromRoute] 從當前request的RouteData中獲取引數資料引數值. 只支援簡單型別的引數(注意當你的values中有可能包含%2f時, 不要使用這個標籤, 而是使用 [FromQuery], 因為在 [FromRoute] 中%2f不會按照理想的方式轉義為/. )
[FromServices] 這種情況是在你的action中使用了其他類的一個例項, 一般來說都是通過依賴注入的方式獲取類的例項, 建構函式中注入的話, 可能沒有必要. 因為只有這一個方法使用. 所以在引數中新增[FromServices]來獲取.

Action的返回值型別