6.3 ASP.NET Core Web API技术选择
控制器父类
Controller
继承自ControllerBase
,只不过增加了视图相关的方法,一般mvc项目选用Controller
而Web API项目选择ControllerBase
即可。
操作方法的返回值和状态码
ASP.NET Core Web API中的操作方法返回值如果是普通数据类型,则返回值默认被序列化为JSON格式的响应报文体返回。
ASP.NET Core Web API也支持IActionResult<T>
类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| [Route("api/[controller]/[action]")] [ApiController] public class TestController : ControllerBase { [HttpGet("{id}")] public ActionResult<Person> GetPerson(int id) { if (id <= 0) { return BadRequest("id必须是正数"); } else if (id == 1) { return new Person(1, "tom", 18); } else if (id == 2) { return new Person(2, "Zack", 8); } else { return NotFound("人员不存在"); } } }
|
对于失败的请求,一般要统一响应报文体的格式以便在客户端进行处理。
public record ErrorInfo(int Code, string? Message);
声明一个表示错误的详细信息类
其中code参数表示错误的自定义业务代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| [HttpGet("{id}")] public ActionResult<Person> GetPerson(int id) { if (id <= 0) { return BadRequest(new ErrorInfo(1,"id必须是正数")); } else if (id == 1) { return new Person(1, "tom", 18); } else if (id == 2) { return new Person(2, "Zack", 8); } else { return NotFound(new ErrorInfo(2,"人员不存在")); } }
|

|

|
操作方法的参数
给服务器传递参数的时候,有URL、QueryString、请求报文体3种方式
请求路径/Student/GetAll/school/MIT/class/A001
GetAll方法添加了[HttpGet("schllo/{schoolName}/class/{classNo}")]
结果:schoolName=MIT和classNo=A001。如果GetAll方法的参数中有和占位符名字同名的参数,那么这个参数就会被自动赋值。如果占位符名字与参数名称不一致,则使用[FromRoute]的Name属性来设置匹配的占位符的名字,例如:
1 2
| [HttpGet("schllo/{schoolName}/class/{classNo}")] public ActionResult<Student[]> GetAll(string schoolName,[FromRoute(Name="classNo")]string calssNum)
|
使用[FromQuery]
来获取,如果操作方法的参数名字和QueryString的名字一致,只需要为参数添加[FromQuery],否则,就要设定[FromQuery]的name属性指定名字
1 2
| public ActionResult<Student[]> GetAll([FromQuery]string pageNum,[FromQuery)(Name="psize")]int pageSize)
|
1 2 3
| [HttpGet("schllo/{schoolName}/class/{classNo}")] public ActionResult<Student[]> GetAll(string schoolName,[FromRoute(Name="classNo")]string calssNum,[FromQuery]string pageNum,[FromQuery)(Name="psize")]int pageSize)
|
目前JSON是主流的请求报文体格式,本文讲JSON报文体
案例:
需求:前端浏览器向服务器发送的报文体:{“name”:”qs”,”age”:”18”}
直接声明一个Person类定义Name和age两个属性
1 2
| [HttpPost] public ActionResult AddNew(Person p)
|
客户端只要向/Person/AddNew提交Post提交即可
也可以从URL中获取参数、从请求报文体获取数据混合使用
1 2 3 4
| [HttpPost("classId/{classId}")] public ActionResult<long> AddNew(long classId,Person s)
|
注意:一定设置请求报文头中Content-Type为application/JSON
案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public record ProcessInfo(int Id,string ProcessName,long WorkingSet64); public record LoginResult(bool isok, ProcessInfo[]? Process); public record LoginRequeset(string username,string password);
[Route("api/[controller]/[action]")] [ApiController] public class LoginController : ControllerBase { [HttpPost] public ActionResult<LoginResult> Login(LoginRequeset loginreq) { if (loginreq.username =="admin" && loginreq.password =="123456") { var process = Process.GetProcesses().Select(p => new ProcessInfo(p.Id, p.ProcessName, p.WorkingSet64)).ToArray(); return new LoginResult(true, process); } else { return new LoginResult(false, null); } } }
|
前端页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>dddd</title> </head> <body> <div id="app"> <div> <label>账户:</label> <input type="text" placeholder="账户" v-model="acount" /> <label>账户:</label> <input type="password" placeholder="密码" v-model="password" /> <button @click="queryprocess"> 搜 索 </button> </div> <div> <ul> <li v-for="(process,index) in processarr"> id: {{process.id}} == processName: {{process.processName}} == workingSet64: {{process.workingSet64}} </li> </ul> </div> </div>
<script src="./vue.js"></script> <script src="./axios.min.js"></script> <script> var app = new Vue({ el: "#app", data: { processarr: [], acount: "", password: "" }, methods: { queryprocess() { var that = this; axios.post("http://localhost:7285/api/Login/Login", { username: this.acount, password: this.password }).then(res => { if(!res.data.isok) { alert("账户密码错误!"); return; } that.processarr = res.data.process; console.log(res); }, err => { alert("访问出错");}); }, } }); </script> </body> </html>
|
启动服务后,发现浏览器没有反应,这是因为前端和后端不在同一个域名下(不同的端口也认为是不同的域名),浏览器默认是禁止AJAX跨域。我们可以采用CORS方式,CORS是浏览器中标准的跨域通信方式。CORS的原理是在服务器的响应报文头文件中通过access-control-allow-origin
告诉浏览器允许跨域访问的域名。
我们需要在后端项目中启用CORS,并且设定前端项目的域名。
1 2 3 4 5 6
| string[] urls = new[] { "http://127.0.0.1:5500" }; builder.Services.AddCors(options => options.AddDefaultPolicy(builder => builder.WithOrigins(urls) .AllowAnyMethod().AllowAnyHeader().AllowCredentials()));
|
