ASP.NET Core Web API 参数传递方式

文章目录


前言

在ASP.NET Core Web API中,参数传递方式多样且灵活,合理选择传递方式对API设计和性能优化至关重要。

一、参数传递方式

路由参数(Route Parameters)

  1. 用途:标识资源路径中的核心参数(如ID、分类名)。

  2. 绑定特性[FromRoute]

  3. 示例

    csharp 复制代码
    [HttpGet("products/{id}")]
    public IActionResult GetProduct([FromRoute] int id) 
    {
        // 通过路径如 /api/products/5 获取id=5
    }

查询字符串参数(Query String Parameters)

  1. 用途:用于过滤、分页、排序等可选操作。

  2. 绑定特性[FromQuery]

  3. 示例

    csharp 复制代码
    [HttpGet("products")]
    public IActionResult Search([FromQuery] string keyword, [FromQuery] int page = 1) 
    {
        // 请求示例:/api/products?keyword=apple&page=2
    }

请求体参数(Request Body)

  1. 用途 :传递复杂数据结构(如JSON 对象),常用于POST/PUT请求。

  2. 绑定特性[FromBody]

  3. 示例

    csharp 复制代码
    [HttpPost("products")]
    public IActionResult CreateProduct([FromBody] ProductDto product) 
    {
        // 请求体为JSON:{ "Name": "Phone", "Price": 999 }
    }

表单数据(Form Data)

  1. 用途 :处理multipart/form-dataapplication/x-www-form-urlencoded 格式(如文件上传)。

  2. 绑定特性[FromForm]

  3. 示例

    csharp 复制代码
    [HttpPost("upload")]
    public IActionResult UploadFile([FromForm] IFormFile file, [FromForm] string description) 
    {
        // 通过表单提交文件和描述字段
    }

请求头参数(Header Parameters)

  1. 用途 :传递元数据 (如认证令牌客户端信息)。

  2. 绑定特性[FromHeader]

  3. 示例

    csharp 复制代码
    [HttpGet("user")]
    public IActionResult GetUser([FromHeader(Name = "Authorization")] string authToken) 
    {
        // 从请求头获取Authorization值
    }

服务注入(Service Injection)

  1. 用途:直接注入依赖的服务(如数据库上下文、日志服务)。

  2. 绑定特性[FromServices]

  3. 示例

    csharp 复制代码
    [HttpGet("logs")]
    public IActionResult GetLogs([FromServices] ILogger<MyController> logger) 
    {
        logger.LogInformation("Fetching logs...");
        // ...
    }

二、高级用法与技巧

混合参数来源

  1. 场景 :同时使用路由查询字符串请求体

  2. 示例:

    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" }
    }

模型绑定(自动绑定)

  1. 说明ASP.NET Core自动根据参数名和类型绑定数据,无需显式标注**[From*]**。

  2. 示例

    csharp 复制代码
    [HttpGet("products")]
    public IActionResult Get(int page, int pageSize) 
    {
        // 自动从查询字符串绑定:/api/products?page=2&pageSize=20
    }

自定义模型绑定

  1. 场景 :处理特殊格式的输入(如自定义日期格式)。

  2. 实现 :继承IModelBinder接口。

  3. 示例

    csharp 复制代码
    public 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) 
    {
        // 使用自定义日期绑定逻辑
    }

三、验证与安全性

数据注解验证

  1. 用途 :通过DataAnnotations验证参数合法性。

  2. 示例

    csharp 复制代码
    public 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);
        }
        // ...
    }

敏感参数处理

  1. 建议 :避免通过URL 传递敏感信息 (如密码 ),改用请求体或Headers

  2. 错误示例

    csharp 复制代码
    // 不推荐:密码暴露在URL中
    [HttpGet("login")]
    public IActionResult Login([FromQuery] string username, [FromQuery] string password) 
    {
        // ...
    }

文件上传安全

  1. 建议 :限制文件类型和大小

  2. 示例

    csharp 复制代码
    [HttpPost("upload")]
    public async Task<IActionResult> Upload([FromForm] IFormFile file)
    {
        if (file.Length > 5 * 1024 * 1024) 
        {
            return BadRequest("文件大小不能超过5MB");
        }
        // ...
    }

四、最佳实践

遵循RESTful设计:

  1. GET:使用路由和查询参数。
  2. POST/PUT:使用请求体传递复杂数据。

明确参数来源:

  1. 显式使用[FromRoute]、[FromQuery]等特性,避免歧义。

性能优化:

  1. 避免在GET请求中使用请求体(不符合HTTP规范)。
  2. 大文件上传使用IFormFile,而非Base64编码。

版本控制:

  1. 通过路由或查询参数实现API版本管理:

    csharp 复制代码
    [Route("api/v1/[controller]")]
    public class ProductsV1Controller : ControllerBase { /*...*/ }

文档化:

  1. 使用Swagger/OpenAPI生成文档,明确参数类型和用途

    csharp 复制代码
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    });
    
    app.UseSwagger();
    app.UseSwaggerUI();

五、常见问题

参数绑定失败如何处理?

  1. 方案 :检查模型绑定错误,返回详细错误信息:

    csharp 复制代码
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

如何接收动态参数(如未知的查询键值对)?

  1. 方案 :使用Dictionary<string, string>动态类型

    csharp 复制代码
    [HttpGet("search")]
    public IActionResult Search([FromQuery] Dictionary<string, string> filters) 
    {
        // 处理动态过滤条件
    }

如何处理数组参数?

  1. 示例 :通过查询字符串传递数组:

    csharp 复制代码
    // 请求:/api/products?categories=books&categories=electronics
    [HttpGet("products")]
    public IActionResult GetProducts([FromQuery] List<string> categories) 
    {
        // categories = ["books", "electronics"]
    }

如果参数和上面不一样需要用到FromRoute: [FromRoute(Name= "XXX")]

  1. 示例

    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。

相关推荐
大学生资源网16 分钟前
基于springboot的万亩助农网站的设计与实现源代码(源码+文档)
java·spring boot·后端·mysql·毕业设计·源码
苏三的开发日记25 分钟前
linux端进行kafka集群服务的搭建
后端
苏三的开发日记43 分钟前
windows系统搭建kafka环境
后端
爬山算法1 小时前
Netty(19)Netty的性能优化手段有哪些?
java·后端
Tony Bai1 小时前
Cloudflare 2025 年度报告发布——Go 语言再次“屠榜”API 领域,AI 流量激增!
开发语言·人工智能·后端·golang
想用offer打牌1 小时前
虚拟内存与寻址方式解析(面试版)
java·后端·面试·系统架构
無量1 小时前
AQS抽象队列同步器原理与应用
后端
9号达人2 小时前
支付成功订单却没了?MyBatis连接池的坑我踩了
java·后端·面试
用户497357337982 小时前
【轻松掌握通信协议】C#的通信过程与协议实操 | 2024全新
后端
草莓熊Lotso2 小时前
C++11 核心精髓:类新功能、lambda与包装器实战
开发语言·c++·人工智能·经验分享·后端·nginx·asp.net