天天看點

.NET 雲原生架構師訓練營(子產品二 基礎鞏固 MVC終結點)--學習筆記2.3.4 Web API -- MVC終結點

2.3.4 Web API -- MVC終結點

  • MVC與MVVM
  • 模型綁定
  • 自定義模型綁定器
  • 模型驗證
  • 傳回資料處理

MVC

ASP.NET Core MVC 概述:

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/overview?view=aspnetcore-5.0
.NET 雲原生架構師訓練營(子產品二 基礎鞏固 MVC終結點)--學習筆記2.3.4 Web API -- MVC終結點

MVVM

ASP.NET Core 中的 Razor Pages 介紹:

https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studio

Razor Pages 沒有 Controller,Model 中可以包含方法

.NET 雲原生架構師訓練營(子產品二 基礎鞏固 MVC終結點)--學習筆記2.3.4 Web API -- MVC終結點

ASP.NET Core MVC 注入

services.AddControllers();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});           

MVC Endpoint

.NET 雲原生架構師訓練營(子產品二 基礎鞏固 MVC終結點)--學習筆記2.3.4 Web API -- MVC終結點

  • 什麼是模型綁定
  • 來源有哪些
  • 複雜的資料綁定

ASP.NET Core 中的模型綁定:

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

控制器和 Razor 頁面處理來自 HTTP 請求的資料。 例如,路由資料可以提供一個記錄鍵,而釋出的表單域可以為模型的屬性提供一個值。 編寫代碼以檢索這些值,并将其從字元串轉換為 .NET 類型不僅繁瑣,而且還容易出錯。

模型綁定會自動化該過程。 模型綁定系統:

  • 從各種源(如路由資料、表單域和查詢字元串)中檢索資料。
  • Razor在方法參數和公共屬性中向控制器和頁面提供資料。
  • 将字元串資料轉換為 .NET 類型。
  • 更新複雜類型的屬性。

  • [FromQuery] -從查詢字元串擷取值。
  • [FromRoute] -從路由資料中擷取值。
  • [FromForm] -從已釋出的表單字段中擷取值。
  • [FromBody] -從請求正文中擷取值。
  • [FromHeader] -從 HTTP 标頭中擷取值。

從路由資料中擷取值

[HttpGet]
[Route("option/{id}")]
public IActionResult GetOption([FromRoute] int id)
{
    return Ok(new {id});
}           

從查詢字元串擷取值

[HttpGet]
[Route("option/{id}")]
public IActionResult GetOption([FromRoute] int id, [FromQuery] string name)
{
    return Ok(new {id, name});
}           

從 HTTP 标頭中擷取值

[HttpGet]
[Route("option/{id}")]
public IActionResult GetOption([FromRoute] int id, [FromQuery] string name,[FromHeader] string termId)
{
    return Ok(new {id, name, termId});
}           

從已釋出的表單字段中擷取值

[HttpPost]
[Route("option/from")]
public IActionResult CreateOption([FromForm] string name, [FromForm] string id)
{
    return Ok(new {name, id});
}           

從請求正文中擷取值

[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] string name)
{
    return Ok(name);
}           

  • 對象
  • 集合
  • 字典
public class Student
{
    public int Id { get; set; }

    public string Name { get; set; }
}

[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] Student student)
{
    return Ok(student);
}           
[HttpGet]
[Route("option")]
public IActionResult GetOption([FromQuery] Dictionary<int, string> dic)
{
    var students = new List<Student>();

    foreach (var item in dic)
    {
        students.Add(new Student {Id = item.Key, Name = item.Value});
    }

    return Ok(students);
}           

啟動程式,通路:

https://localhost:5001/config/option?dic[1001]=ming

$dic[1002]=rank&dic[1003]=abc

輸出:

[{"id":1001,"name":"ming$dic[1002]=rank"},{"id":1003,"name":"abc"}]           

ASP.NET Core 中的自定義模型綁定:

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/advanced/custom-model-binding?view=aspnetcore-5.0

ModelBinder

[ModelBinder(BinderType = typeof(AuthorEntityBinder))]
public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string GitHub { get; set; }
    public string Twitter { get; set; }
    public string BlogUrl { get; set; }
}

public class AuthorEntityBinder : IModelBinder           

ModelBinderProvider

public class AuthorEntityBinderProvider : IModelBinderProvider

services.AddControllers(options =>
{
    options.ModelBinderProviders.Insert(0, new AuthorEntityBinderProvider());
});           

  • 什麼是模型驗證
  • 模型驗證的特性與消息
  • FluentValidation

ASP.NET Core MVC 和頁面中的模型驗證 Razor:

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation?view=aspnetcore-5.0

Web 應用負責檢查 ModelState.IsValid 并做出相應響應

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

  • [CreditCard]:驗證屬性是否具有信用卡格式。
  • [Compare]:驗證模型中的兩個屬性是否比對。
  • [EmailAddress]:驗證屬性是否具有電子郵件格式。
  • [Phone]:驗證屬性是否具有電話号碼格式。
  • [Range]:驗證屬性值是否在指定的範圍内。
  • [RegularExpression]:驗證屬性值是否與指定的正規表達式比對。
  • [Required]:驗證字段是否不為 null。
  • [StringLength]:驗證字元串屬性值是否不超過指定長度限制。
  • [Url]:驗證屬性是否具有 URL 格式。
  • [Remote]:通過在伺服器上調用操作方法來驗證用戶端上的輸入。

[Required] [Range]

public class Student
{
    [Required]
    [Range(1,10,ErrorMessage = "id 為 1-10 之間的數字")]
    public int Id { get; set; }

    public string Name { get; set; }
}           

ModelState

[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] Student student)
{
    if (!ModelState.IsValid)
    {
        return ValidationProblem();
    }

    return Ok(student);
}           

不同場景下同一個模型有不同的驗證規則,最好将模型與驗證分開

表達式寫法:

public class CustomerValidator : AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(x => x.Surname).NotEmpty();
    RuleFor(x => x.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(x => x.Discount).NotEqual(0).When(x => x.HasDiscount);
    RuleFor(x => x.Address).Length(20, 250);
    RuleFor(x => x.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}           

Installation:

https://docs.fluentvalidation.net/en/latest/installation.html
Install-Package FluentValidation           

StudentValidator

namespace HelloApi.Validations
{
    public class StudentValidator : AbstractValidator<Student>
    {
        public StudentValidator()
        {
            RuleFor(s => s.Id).InclusiveBetween(1,10).WithMessage("id需要在1和10之間");
        }
    }
}           

ASP.NET Core Getting Started:

https://docs.fluentvalidation.net/en/latest/aspnet.html
dotnet add package FluentValidation.AspNetCore           

ConfigureServices

單個添加

services.AddControllers()
    .AddFluentValidation();

// 通過依賴注入的方式(單個添加)
services.AddTransient<IValidator<Student>, StudentValidator>();           

全部添加

// 通過掃描程式集的方式(全部添加)
services.AddControllers()
    .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<StudentValidator>());           

  • 傳回資料類型
  • 格式化響應資料

ASP.NET Core Web API 中控制器操作的傳回類型:

https://docs.microsoft.com/zh-cn/aspnet/core/web-api/action-return-types?view=aspnetcore-5.0
  • 特定類型
  • IActionResult
  • ActionResult

特定類型:最簡單的操作傳回基元或複雜資料類型(如 string 或自定義對象類型)

IActionResult:常見傳回類型為 BadRequestResult (400)、NotFoundResult (404) 和 OkObjectResult (200)

[HttpPost]
[Route("option/body")]
public IActionResult CreateOption([FromBody] Student student)
{
    if (!ModelState.IsValid)
    {
        return ValidationProblem();
    }

    //return BadRequest();

    //return NotFound();

    return Ok(student);
}           

設定 ASP.NET Core Web API 中響應資料的格式:

https://docs.microsoft.com/zh-cn/aspnet/core/web-api/advanced/formatting?view=aspnetcore-5.0

浏覽器和内容協商

services.AddControllers(options =>
{
    options.RespectBrowserAcceptHeader = true;// 浏覽器和内容協商
});           

添加 XML 格式支援

services.AddControllers(options =>
{
    options.RespectBrowserAcceptHeader = true; // 浏覽器和内容協商
})
.AddXmlSerializerFormatters() // 添加 XML 格式支援
.AddFluentValidation();           

啟動程式,添加 XML Headers 通路:

.NET 雲原生架構師訓練營(子產品二 基礎鞏固 MVC終結點)--學習筆記2.3.4 Web API -- MVC終結點

添加基于 Newtonsoft.Json 的 JSON 格式支援

添加 nuget 包:Microsoft.AspNetCore.Mvc.NewtonsoftJson

services.AddControllers(options =>
{
    options.RespectBrowserAcceptHeader = true; // 浏覽器和内容協商
})
.AddNewtonsoftJson()// 添加基于 Newtonsoft.Json 的 JSON 格式支援
.AddXmlSerializerFormatters() // 添加 XML 格式支援
.AddFluentValidation();           

GitHub源碼連結:

https://github.com/MINGSON666/Personal-Learning-Library/tree/main/ArchitectTrainingCamp/HelloApi