文章目录
- 前言
- 一、参数传递方式
-
- [路由参数(Route Parameters)](#路由参数(Route Parameters))
- [查询字符串参数(Query String Parameters)](#查询字符串参数(Query String Parameters))
- [请求体参数(Request Body)](#请求体参数(Request Body))
- [表单数据(Form Data)](#表单数据(Form Data))
- [请求头参数(Header Parameters)](#请求头参数(Header Parameters))
- [服务注入(Service Injection)](#服务注入(Service Injection))
- 二、高级用法与技巧
- 三、验证与安全性
- 四、最佳实践
- 五、常见问题
-
- 参数绑定失败如何处理?
- 如何接收动态参数(如未知的查询键值对)?
- 如何处理数组参数?
- [如果参数和上面不一样需要用到FromRoute: [FromRoute(Name= "XXX")]](#如果参数和上面不一样需要用到FromRoute: [FromRoute(Name= "XXX")])
- 总结
前言
在ASP.NET Core Web API中,参数传递方式多样且灵活,合理选择传递方式对API设计和性能优化至关重要。
一、参数传递方式
路由参数(Route Parameters)
-
用途:标识资源路径中的核心参数(如ID、分类名)。
-
绑定特性 :[FromRoute]
-
示例 :
csharp[HttpGet("products/{id}")] public IActionResult GetProduct([FromRoute] int id) { // 通过路径如 /api/products/5 获取id=5 }
查询字符串参数(Query String Parameters)
-
用途:用于过滤、分页、排序等可选操作。
-
绑定特性 :[FromQuery]
-
示例 :
csharp[HttpGet("products")] public IActionResult Search([FromQuery] string keyword, [FromQuery] int page = 1) { // 请求示例:/api/products?keyword=apple&page=2 }
请求体参数(Request Body)
-
用途 :传递复杂数据结构(如JSON 对象),常用于POST/PUT请求。
-
绑定特性 :[FromBody]
-
示例 :
csharp[HttpPost("products")] public IActionResult CreateProduct([FromBody] ProductDto product) { // 请求体为JSON:{ "Name": "Phone", "Price": 999 } }
表单数据(Form Data)
-
用途 :处理multipart/form-data 或application/x-www-form-urlencoded 格式(如文件上传)。
-
绑定特性 :[FromForm]
-
示例 :
csharp[HttpPost("upload")] public IActionResult UploadFile([FromForm] IFormFile file, [FromForm] string description) { // 通过表单提交文件和描述字段 }
请求头参数(Header Parameters)
-
用途 :传递元数据 (如认证令牌 、客户端信息)。
-
绑定特性 :[FromHeader]
-
示例 :
csharp[HttpGet("user")] public IActionResult GetUser([FromHeader(Name = "Authorization")] string authToken) { // 从请求头获取Authorization值 }
服务注入(Service Injection)
-
用途:直接注入依赖的服务(如数据库上下文、日志服务)。
-
绑定特性 :[FromServices]
-
示例 :
csharp[HttpGet("logs")] public IActionResult GetLogs([FromServices] ILogger<MyController> logger) { logger.LogInformation("Fetching logs..."); // ... }
二、高级用法与技巧
混合参数来源
-
场景 :同时使用路由 、查询字符串 和请求体。
-
示例:
csharp[HttpPut("products/{id}")] public IActionResult UpdateProduct( [FromRoute] int id, [FromQuery] bool forceUpdate, [FromBody] ProductDto product ) { // 请求示例:PUT /api/products/5?forceUpdate=true // Body: { "Name": "New Name" } }
模型绑定(自动绑定)
-
说明:ASP.NET Core自动根据参数名和类型绑定数据,无需显式标注**[From*]**。
-
示例
csharp[HttpGet("products")] public IActionResult Get(int page, int pageSize) { // 自动从查询字符串绑定:/api/products?page=2&pageSize=20 }
自定义模型绑定
-
场景 :处理特殊格式的输入(如自定义日期格式)。
-
实现 :继承IModelBinder接口。
-
示例 :
csharppublic class CustomDateBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext context) { var value = context.ValueProvider.GetValue("customDate").FirstValue; // 解析自定义日期格式... } } [HttpGet("events")] public IActionResult GetEvents([ModelBinder(typeof(CustomDateBinder))] DateTime date) { // 使用自定义日期绑定逻辑 }
三、验证与安全性
数据注解验证
-
用途 :通过DataAnnotations验证参数合法性。
-
示例 :
csharppublic class ProductDto { [Required] [StringLength(100)] public string Name { get; set; } [Range(0, 10000)] public decimal Price { get; set; } } [HttpPost("products")] public IActionResult CreateProduct([FromBody] ProductDto product) { if (!ModelState.IsValid) { return BadRequest(ModelState); } // ... }
敏感参数处理
-
建议 :避免通过URL 传递敏感信息 (如密码 ),改用请求体或Headers。
-
错误示例 :
csharp// 不推荐:密码暴露在URL中 [HttpGet("login")] public IActionResult Login([FromQuery] string username, [FromQuery] string password) { // ... }
文件上传安全
-
建议 :限制文件类型和大小。
-
示例 :
csharp[HttpPost("upload")] public async Task<IActionResult> Upload([FromForm] IFormFile file) { if (file.Length > 5 * 1024 * 1024) { return BadRequest("文件大小不能超过5MB"); } // ... }
四、最佳实践
遵循RESTful设计:
- GET:使用路由和查询参数。
- POST/PUT:使用请求体传递复杂数据。
明确参数来源:
- 显式使用[FromRoute]、[FromQuery]等特性,避免歧义。
性能优化:
- 避免在GET请求中使用请求体(不符合HTTP规范)。
- 大文件上传使用IFormFile,而非Base64编码。
版本控制:
-
通过路由或查询参数实现API版本管理:
csharp[Route("api/v1/[controller]")] public class ProductsV1Controller : ControllerBase { /*...*/ }
文档化:
-
使用Swagger/OpenAPI生成文档,明确参数类型和用途
csharpbuilder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); }); app.UseSwagger(); app.UseSwaggerUI();
五、常见问题
参数绑定失败如何处理?
-
方案 :检查模型绑定错误,返回详细错误信息:
csharpif (!ModelState.IsValid) { return BadRequest(ModelState); }
如何接收动态参数(如未知的查询键值对)?
-
方案 :使用Dictionary<string, string>或动态类型 :
csharp[HttpGet("search")] public IActionResult Search([FromQuery] Dictionary<string, string> filters) { // 处理动态过滤条件 }
如何处理数组参数?
-
示例 :通过查询字符串传递数组:
csharp// 请求:/api/products?categories=books&categories=electronics [HttpGet("products")] public IActionResult GetProducts([FromQuery] List<string> categories) { // categories = ["books", "electronics"] }
如果参数和上面不一样需要用到FromRoute: [FromRoute(Name= "XXX")]
-
示例 :
csharp[HttpGet("{age}/{address}")] public ActionResult<Person> GetPersonByAgeAndAddress(int age, string address) //如果参数和上面不一样需要用到FromRoute: [FromRoute(Name= "address")]string addre //public ActionResult<Person> GetPersonByAgeAndAddress(int age,[FromRoute(Name= "address")]string addre) { List<Person> plist = new List<Person> { new Person ("张三", 32, "湖北"), new Person ("李四", 29, "湖南") }; var person = plist.SingleOrDefault(a => a.Age == age&&a.Address== address); if (person == null) { return NotFound("无此人员的数据信息"); } else { return person; } }
总结
通过合理选择参数传递方式,结合验证和安全性措施,可以构建高效、安全且易维护的Web API。