文章目录
- 项目地址
- 一、WebAPI基础
- 1. 项目初始化
- 1.1 创建简单的API
- 1.1.1 get请求
- 1.1.2 post请求
- 1.1.3 put请求
- 1.1.4 Delete请求
- 1.2 webapi的流程
- 2.Controllers
- 2.1 创建一个shirts的Controller
- 3. Routing
- 3.1 使用和创建MapControllers
- 3.2 使用Routing的模板语言
- 4. Mould Binding
- 4.1 指定数据的来源
- 4.1.1 给Request请求添加
- 1. FromRoute
- 2. FromQuery
- 3. FromHeader
- 4.1.2 给Post请求添加
- 1. FromBody
- 2. FromForm
- 5. Mould Validation
- 5.1 添加Model Validation
- 5.2 添加自定义的Validation
- 6. WebApi Return Types
- 6.1 直接返回对象
- 6.2 返回多类型
- 7. Action filter
- 7.1 创建filter
项目地址
- 教程作者:
- 教程地址:
- 代码仓库地址:
- 所用到的框架和插件:
webapi
一、WebAPI基础
1. 项目初始化
- 创建一个一个项目文件夹,并且在控制台输入
dotnew webapi -n Restaurants.API --noopenapi -controllers
- 但是此时的项目是没有sln文件的,创建sln文件,但是这时候打开vs显示的是空项目
dotnet new sln
- 将项目添加到vs里
dotnet sln add ./Restaurants.API
1.1 创建简单的API
- 在program.cs里使用routing中间件配置路由
1.1.1 get请求
- 获取所有的shirts
app.MapGet("/shirts", () =>
{
return "Reading all the shirts";
});
- 根据ID获取一个
//2.get shirt by id
app.MapGet("/shirts/{id}", (int id) =>
{
return $"Reading shirt with ID: {id}";
});
1.1.2 post请求
app.MapPost("/shirts", () =>
{
return "Creating a new shirt.";
});
1.1.3 put请求
更新
app.MapPut("/shirts/{id}", (int id) =>
{
return $"Updating shirt with ID: {id}";
});
1.1.4 Delete请求
删除
app.MapDelete("/shirts/{id}", (int id) =>
{
return $"Deleting shirt with ID: {id}";
});
1.2 webapi的流程
2.Controllers
2.1 创建一个shirts的Controller
- 创建
Controllers文件夹
,在该文件夹下创建ShirtsController.cs
文件
using Microsoft.AspNetCore.Mvc;
namespace WebAPIDemo.Controllers
{
[ApiController]
public class ShirtsController : ControllerBase
{
public string GetShirts()
{
return "Reading all the shirts";
}
public string GetShirtById(int id)
{
return $"Reading shirt with ID: {id}";
}
public string CreateShirt()
{
return "Creating a new shirt.";
}
public string UpdateShirt() {
return "Updating shirt with ID: {id}";
}
public string DeleteShirt(int id)
{
return $"Deleting shirt with ID: {id}";
}
}
}
3. Routing
3.1 使用和创建MapControllers
- 在
Program.cs
里添加rout的中间件
- 在Controller里,直接使用特性标记routing
using Microsoft.AspNetCore.Mvc;
namespace WebAPIDemo.Controllers
{
[ApiController]
public class ShirtsController : ControllerBase
{
[HttpGet("/shirts")]
public string GetShirts()
{
return "Reading all the shirts";
}
[HttpGet("/shirts/{id}")]
public string GetShirtById(int id)
{
return $"Reading shirt with ID: {id}";
}
[HttpPost("/shirts")]
public string CreateShirt()
{
return "Creating a new shirt.";
}
[HttpPut("/shirts/{id}")]
public string UpdateShirt() {
return "Updating shirt with ID: {id}";
}
[HttpDelete("/shirts/{id}")]
public string DeleteShirt(int id)
{
return $"Deleting shirt with ID: {id}";
}
}
}
3.2 使用Routing的模板语言
- 在上面我们给每个Controller都使用一个路由,这样代码冗余,我们可以使用模板来指定rout;
- 这样我们可以直接用过
https://localhost:7232/shirts
进行访问shirts
就是控制器的名称
- 如果我们想通过
https://localhost:7232/api/shirts
进行访问的话,修改模板routing
4. Mould Binding
将Http request和 Controller里的 parameter绑定起来
4.1 指定数据的来源
4.1.1 给Request请求添加
1. FromRoute
- 指定这个参数必须是从
https://localhost:7232/api/shirts/2/red
从路由里来,如果不是,则报错
[HttpGet("{id}/{color}")]
public string GetShirtById(int id,[FromRoute]string color)
{
return $"Reading shirt with ID: {id},color is {color}";
}
2. FromQuery
- 必须通过
QueryString
的形式提供:https://localhost:7232/api/shirts/2?color=red
[HttpGet("{id}/{color}")]
public string GetShirtById(int id,[FromQuery]string color)
{
return $"Reading shirt with ID: {id},color is {color}";
}
3. FromHeader
- 必须通过请求头来传递,且Key是Name
[HttpGet("{id}/{color}")]
public string GetShirtById(int id,[FromHeader(Name="color")]string color)
{
return $"Reading shirt with ID: {id},color is {color}";
}
4.1.2 给Post请求添加
- 在webapp里创建一个新的文件夹
Models
,并且添加一个Shirts,cs
类
namespace WebAPIDemo.Models
{
public class Shirt
{
public int ShirtId { get; set; }
public string? Brand { get; set; }
public string? Color { get; set; }
public int Size { get; set; }
public string? Gender { get; set; }
public double Price { get; set; }
}
}
1. FromBody
- 从请求体里来
[HttpPost]
public string CreateShirt([FromBody]Shirt shirt)
{
return "Creating a new shirt.";
}
2. FromForm
- 通过表格形式传递
[HttpPost]
public string CreateShirt([FromForm]Shirt shirt)
{
return "Creating a new shirt.";
}
5. Mould Validation
5.1 添加Model Validation
- 在
Models/Shirts.cs
类里添加验证,如果没有给出必须的参数,请求会报错400
using System.ComponentModel.DataAnnotations;
namespace WebAPIDemo.Models
{
public class Shirt
{
[Required]
public int ShirtId { get; set; }
[Required]
public string? Brand { get; set; }
public string? Color { get; set; }
public int Size { get; set; }
[Required]
public string? Gender { get; set; }
public double Price { get; set; }
}
}
5.2 添加自定义的Validation
- 在
Models文件夹
里,添加Validations文件夹
,并且添加文件Shirt_EnsureCorrectSizingAttribute.cs
using System.ComponentModel.DataAnnotations;
using WebAPIDemo.Models;
namespace WebApp.Models.Validations
{
public class Shirt_EnsureCorrectSizingAttribute : ValidationAttribute
{
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
var shirt = validationContext.ObjectInstance as Shirt;
if (shirt != null && !string.IsNullOrWhiteSpace(shirt.Gender))
{
if (shirt.Gender.Equals("men", StringComparison.OrdinalIgnoreCase) && shirt.Size < 8)
{
return new ValidationResult("For men's shirts, the size has to be greater or equal to 8.");
}
else if (shirt.Gender.Equals("women", StringComparison.OrdinalIgnoreCase) && shirt.Size < 6)
{
return new ValidationResult("For women's shirts, the size has to be greater or equal to 6.");
}
}
return ValidationResult.Success;
}
}
}
- 我们验证的是Size,所以在Model里的Size添加我们自定义的Attribute
[Shirt_EnsureCorrectSizing]
public int Size { get; set; }
6. WebApi Return Types
6.1 直接返回对象
- 创建一个List,存放所有的Shirt实例,返回一个Shirt类型
- 通过id访问
https://localhost:7232/api/shirts/1
, 返回一个json
{
shirtId: 1,
brand: "My Brand",
color: "Blue",
size: 10,
gender: "Men",
price: 30
}
6.2 返回多类型
- 如果返回多类型,就不能指定具体返回的类型,需要返回一个
IActionResult
[HttpGet("{id}")]
public IActionResult GetShirtById(int id)
{
if (id <= 0)
{
return BadRequest("Invalid shirt ID");
}
var shirt = shirts.FirstOrDefault(x => x.ShirtId == id);
if( shirt == null)
{
return NotFound();
}
return Ok(shirt);
}
7. Action filter
- 使用Action filter进行data validation
7.1 创建filter
- 创建Filters文件夹,并且创建
Shirt_ValidateShirtId.cs
类,并且添加对ShortId的验证
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using WebAPIDemo.Models.Repositories;
namespace WebAPIDemo.Filters
{
public class Shirt_ValidateShirtIdFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(context);
var shirtId = context.ActionArguments["id"] as int?;
if (shirtId.HasValue)
{
if (shirtId.Value <= 0)
{
context.ModelState.AddModelError("ShirtId", "ShirtId is invalid.");
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Status = StatusCodes.Status400BadRequest
};
context.Result = new BadRequestObjectResult(problemDetails);
}
else if (!ShirtRepository.ShirtExists(shirtId.Value))
{
context.ModelState.AddModelError("ShirtId", "Shirt doesn't exist.");
var problemDetails = new ValidationProblemDetails(context.ModelState)
{
Status = StatusCodes.Status404NotFound
};
context.Result = new NotFoundObjectResult(problemDetails);
}
}
}
}
}
- 使用添加的filter,对 id进行验证
[HttpGet("{id}")]
[Shirt_ValidateShirtIdFilter]
public IActionResult GetShirtById(int id)
{
return Ok(ShirtRepository.GetShirtById(id));
}