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
MVVM
ASP.NET Core 中的 Razor Pages 介紹:
https://docs.microsoft.com/zh-cn/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studioRazor Pages 沒有 Controller,Model 中可以包含方法
ASP.NET Core MVC 注入
services.AddControllers();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
MVC Endpoint
- 什麼是模型綁定
- 來源有哪些
- 複雜的資料綁定
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.0ModelBinder
[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.0Web 應用負責檢查 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.htmlInstall-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.htmldotnet 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 通路:
添加基于 Newtonsoft.Json 的 JSON 格式支援
添加 nuget 包:Microsoft.AspNetCore.Mvc.NewtonsoftJson
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // 浏覽器和内容協商
})
.AddNewtonsoftJson()// 添加基于 Newtonsoft.Json 的 JSON 格式支援
.AddXmlSerializerFormatters() // 添加 XML 格式支援
.AddFluentValidation();