此入门教程是记录下方参考资料视频的学习过程
开发工具:Visual Studio 2019
参考资料:https://www.bilibili.com/video/BV1c441167KQ
API文档:https://docs.microsoft.com/zh-cn/dotnet/api/?view=aspnetcore-3.1
ASP.NET Core 3.x 入门(一)创建项目 和 部署
ASP.NET Core 3.x 入门(二)建立 Controller ,使用 Tag Helper
ASP.NET Core 3.x 入门(三)View Component
ASP.NET Core 3.x 入门(四)Razor Page
ASP.NET Core 3.x 入门(五)SignalR
ASP.NET Core 3.x 入门(六)Blazor
ASP.NET Core 3.x 入门(七)Web API
ASP.NET Core 3.x 入门(八)gRPC - Protocol Buffer
ASP.NET Core 3.x 入门(九)gRPC in ASP.NET Core 3.x
还是 ASP.NET Core Web Application
我的命名是 My_ASP_NET_Core_Api
空模板,Https 和 Docker 都不勾选
将之前项目的 Models 和 Services 文件夹都复制到当前项目中,Services 目录下删除 Department 和 Employee 相关的接口和类
项目下新建 Repositories 文件夹,新建六个类
IDepartmentRepository.cs
public interface IDepartmentRepository
{
Task Add(Department department);
Task> GetAll();
Task GetById(int id);
}
DepartmentRepository.cs
public class DepartmentRepository : IDepartmentRepository
{
private readonly List _departments = new List();
public DepartmentRepository()
{
this._departments.Add(new Department
{
Id = 1,
Name = "HR",
EmployeeCount = 16,
Location = "Beijing"
});
this._departments.Add(new Department
{
Id = 2,
Name = "R&D",
EmployeeCount = 52,
Location = "Shanghai"
});
this._departments.Add(new Department
{
Id = 3,
Name = "Sales",
EmployeeCount = 200,
Location = "China"
});
}
public Task> GetAll()
{
return Task.Run(() => this._departments.AsEnumerable());
}
public Task GetById(int id)
{
return Task.Run(() => this._departments.FirstOrDefault(x => x.Id == id));
}
public Task Add(Department department)
{
department.Id = this._departments.Max(x => x.Id) + 1;
this._departments.Add(department);
return Task.Run(() => department);
}
}
IEmployeeRepository.cs
public interface IEmployeeRepository
{
Task Add(Employee employee);
Task> GetByDepartmentId(int departmentId);
Task Fire(int id);
}
EmployeeRepository.cs
public class EmployeeRepository : IEmployeeRepository
{
private readonly List _employees = new List();
public EmployeeRepository()
{
this._employees.Add(new Employee
{
Id = 1,
DepartmentId = 1,
FirstName = "Nick",
LastName = "Carter",
Gender = Gender.男
});
this._employees.Add(new Employee
{
Id = 2,
DepartmentId = 1,
FirstName = "Michael",
LastName = "Jackson",
Gender = Gender.男
});
this._employees.Add(new Employee
{
Id = 3,
DepartmentId = 1,
FirstName = "Mariah",
LastName = "Carey",
Gender = Gender.女
});
this._employees.Add(new Employee
{
Id = 4,
DepartmentId = 2,
FirstName = "Axl",
LastName = "Rose",
Gender = Gender.男
});
this._employees.Add(new Employee
{
Id = 5,
DepartmentId = 2,
FirstName = "Kate",
LastName = "Winslet",
Gender = Gender.女
});
this._employees.Add(new Employee
{
Id = 6,
DepartmentId = 3,
FirstName = "Rob",
LastName = "Thomas",
Gender = Gender.男
});
this._employees.Add(new Employee
{
Id = 7,
DepartmentId = 3,
FirstName = "Avril",
LastName = "Lavigne",
Gender = Gender.女
});
this._employees.Add(new Employee
{
Id = 8,
DepartmentId = 3,
FirstName = "Katy",
LastName = "Perry",
Gender = Gender.女
});
this._employees.Add(new Employee
{
Id = 9,
DepartmentId = 3,
FirstName = "Michelle",
LastName = "Monaghan",
Gender = Gender.女
});
}
public Task Add(Employee employee)
{
employee.Id = this._employees.Max(x => x.Id) + 1;
this._employees.Add(employee);
return Task.Run(() => employee);
}
public Task> GetByDepartmentId(int departmentId)
{
return Task.Run(() => this._employees.Where(x => x.DepartmentId == departmentId));
}
public Task Fire(int id)
{
return Task.Run(() =>
{
var employee = this._employees.FirstOrDefault(e => e.Id == id);
if (employee != null)
{
employee.Fired = true;
return employee;
}
return null;
});
}
}
ISummaryRepository.cs
public interface ISummaryRepository
{
public Task GetCompanySummary();
}
SummaryRepository.cs
public class SummaryRepository : ISummaryRepository
{
private readonly IDepartmentRepository _departmentRepository;
public SummaryRepository(IDepartmentRepository departmentRepository)
{
this._departmentRepository = departmentRepository;
}
public Task GetCompanySummary()
{
return Task.Run(() =>
{
var all = this._departmentRepository.GetAll().Result;
return new CompanySummary
{
EmployeeCount = all.Sum(x => x.EmployeeCount),
AverageDepartmentEmployeeCount = (int)all.Average(x => x.EmployeeCount)
};
});
}
}
这六个文件和之前删除的 Service 差不多
写完别忘记注册,Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
新建 Controllers
ApiController 建议继承 ControllerBase ,Controller 就是继承自 ControllerBase
ControllerBase 没有对 View 的支持,因为是 Web Api ,所以不需要 View
DepartmentController.cs
[Route("v1/[controller]")]
[ApiController]
public class DepartmentController : ControllerBase
{
private readonly IDepartmentRepository _departmentRepository;
public DepartmentController(IDepartmentRepository departmentRepository)
{
this._departmentRepository = departmentRepository;
}
[HttpGet]// v1/Department verb:GET
//public async Task GetAll() //也可以
public async Task>> GetAll()
{
var departments = await this._departmentRepository.GetAll();
if (!departments.Any())
{
return NoContent();
}
return Ok(departments);
//return new ObjectResult(departments);
}
[HttpPost]// v1/Department verb:POST
public async Task> Add([FromBody]Department department)
{
var added = await this._departmentRepository.Add(department);
return Ok(added);
}
}
EmployeeController.cs
[Route("v1/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
private readonly IEmployeeRepository _employeeRepository;
public EmployeeController(IEmployeeRepository employeeRepository)
{
this._employeeRepository = employeeRepository;
}
[HttpGet("{departmentId}")]
public async Task GetByDepartmentId(int departmentId)
{
var employees = await this._employeeRepository.GetByDepartmentId(departmentId);
if (!employees.Any())
{
return NoContent();
}
return Ok(employees);
}
[HttpGet("One/{id}", Name = "GetById")]
public async Task GetById(int id)
{
var result = await this._employeeRepository.GetById(id);
if (null == result)
{
return NotFound();
}
return Ok(result);
}
[HttpPost]
public async Task Add([FromBody] Employee employee)
{
var added = await this._employeeRepository.Add(employee);
return CreatedAtRoute("GetById", new { id = added.Id }, added);
//这里的 GetById 就是上面写的那个 GetById 方法,[HttpGet("One/{id}", Name = "GetById")]
}
[HttpPut("{id}")]//其实这里应该用 [HttpPatch]
public async Task Fire(int id)
{
var result = await this._employeeRepository.Fire(id);
if (null != result)
{
return NoContent();
}
return NotFound();
}
}
SummaryController.cs
[Route("v1/[controller]")]
[ApiController]
public class SummaryController : ControllerBase
{
private readonly ISummaryRepository _summaryRepository;
public SummaryController(ISummaryRepository summaryRepository)
{
this._summaryRepository = summaryRepository;
}
public async Task Get()
{
var result = await this._summaryRepository.GetCompanySummary();
return Ok(result);
}
}
Controller 上标注的 [ApiController]
[FromBody]Department department
,会根据 Model 字段或属性的 Attribute 标注进行验证[FromBody]Department department
显示的写出 department 是从请求的 Body 里来的,因为 Controller 有 [ApiController]
标注,所以不加 [FromBody]
也行
[HttpGet("{departmentId}")]
,但是使用 [HttpGet("")]
的方法的参数里就不需要再标注 [FromRoute]
?
的参数[Route("v1/[controller]")]
路由,v1
版本控制,[controller]
是一个通配符,指的是控制器的名称,Department
RESTful Api 主要是通过 Http 动词来区分 Action ,所以默认不用加 Action ,就是说 url 访问 GET 的方法不需要管 Action 的名称
[ApiController]
[HttpGet]
HttpGet 默认可以不写,url 就是 版本/控制器名称 verb:GET
[HttpPost]
[FromBody]
CreatedAtRoute (string routeName, object routeValues, object content);
routeName
String
用于生成 URL 的路由的名称。
routeValues
Object
用于生成 URL 的路由数据。
content
Object
要在实体正文中设置格式的内容值。说白了就是返回给前端的数据
若使用 xml 去请求,还是会返回 json
因为默认情况下,ASP.NET Core Api 返回的是 json 格式的数据
若想支持 xml ,需要修改 Startup 类
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddXmlSerializerFormatters();
}
ASP.NET Core Api 也支持一些常用的格式,以及自定义格式
http://localhost:5000/v1/Department
效果图
选择 POST ,url 不变,在 Body 里添加数据
效果图
状态码截图
http://localhost:5000/v1/Emoloyee/1
效果图
http://localhost:5000/v1/Employee/One/1
效果图
http://localhost:5000/v1/Employee
效果图
http://localhost:5000/v1/Employee/9
效果图
状态码 204 ,对应 NoContent()
,说明成功
Get 去验证一下
效果图
http://localhost:5000/v1/Summary
效果图