精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從 MVC 到使用 ASP.NET Core 6.0 的最小 API

開發 后端
2007 年,隨著 ASP.NET MVC 引入了其他語言中變得司空見慣的模型-視圖-控制器模式[1],并為其提供原生支持,.NET Web 應用程序開發有了極速的發展。

[[429688]]

本文轉載自微信公眾號「DotNET技術圈」,作者Ben Foster。轉載本文請聯系DotNET技術圈公眾號。

2007 年,隨著 ASP.NET MVC 引入了其他語言中變得司空見慣的模型-視圖-控制器模式[1],并為其提供原生支持,.NET Web 應用程序開發有了極速的發展。

2012 年,也許是由于 ReSTful API 的日益流行,借鑒了 ASP.NET MVC 的許多概念又引入了 ASP.NET Web API,這是對 WCF 的重大改進,使開發人員能夠以更少的儀式構建 HTTP API,。

后來,在 ASP.NET Core 中,用于構建網站和 API 的單一框架,這些框架被統一到了 ASP.NET Core MVC 中。

在 ASP.NET Core MVC 應用程序中,控制器負責接受輸入、執行或編排操作并返回響應。它是一個功能齊全的框架,通過過濾器、內置模型綁定和驗證、約定和基于聲明的行為等提供可擴展的管道。對于許多人來說,它是構建現代 HTTP 應用程序的多合一解決方案。

在某些情況下,您可能只需要 MVC 框架的特定功能或具有使 MVC 不受歡迎的性能限制。隨著更多 HTTP 功能作為 ASP.NET Core 中間件(例如身份驗證、授權、路由等)出現,無需 MVC 即可構建輕量級 HTTP 應用程序變得更加容易,但通常需要一些功能,否則您必須自己構建,例如作為模型綁定和 HTTP 響應生成。

ASP.NET Core 6.0 旨在通過 Minimal API 彌合這一差距,以更少的儀式提供 ASP.NET MVC 的許多功能。這篇文章提供了有關如何將傳統 MVC 概念轉換為這種構建輕量級 HTTP API 和服務的新方法的分步指南。

在這些示例中,我使用的是 .NET 6.0 預覽 7,為了提供公平和最新的并排比較,我還使用了最新的webapi模板,因為 MVC 還受益于 C# 10 的一些新特性,使事情變得更加“最小化”。

引導

MVC

dotnet new webapi

新的 ASP.NET 模板取消了Startup類并利用了 C# 10 的頂級語句功能,因此我們有一個Program.cs包含所有引導代碼的文件:

  1. var builder = WebApplication.CreateBuilder(args); 
  2.  
  3. // Add services to the container. 
  4.  
  5. builder.Services.AddControllers(); 
  6.  
  7. var app = builder.Build(); 
  8.  
  9. // Configure the HTTP request pipeline. 
  10. if (builder.Environment.IsDevelopment()) 
  11.     app.UseDeveloperExceptionPage(); 
  12.  
  13. app.UseHttpsRedirection(); 
  14. app.UseAuthorization(); 
  15. app.MapControllers(); 
  16. app.Run(); 

調用builder.Services.AddControllers()負責注冊 MVC 框架依賴項并發現我們的控制器。然后我們調用app.MapControllers()注冊我們的控制器路由和 MVC 中間件。

最少的API

  1. dotnet new web 

ASP.NET Empty 模板對規范的“Hello world”示例使用 Minimal API:

  1. var builder = WebApplication.CreateBuilder(args); 
  2. var app = builder.Build(); 
  3.  
  4. if (app.Environment.IsDevelopment()) 
  5.     app.UseDeveloperExceptionPage(); 
  6.  
  7. app.MapGet("/", () => "Hello World!"); 
  8.  
  9. app.Run(); 

該MapGet方法是 Minimal API 擴展的一部分。除此之外,它與 MVC 并沒有太大區別(考慮到 HTTPS 重定向和授權中間件只是從 Empty 模板中省略而不是隱式啟用)。

定義路由和處理程序

MVC

在 MVC 中,我們有兩種[2]定義路由的方法,一種是通過約定,一種是使用屬性。

基于約定的路由更常用于網站而不是 API,并包含在mvc模板中。而不是app.MapControllers我們使用:

  1. app.MapControllerRoute( 
  2.     name"default"
  3.     pattern: "{controller=Home}/{action=Index}/{id?}"); 

所述pattern指定路線的不同區段,并且允許指定的默認值。參數可以利用 ASP.NET 的路由約束語法[3]來限制接受的值。

對于 API,建議使用基于屬性的路由[4]。

通過屬性路由,您可以使用指定 HTTP 動詞和路徑的屬性來裝飾控制器和動作:

  1. [ApiController] 
  2. [Route("[controller]")] 
  3. public class WeatherForecastController : ControllerBase 
  4.     private static readonly string[] Summaries = new[] 
  5.     { 
  6.         "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching" 
  7.     }; 
  8.  
  9.     [HttpGet] 
  10.     public IEnumerable<WeatherForecast> Get() 
  11.     { 
  12.         return Enumerable.Range(1, 5).Select(index => new WeatherForecast 
  13.         { 
  14.             Date = DateTime.Now.AddDays(index), 
  15.             TemperatureC = Random.Shared.Next(-20, 55), 
  16.             Summary = Summaries[Random.Shared.Next(Summaries.Length)] 
  17.         }) 
  18.         .ToArray(); 
  19.     } 

在啟動時,路由將自動注冊。上面的示例來自默認webapi模板,演示了路由令牌替換。該[Route("[controller]")]屬性將使用/weatherforecast所有路由的前綴(或資源)(控制器類名減去“Controller”后綴),無參數[HttpGet]屬性將在資源的根處注冊操作,因此HTTP GET /weatherforecast將命中此操作。

如果我想擴展 API 以允許按位置檢索預測,我可以添加以下操作:

  1. [HttpGet("locations/{location}")] 
  2. public IEnumerable<WeatherForecast> GetByLocation(string location) 
  3.  

請求時,/weatherforecast/locations/london該值london將綁定到相應的操作參數。

與它們的 Minimal API 對應物相比,MVC 控制器看起來非常臃腫。但是,值得注意的是,控制器也可以是 POCO(Plain Old CLR Objects)。為了獲得與上面的“Hello World”最小 API 示例相同的結果,我們只需要:

  1. public class RootController 
  2.     [HttpGet("/")] 
  3.     public string Hello() => "Hello World"

從這里你可以看到尤其是當你考慮到你仍然需要一定程度的模塊化時,即使使用最小的 API, MVC 也可以是“最小的”,。

最少的API

要使用 Minimal API 定義路由和處理程序,請使用Map(Get|Post|Put|Delete)方法。有趣的是沒有MapPatch方法,但您可以使用MapMethods.

要使用 Minimal API 實現相同的天氣預報示例:

  1. var summaries = new[]{    "Freezing""Bracing""Chilly""Cool""Mild""Warm""Balmy""Hot""Sweltering""Scorching"};app.MapGet("/weatherforecast", () =>{    return Enumerable.Range(1, 5).Select(index => new WeatherForecast    {        Date = DateTime.Now.AddDays(index),        TemperatureC = Random.Shared.Next(-20, 55),        Summary = summaries[Random.Shared.Next(summaries.Length)]    })    .ToArray();});app.Run(); 

與 MVC 示例類似,我們可以將其擴展為按位置查詢:

  1. app.MapGet("/weatherforecast/locations/{location}", (string location) =>{}); 

請注意,在 MVC 和 Minimal API 示例中,我們受益于返回類型到序列化 HTTP 200 (OK) 響應的隱式轉換。稍后我們將介紹兩個框架的更明確的 HTTP 對象模型。

模型綁定

模型綁定是從 HTTP 請求中檢索值并將它們轉換為 .NET 類型的過程。由于我們在上面介紹了綁定路由值,本節將主要關注在請求正文中或通過查詢字符串參數接收 JSON 數據。

MVC

在 MVC 中,您可以將 JSON 從請求正文綁定到 .NET 類型,方法是將其作為參數傳遞給您的操作方法并使用[FromBody]屬性對其進行修飾:

  1. [HttpPost("/payments")]public IActionResult Post([FromBody]PaymentRequest request){    } 

或者,通過使用[ApiController]屬性裝飾您的控制器,將應用一個約定來綁定主體中的任何復雜類型。

在某些情況下,您可能希望從查詢參數綁定復雜類型。我喜歡為具有多個過濾選項的搜索端點執行此操作。您可以使用以下[FromQuery]屬性實現此目的:

  1. [HttpGet("/echo")]public IActionResult Search([FromQuery]SearchRequest request){    } 

否則,簡單類型將從路由或查詢字符串值綁定:

  1. [HttpGet("/portfolios/{id}")]public IActionResult Search(int id, int? page = 1, int? pageSize = 10){    } 

/portfolios/10?page=2&pagesize=20將滿足上述操作參數的請求。

上面的示例還通過將可選參數標記為可為空并可選地提供默認值來演示可選參數的使用。

這對于復雜類型的工作方式略有不同。即使將類型設為可空,如果未發送正文,您將收到 HTTP 415(無效媒體類型)或 400(錯誤請求)響應,具體取決于是否Content-Type設置了標頭。

以前,這種行為只能通過全局進行MvcOptions.AllowEmptyInputInBodyModelBinding全局配置,但從 ASP.NET Core 5 開始,它現在可以按請求進行配置:

  1. [HttpPost("/payments")]public IActionResult Post([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)]PaymentRequest? request){    } 

最少的API

Minimal API 中的模型綁定非常相似;您使用您希望從請求中綁定的類型配置您的處理程序委托。復雜類型將從請求正文中自動綁定,而簡單類型將從路由或查詢字符串參數中綁定。使用 Minimal API 實現的相同示例如下:

  1. app.MapPost("/payments", (PaymentRequest paymentRequest) => {    });app.MapGet("/portfolios/{id}", (int id, int? page, int? pageSize) => {}); 

為了指定默認值,您需要傳遞一個方法作為委托,因為 C# 尚不支持內聯 lambda 函數的默認值:

  1. app.MapGet("/search/{id}", Search);app.Run();IResult Search(int id, int? page = 1, int? pageSize = 10){} 

該[FromQuery]屬性不支持綁定復雜類型。有可用于自定義模型綁定的擴展點,我將在后面的文章中介紹。

要支持可選的請求參數,您可以應用與[FromBody]MVC相同的屬性,指定EmptyBodyBehavior:

  1. app.MapPost("/payments", ([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)]PaymentRequest? paymentRequest]) => {}); 

HTTP 響應

MVC 和 Minimal API 都會自動將您的返回類型序列化到響應正文并返回 HTTP 200 (OK) 響應,例如:

  1. // MVC[HttpPost("/echo")]public EchoRequest Echo(EchoRequest echo) => echo;// Minimal APIapp.MapPost("/echo", (EchoRequest echo) => echo); 

您還可以返回void或Task返回一個空的 HTTP 200 (OK) 響應:

  1. // MVC[HttpPost("/echo")]public void Echo(EchoRequest echo) => {};// Minimal APIapp.MapPost("/echo", (EchoRequest echo) => {}); 

除了隱式轉換之外,MVC 和 Minimal API 都有一個豐富的 HTTP 響應對象模型,涵蓋了最常見的 HTTP 響應。

MVC

在 MVC 中,您可以返回IActionResult并使用許多內置實現,例如AcceptedResult. 如果您是從ControllerBase那里派生控制器的,那么大多數響應類型都可以使用輔助方法:

  1. [HttpDelete("/projects/{id}")]public IActionResult Delete(int id){    return Accepted();} 

最少的API

使用 Minimal API,我們可以返回IResult. 在Results靜態類可以很容易地產生了一些內置的響應類型:

  1. app.MapDelete("/projects/{id}", (int id) =>{    return Results.Accepted();}); 

依賴注入

MVC

要將依賴項注入 MVC 控制器,我們通常使用構造函數注入,其中所需的類型(或更常見的是它們的底層接口)作為構造函數參數提供:

  1. public class CacheController : ControllerBase{    private readonly ICache _cache;    public CacheController(ICache cache)    {        _cache = cache;    }    [HttpDelete("/cache/{id}")]    public async Task<IActionResult> Delete(string id)    {        await _cache.Delete(id);        return Accepted();    }} 

依賴項在啟動時注冊(現在默認在 Program.cs 中):

  1. builder.Services.AddScoped<ICache, MemoryCache>(); 

使用范圍生命周期注冊的服務將在 MVC 應用程序中按 HTTP 請求創建。

最少的API

使用 Minimal API,我們仍然可以從依賴注入中受益,但不是使用構造函數注入,而是在處理程序委托中將依賴作為參數傳遞:

  1. app.MapDelete("/cache/{id}", async (string id, ICache cache) =>{    await cache.Delete(id);    return Results.Accepted();}); 

這種方法更純粹,可以使測試更容易。不利的一面是,一旦您獲得多個依賴項,您的處理程序定義就會變得非常嘈雜。

最后,雖然依賴在 內本地聲明的依賴項可能很誘人Program.cs,但這不僅會使測試變得困難,而且還會導致范圍問題。我建議盡可能利用 DI 容器,即使是單例依賴。

語境

您的 API 可能需要訪問有關 HTTP 請求的其他信息,例如當前用戶的標頭或詳細信息。MVC 和 Minimal API 都構建在您熟悉的相同 ASP.NET Core HTTP 抽象之上。

MVC

在MVC中,獲得您的控制器時,從ControllerBase您可以訪問HttpContext,HttpRequest,HttpResponse和當前用戶(ClaimsPrincipal從基類屬性):

  1. [HttpGet]public IEnumerable<WeatherForecast> Get(){    if (Request.Headers.TryGetValue("some header"out var headerValue))    {    }    bool isSpecialUser = User.Identity.IsAuthenticated         && User.HasClaim("special"); 

如果您的控制器是一個簡單的 POCO 并且不是派生自ControllerBase您,則需要使用構造函數注入來注入IHttpContextAccessor您的控制器或直接訪問請求、響應和用戶,請為這些類型執行一些 DI 連接。如果 POCO 控制器可以利用類似于下面描述的 Minimal API 的方法注入,那就太好了。

最少的API

使用 Minimal API,您可以通過將以下類型之一[5]作為參數傳遞給處理程序委托來訪問相同的上下文信息:

  • HttpContext
  • HttpRequest
  • HttpResponse
  • ClaimsPrincipal
  • CancellationToken (請求中止)
  1. app.MapGet("/hello", (ClaimsPrincipal user) => {    return "Hello " + user.FindFirstValue("sub");}); 

鏈接生成

在某些情況下,您需要生成指向 API 其他部分的鏈接。在 ASP.NET Core 中,我們可以依靠現有的 HTTP 和路由基礎結構來避免對 URI 組件進行硬編碼。要生成到已知路線的鏈接,我們首先需要一種方法來識別它們。

MVC

在 MVC 中,我們可以將一個Name屬性傳遞給我們用來裝飾控制器操作的路由屬性,例如:

  1. [HttpGet("products/{id}"Name = "get_product")]public IActionResult GetProduct(int id){} 

然后我們可以使用IUrlHelper生成指向該路由的鏈接:

  1. [HttpPost("products"Name = "create_product")]public IActionResult CreateProduct(CreateProduct command){    var product = Create(command);    return Created(Url.Link("get_product", new { id = product.Id }));} 

請注意路由的路由參數(get_product在本例中為 ID)是如何作為匿名對象傳遞的。

IUrlHelper可通過Url酒店獲得ControllerBase。或者,您可以將它注入到您的類中,前提是您

HTTP 范圍內。

最少的API

使用 Minimal API,您可以通過附加元數據來命名端點:

  1. app.MapGet("/products/{id}", (int id) =>{    return Results.Ok();}).WithMetadata(new EndpointNameMetadata("get_product")); 

上述內容的簡寫版本WithName將在未來版本中提供。

還有一個出色的建議[6]是在傳遞方法組而不是內聯 lambda 時隱式生成端點名稱。從上面的問題:

  1. // These endpoints have their name set automaticallyapp.MapGet("/todos/{id}", GetTodoById);async Task<IResult> GetTodoById(int id, TodoDb db){    return await db.Todos.FindAsync(id)        is Todo todo            ? Results.Ok(todo)            : Results.NotFound();}; 

更新:David Fowler 確認這將在 .NET 6 rc1 中可用

命名端點后,您可以注入LinkGenerator處理程序以生成鏈接:

  1. app.MapPost("payments", async (HttpContext httpContext, IMediator mediator, LinkGenerator links, PaymentRequest payment) =>{    var result = await mediator.Send(payment);    return result.Match(        invalidRequest => invalidRequest.ToValidationProblem(),        success => Results.Created(links.GetUriByName(httpContext, "get_payment", new { id = success.Id})!, payment)    );}) 

一些內置的 Result 助手代表你處理這個樣板。同樣的例子,簡化為Results.CreatedAtRoute:

  1. app.MapPost("payments", async (HttpContext httpContext, IMediator mediator, PaymentRequest payment) =>{    var result = await mediator.Send(payment);    return result.Match(        invalidRequest => invalidRequest.ToValidationProblem(),        success => Results.CreatedAtRoute("get_payment", new { id = success.Id }, success);    );}) 

驗證

MVC

輸入驗證是任何 API 的重要組成部分。MVC 在 ASP.NET 之上添加的功能之一是模型狀態。從文檔[7]:

模型狀態表示來自兩個子系統的錯誤:模型綁定和模型驗證。源自模型綁定的錯誤通常是數據轉換錯誤。

MVC 還包括對通過屬性[8]進行驗證的內置支持,例如:

  1. public class PaymentRequest{    [Required]    public int? Amount { get; set; }        [Required]    [StringLength(3)]    public string Currency { get; set; }} 

提示:一個流行的選擇是為Fluent Validation[9]替換基于默認屬性的驗證。

綁定到此模型類型時,任何驗證錯誤都會自動添加到模型狀態。在控制器中,我們可以檢查它并采取適當的措施:

  1. public IActionResult Post(PaymentRequest paymentRequest){    if (!ModelState.IsValid)    {        // return validation error    }    // otherwise process} 

事實上,如果我們用[ApiController]約定來裝飾我們的控制器,我們甚至不需要做上面的事情。這將過濾器應用于 MVC 管道,該過濾器將驗證任何請求的輸入并在必要時返回問題詳細信息響應。

  1. {    "type""https://tools.ietf.org/html/rfc7231#section-6.5.1",    "title""One or more validation errors occurred.",    "status": 400,    "traceId""00-293242b60c05924743847956126b31fe-a1b01281b398430d-00",    "errors": {        "Amount": [            "The Amount field is required."        ],        "Currency": [            "The Currency field is required."        ]    }} 

這是 MVC 過濾器管道如何從您的應用程序中刪除重復的一個很好的例子。過濾器可以訪問您在 ASP.NET 中間件中沒有的其他上下文。這是允許內置驗證中間件自動執行的原因,因為它能夠

模型綁定發生

運行。

最少的API

就目前而言,Minimal API 沒有任何內置的驗證支持。但是,您當然可以自由地推出自己的產品。

Damian Edwards 創建了MinimalValidation[10],這是一個利用類似于默認 MVC 驗證的驗證屬性的小型庫:

  1. app.MapPost("/widgets", (Widget widget) =>    !MinimalValidation.TryValidate(widget, out var errors)        ? Results.BadRequest(errors)        : Results.Created($"/widgets/{widget.Name}", widget));app.Run();class Widget{    [Required, MinLength(3)]    public string? Name { get; set; }    public override string? ToString() => Name;} 

您可以在此處[11]找到更多示例。

我個人更喜歡使用Fluent Validation[12]通常用這個庫替換 MVC 中基于屬性的驗證。

下面是使用 Fluent Validation 和最少 API 的示例:

  1. builder.Services.AddValidatorsFromAssemblyContaining<PaymentRequest>(lifetime: ServiceLifetime.Scoped);var app = builder.Build();app.MapPost("payments", async (IValidator<PaymentRequest> validator, PaymentRequest paymentRequest) =>{    ValidationResult validationResult = validator.Validate(paymentRequest);    if (!validationResult.IsValid)    {        return Results.ValidationProblem(validationResult.ToDictionary());    }    // otherwise process});// URL generation?app.Run();public record PaymentRequest(int? Amount, string Currency){    public class Validator : AbstractValidator<PaymentRequest>    {        public Validator()        {            RuleFor(x => x.Amount).NotNull().WithMessage("amount_required");            RuleFor(x => x.Currency).Length(3).WithMessage("currency_invalid");        }    }}public static class ValidationExtensions{    public static IDictionary<string, string[]> ToDictionary(this ValidationResult validationResult)        => validationResult.Errors                .GroupBy(x => x.PropertyName)                .ToDictionary(                    g => g.Key,                    g => g.Select(x => x.ErrorMessage).ToArray()                );} 

注意:FV 驗證器不需要嵌套在它們的目標類型中。這只是個人喜好。

在這里,我利用 Fluent Validation 的程序集掃描功能來定位我的驗證器。或者,我可以IValidator顯式注冊實現。無論哪種方式,這都意味著我的驗證器可以提供給我的處理程序,我可以驗證傳入的類型。

這里的一個缺點是您可能最終會在每個處理程序中編寫相同的樣板驗證檢查。可以通過一些重構來減少它,但是沒有可以訪問綁定模型的預處理程序鉤子,我們不能像使用 MVC 過濾器那樣輕松地短路請求。我將在稍后的博客文章中介紹一些替代方法。

JSON 序列化

您可能需要自定義默認的 JSON 序列化設置以滿足您的需求或 API 樣式指南。例如,默認設置將字段名稱序列化為駝峰式大小寫(即firstName),但我們的 API 標準要求所有 API 都使用蛇形大小寫(即first_name)。

ASP.NET 6.0 使用 System.Text.Json 處理 JSON,自定義選項在此處[13]有詳細說明。

MVC

在 MVC 中,您可以通過AddJsonOptions擴展自定義 JSON :

  1. services.AddControllers()    .AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = new SnakeCaseNamingPolicy()); 

注意:開箱即用仍不支持蛇形命名法(Snake casing[14],譯者按:當今許多編程語言都建議在某些情況下使用類似蛇的命名法,對于單個字符或單詞(例如A,PYTHON,BOY),當將它們用作變量名時,大致所有小寫字母,全部大寫字母和首字母大寫字母。但是,編程語言通常需要使用多個單詞或符號來表示變量名中更豐富的含義。英語習慣于使用空格分隔單詞,但是這種用法會給編程語言帶來麻煩,因此程序員創建了其他方法,蛇形命名法就是用下劃線分隔兩個字符,使其可讀性更強)。您可以在此處[15]找到上述策略的源代碼。

最少的 API

最小的 API 依賴于許多擴展方法[16]來序列化到/從 JSON。它們允許JsonSerializerOptions提供,但否則會退回到JsonOptions從HttContext.Request.Services. 您可以在啟動時配置這些選項:

  1. builder.Services.Configure<JsonOptions>(opt =>{    opt.SerializerOptions.PropertyNamingPolicy = new SnakeCaseNamingPolicy());}); 

注意,你需要配置的Microsoft.AspNetCore.Http.Json.JsonOptions不是Mvc命名空間下的類。

我在深入研究源代碼時發現的一件事是,序列化對象ObjectResult[17]的IResult實現的基類僅支持序列化 JSON。有人告訴我這是設計使然,因為大多數開發人員很少需要支持其他媒體類型。如果您需要支持內容協商,您可能需要構建自己的IResult.

授權

我想介紹的最后一個功能是授權。身份驗證和授權都作為中間件存在,可用于任何風格的 ASP.NET Core 應用程序。

添加 MVC 或 Minimal API 中間件

之前

,您需要確保在應用程序中同時注冊授權服務和中間件:

  1. var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)    .AddJwtBearer();builder.Services.AddAuthorization();builder.Services.AddControllers(); // If MVCvar app = builder.Build();// Configure the HTTP request pipeline.if (builder.Environment.IsDevelopment()){    app.UseDeveloperExceptionPage();}app.UseAuthentication();app.UseAuthorization(); // <-- this needs to come firstapp.MapControllers(); // MVCapp.MapGet("/", () => "Hello World!"); // Minimal APIsapp.Run(); 

上面的例子是使用 JWT Bearer 認證。

MVC 和 Minimal API 之間的主要區別在于您聲明授權要求的方式。

默認安全

如果您對所有端點都有相同的授權要求,我建議您將回退策略設置為要求經過身份驗證的用戶:

  1. builder.Services.AddAuthorization(options =>{    options.FallbackPolicy = new AuthorizationPolicyBuilder()      .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)      .RequireAuthenticatedUser();}) 

如果您有其他要求或需要允許對特定端點進行匿名訪問,您可以使用以下說明注釋您的端點。

MVC

在 MVC 應用程序中,使用[Authorize]屬性裝飾您的控制器和/或操作以指定您的授權要求。此屬性允許您指定角色和策略。此示例取自Microsoft Docs[18],將AtLeast21策略應用于控制器中定義的所有操作:

  1. [Authorize(Policy = "AtLeast21")]public class AlcoholPurchaseController : Controller{    public IActionResult Index() => Ok();} 

如果您的某些 API 端點需要允許匿名訪問,您可以使用以下[AllowAnonymous]屬性裝飾這些操作:

  1. [AllowAnonymous][HttpGet("/free-for-all")]public IActionResult FreeForAll(){    return Ok();} 

最少的API

為了使用 Minimal API 實現相同的行為,我們可以將額外的元數據附加到端點,如下所示:

  1. app.MapGet("/alcohol", () => Results.Ok())    .RequireAuthorization("AtLeast21"); 

同樣,要允許匿名訪問:

  1. app.MapGet("/free-for-all", () => Results.Ok())    .AllowAnonymous(); 

后來我發現[Authorize]在使用方法組定義處理程序時可以使用與 MVC相同的屬性:

  1. [Authorize("AtLeast21")]string Alcohol(){    } 

包起來

最小 API 提供了一種使用 ASP.NET Core 構建 API 的替代方法。盡管很容易將它們視為“代碼較少的 API”,但主要的好處是您擁有一個輕量級的基礎,您可以在此基礎上挑選所需的組件,而不是像 MVC 那樣沉重的東西,后者可能包含許多出色的功能你不使用(例如過濾器)。在許多情況下,這可能會導致服務占用空間小得多,并隨后獲得性能提升。

值得一提的是,過去曾有社區努力實現同樣的目標。Nancy[19]在 Web API / OWIN 時代為我們提供了類似的東西,最近Carter[20]為 ASP.NET Core 出現,提供與 Minimal API 類似的功能。

作為 ASP.NET Core 開發人員,您現在在如何構建 API 方面有多種選擇,這只能是一件好事。

References

[1] 模型-視圖-控制器模式: https://en.wikipedia.org/wiki/Model–view–controller

[2] 兩種: https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0

[3] 路由約束語法: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-5.0#route-constraint-reference

[4] 基于屬性的路由: https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0#attribute-routing-for-rest-apis

[5] 以下類型之一: https://github.com/dotnet/aspnetcore/blob/867cec475d18892b828ac44a82d74eccfbbb0e49/src/Http/Http.Extensions/src/RequestDelegateFactory.cs#L243

[6] 出色的建議: https://github.com/dotnet/aspnetcore/issues/34540

[7] 文檔: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-5.0

[8] 屬性: https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-5.0#validation-attributes

[9] Fluent Validation: https://fluentvalidation.net/

[10] MinimalValidation: https://github.com/DamianEdwards/MinimalValidation

[11] 在此處: https://github.com/DamianEdwards/MinimalApiPlayground

[12] Fluent Validation: https://fluentvalidation.net/

[13] 此處: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-configure-options?pivots=dotnet-5-0

[14] Snake casing: https://en.wikipedia.org/wiki/Snake_case

[15] 此處: https://github.com/benfoster/problem-details-demo/blob/main/src/ProblemDetailsDemo/Startup.cs

[16] 擴展方法: https://github.com/dotnet/aspnetcore/tree/main/src/Http/Http.Extensions/src

[17] ObjectResult: https://github.com/dotnet/aspnetcore/blob/main/src/Http/Http.Results/src/ObjectResult.cs

[18] Microsoft Docs: https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-5.0

[19] Nancy: https://nancyfx.org/

[20] Carter: https://github.com/CarterCommunity/Carter

 

責任編輯:武曉燕 來源: DotNET技術圈
相關推薦

2009-07-23 15:44:39

ASP.NET MVC

2021-03-12 00:04:52

網關Api

2021-06-22 16:59:56

微軟.NETC# 軟件開發

2009-07-31 12:43:59

ASP.NET MVC

2009-07-24 13:20:44

MVC框架ASP.NET

2017-03-06 11:13:57

ASP.NETCoreMVC

2009-10-29 09:15:32

ASP.NET MVCDropDownLis

2009-07-22 09:36:54

使用UpdataModASP.NET MVC

2009-07-22 16:34:36

使用T4ASP.NET MVC

2009-08-25 14:47:26

傳統ASP到ASP.N

2012-02-03 09:06:53

ASP.NET MVC

2009-07-22 09:11:02

Action方法ASP.NET MVC

2009-07-20 15:44:32

ASP.NET MVC

2023-07-03 08:48:40

Web模塊化設計

2009-07-22 10:34:37

ActionInvokASP.NET MVC

2009-07-23 14:31:20

ASP.NET MVC

2009-07-22 13:24:24

ASP.NET MVC

2009-07-20 10:53:59

ASP.NET MVC

2009-07-22 10:09:59

ASP.NET MVC

2009-03-06 10:28:30

MVCASP.NET異步Action
點贊
收藏

51CTO技術棧公眾號

中文字幕乱码一区二区三区| 欧美成人亚洲成人| 女人另类性混交zo| av大全在线免费看| 国产一区二区三区黄视频 | 免费成人av| 91福利资源站| 三级在线免费观看| 精品视频三区| 国产v日产∨综合v精品视频| 国产91色在线|免| 欧美成人国产精品高潮| 国产乱码精品一区二区亚洲 | 亚洲精品久久在线| 久久婷五月综合| av成人 com a| 国产精品久久久久久久久搜平片| 国产精品电影一区| 久久久久久久九九九九| 成人羞羞网站入口| 51精品国自产在线| 免费久久久久久| 欧美视频综合| 麻豆成人av在线| 91成人性视频| 毛片aaaaa| 欧美第一精品| 夜夜嗨av色一区二区不卡| xxxxwww一片| 电影91久久久| 欧美性受xxxx| 大肉大捧一进一出好爽视频| 污视频网站在线免费| 成人综合婷婷国产精品久久| 国产精品欧美亚洲777777| 久久精品在线观看视频| 国产aⅴ精品一区二区三区久久| 欧美日本免费一区二区三区| 日韩精品一区二区三区不卡 | 色久欧美在线视频观看| 中国黄色a级片| 黄色日韩网站| 欧亚一区二区三区| 成人小视频在线看| 涩涩视频在线| 精品久久久久久久久久国产 | 日本精品久久久久影院| 国产午夜福利精品| 亚洲国产日本| 97av在线视频免费播放| 在线看成人av| 99伊人成综合| 97成人精品区在线播放| jizzjizzjizz国产| 卡通动漫精品一区二区三区| 精品成人私密视频| 喷水视频在线观看| 日韩精品导航| 日韩欧美国产精品| 日批视频免费看| 国产成人精品福利| 日韩av中文字幕在线播放| 奇米777第四色| 人人网欧美视频| 国产婷婷色综合av蜜臀av | 久久无码精品丰满人妻| 视频国产一区| 中文字幕日韩在线播放| 貂蝉被到爽流白浆在线观看| 日韩免费久久| 久久成人在线视频| 精品一级少妇久久久久久久| 亚洲精品婷婷| 日本不卡视频在线播放| 中国精品一区二区| 国产美女久久久久| 国产一区免费观看| 成人综合影院| 亚洲三级电影网站| 僵尸世界大战2 在线播放| 欧美精品电影| 亚洲乱码国产乱码精品精98午夜| 亚洲一二三区精品| av黄在线观看| 日韩欧美国产激情| 精品少妇一区二区三区在线| 欧美大片免费观看网址| 欧美日韩在线三区| 精品久久久久久无码人妻| 天海翼精品一区二区三区| 日韩精品一区二区三区中文不卡| 99日在线视频| 国产精品香蕉| 亚洲欧美国内爽妇网| 国产精品69久久久久孕妇欧美| 免费成人网www| 久久久久www| 四虎成人永久免费视频| 国产在线播放一区二区三区| 韩国精品一区二区三区六区色诱| 亚洲xxx在线| 久久久久久久网| 国产高清不卡无码视频| 日本三级在线观看网站| 亚洲一二三区不卡| 91最新在线观看| 97青娱国产盛宴精品视频| 精品毛片乱码1区2区3区| 91精产国品一二三| 日韩88av| 97超级碰在线看视频免费在线看| 久久久久久久久久久久久av| 久久国产精品99久久人人澡| 91久久久久久国产精品| 青青草免费在线| 中文字幕av一区 二区| 亚洲欧美日本国产有色| 国产拍在线视频| 欧美色图第一页| 瑟瑟视频在线观看| 亚洲伦伦在线| 国产成人小视频在线观看| 中文字幕精品在线观看| 99re热视频精品| 日韩欧美精品一区二区| jizzjizz中国精品麻豆| 欧美精品18+| 日本人亚洲人jjzzjjz| 99久久激情| 国产精品第10页| 深夜福利在线观看直播| 亚洲国产成人高清精品| 国产成人久久婷婷精品流白浆| 国产91欧美| 亚洲欧美中文日韩在线v日本| 后入内射无码人妻一区| 久久午夜av| 久久99欧美| 理论不卡电影大全神| 欧美三级电影在线看| av小说在线观看| 久久国产主播| 欧美日韩国产一二| 成人福利av| 亚洲精品自在久久| youjizz在线视频| 久久亚洲私人国产精品va媚药| 中文字幕一区二区三区最新| 成人全视频在线观看在线播放高清 | 国产日本欧美在线| 国产精品电影| 亚洲精品电影在线| 欧美日韩一二三四区| 26uuu亚洲综合色| 国产无套内射久久久国产| 在线观看欧美理论a影院| 日av在线播放中文不卡| 国产夫妻在线观看| 夜夜揉揉日日人人青青一国产精品| 久久久久久久久久久免费视频| 欧美h版在线观看| 欧美尺度大的性做爰视频| 精品人妻一区二区三区三区四区| 久久综合久久综合亚洲| 粗暴91大变态调教| 91亚洲国产高清| 1卡2卡3卡精品视频| a级大胆欧美人体大胆666| 日韩精品丝袜在线| 无码人妻精品一区二区| 亚洲国产高清在线观看视频| 男人的天堂最新网址| 欧美午夜不卡| 乱一区二区三区在线播放| jizz久久久久久| 欧美成人午夜激情| 亚洲欧美日韩精品永久在线| 欧美日韩一区二区免费在线观看 | 久久综合网色—综合色88| 国产精品69页| 66视频精品| 精品不卡在线| 久久亚洲资源中文字| 欧美激情综合亚洲一二区| 黄上黄在线观看| 欧美一级片在线看| 日韩一区二区视频在线| 国产乱码精品一区二区三区av| 致1999电视剧免费观看策驰影院| 激情亚洲影院在线观看| 久久国产加勒比精品无码| 天天综合永久入口| 午夜精品福利一区二区三区av| 亚洲成人av免费观看| 西西人体一区二区| 神马午夜伦理影院| 亚洲国产精品嫩草影院久久av| 国内精品久久久| av资源在线观看免费高清| 欧美变态凌虐bdsm| 亚洲一二区视频| 懂色av影视一区二区三区| 艳妇荡乳欲伦69影片| 26uuu亚洲综合色| 亚洲欧美激情网| 在线免费高清一区二区三区| 亚洲成色www久久网站| 国产精品对白| 91人成网站www| 亚洲成人一区在线观看| 91sao在线观看国产| 羞羞电影在线观看www| 伊人亚洲福利一区二区三区| 中文字幕第2页| 精品久久久久久久久久久久久久| 我和岳m愉情xxxⅹ视频| 日韩成人免费电影| 国产原创popny丨九色| 一区二区影视| 亚洲制服中文| 狠狠操综合网| 麻豆av一区二区三区| 永久免费精品视频| 热99精品只有里视频精品| 青草青在线视频| 久久久国产视频91| 欧美极品另类| 日韩中文字幕亚洲| 黄色av免费观看| 日韩午夜av电影| 国产免费久久久| 欧美美女黄视频| 亚洲午夜精品久久久| 欧美少妇bbb| 超碰在线免费97| 一区二区三区色| 永久免费成人代码| 久久综合色8888| wwwwww日本| 久久久综合精品| www.久久com| 国产一区二区三区四区五区入口| 一二三四视频社区在线| 国产一区日韩一区| 福利在线小视频| 午夜激情一区| www.日本在线播放| 亚洲国产日韩欧美一区二区三区| 水蜜桃一区二区三区| 精品国产一区二区三区久久久樱花 | 国产精品igao激情视频| 99久久99久久精品国产片桃花| 精品国产综合| 青青一区二区| 欧美一级爽aaaaa大片| 黄色不卡一区| 亚洲三区视频| 外国成人激情视频| 白白操在线视频| 亚洲视频二区| 色婷婷综合久久久久中文字幕| 伊人成人在线| 国产网站免费在线观看| 午夜视频精品| 你真棒插曲来救救我在线观看| 欧美岛国激情| 50度灰在线观看| 国产精品久久777777毛茸茸| 国产女大学生av| 久久婷婷亚洲| 97人人模人人爽人人澡| 不卡的av中国片| 久久成人激情视频| 91麻豆国产香蕉久久精品| 91成年人网站| 中文字幕一区av| jizz18女人高潮| 亚洲免费高清视频在线| 日本少妇全体裸体洗澡| 在线免费观看一区| av网站在线免费看| 日韩精品在线免费观看| 午夜伦全在线观看| 亚洲91av视频| 国产精品久久久久久久久免费高清 | 一区二区三区短视频| 国产精品直播网红| www.神马久久| 丝袜美腿玉足3d专区一区| 欧美黄色aaaa| 亚洲精品一二三四五区| 久久激情视频| 免费观看黄网站| 久久久综合精品| 国产小视频在线看| 欧美三级电影精品| 天堂在线视频免费观看| 色yeye香蕉凹凸一区二区av| 极品视频在线| 亚洲精品日产aⅴ| 精品国产一区二区三区久久久樱花| 奇米影视首页 狠狠色丁香婷婷久久综合| 日韩精品免费一区二区夜夜嗨| 欧美精品二区三区四区免费看视频 | 91麻豆精品91久久久久同性| 四虎成人免费在线| 欧美成人自拍视频| 国产精品美女午夜爽爽| 成人淫片在线看| 激情不卡一区二区三区视频在线| 91亚洲人电影| 精品久久影视| 浮妇高潮喷白浆视频| 国产成人在线观看免费网站| 97伦伦午夜电影理伦片| 亚洲18色成人| www夜片内射视频日韩精品成人| 精品久久免费看| 国产在线更新| 成人观看高清在线观看免费| 国产成人三级| 国产精品第12页| 国精产品一区一区三区mba视频| 欧美熟妇精品一区二区| 91免费看视频| 日本三级免费看| 欧美变态凌虐bdsm| 婷婷av在线| 97久久人人超碰caoprom欧美| 欧美1区2区3区4区| 欧美精品久久久久久久久久久| 日韩一区欧美二区| 变态另类丨国产精品| 精品福利视频导航| 色欲av永久无码精品无码蜜桃 | 色噜噜日韩精品欧美一区二区| 中文一区在线播放| 日韩av免费播放| 国产亚洲一级高清| 美足av综合网| 99久久99久久| 狠色狠色综合久久| 能看的毛片网站| 成人性生交大合| 国产在线视频二区| 亚洲第一免费网站| 理论不卡电影大全神| 91精品视频专区| 亚洲精品一区二区在线看| 中文字幕一区二区在线观看视频| 91丨porny丨在线| 久久久久久久久久久影院| 亚洲美女视频网| 台湾成人免费视频| 亚洲最大色综合成人av| 韩日av一区二区| 亚洲v国产v欧美v久久久久久| 亚洲综合精品自拍| 日韩中文字幕综合| 日本韩国在线不卡| 日韩欧美中文| 超碰人人cao| 无码av免费一区二区三区试看| 一级做a爱片性色毛片| 久久视频在线免费观看| 亚洲网一区二区三区| 欧美极品欧美精品欧美| 国产亲近乱来精品视频| 国产精品无码在线播放| 欧美黑人国产人伦爽爽爽| 香蕉久久一区| 欧美一区二区视频在线播放| av成人老司机| 国产精品无码一区| 欧美大秀在线观看| 蜜桃一区二区| 91精品999| 无码av免费一区二区三区试看| 性网爆门事件集合av| 57pao国产成人免费| 日韩av有码| 国产69视频在线观看| 亚洲尤物视频在线| 内衣办公室在线| 亚洲xxxx3d| 亚洲综合三区| 国产成人久久久久| 亚洲精品自拍第一页| 国产一区二区三区免费观看在线 | 欧美日韩一区二区在线观看| 亚洲婷婷噜噜| 日韩精品不卡| 国产a精品视频| 中国a一片一级一片| 中文字幕av一区二区| 欧美激情啪啪| 亚洲乱码中文字幕久久孕妇黑人| 91视频免费看| 国产美女明星三级做爰| 国产91|九色|