ASP.NET Core 3.1 API 邮箱路由/查询参数传参失效及返回值异常求解
接口传参与逻辑异常的根因和修复方案
核心问题根因
- 路径传参带邮箱无法匹配:Kestrel处理带句点(.)的路径段时,若静态文件中间件顺序在路由中间件之前,会将请求判定为静态文件请求,拦截API路由匹配。
- 返回值带多余转义引号:URL中直接写入双引号字符,未做编码处理,框架将包含引号的原始字符串直接绑定为参数值,序列化时自然带上转义引号。
- 查询传参拿到值为"email":ASP.NET Core 模型绑定优先级为路由值 > 查询字符串,你的路由模板定义了
{email}占位符,URL路径段的"email"会优先被绑定为参数值,后续查询字符串中的同名参数不会被读取覆盖。
分场景调整方案
方案1:保留路径传参模式
- 调整中间件顺序,让API路由优先匹配请求:
在Startup.cs的Configure方法中,确保路由中间件在静态文件中间件之前执行:
// 正确的中间件顺序 app.UseRouting(); app.UseStaticFiles();
- 修正请求URL写法:
直接在路径段传入编码后的邮箱值即可,无需额外加引号,正确示例为https://localhost:5001/api/User/test@test.com,框架会自动解码得到正确的邮箱值。
方案2:改用查询字符串传参(更推荐)
修改控制器Action的路由定义,明确指定参数从查询字符串读取,彻底避免路由值和查询值的绑定冲突:
// 去掉路由模板中的email占位符 [HttpGet] public async Task<IActionResult> Get([FromQuery] string email) { // 移除无意义的email.ToString(),参数本身已是string类型 IUsers user = new Users(); IDictionary<string, string> fetch = await Task.Run(() => user.FetchUser(email)); System.Diagnostics.Debug.WriteLine("Fetch User - " + fetch); // 用TryGetValue优化null判断,避免KeyNotFoundException if (fetch.TryGetValue("passhash", out var passhash) && passhash != null) { return Ok(fetch); } return BadRequest(); }
此时正确的请求地址为https://localhost:5001/api/User?email=test@test.com,不会出现参数绑定错乱的问题。
必须修复的代码安全风险
当前数据库查询逻辑存在严重的SQL注入风险,直接用字符串拼接SQL的写法,遇到邮箱值带单引号时会直接破坏语法,还会被恶意注入攻击。需要替换为参数化查询:
IDictionary<string, string> IUsers.FetchUser(string email) { using (dbConnection) { // 替换字符串拼接为参数化查询 string cmd = "select u.passhash from users u where email=@Email"; var passhash = dbConnection.Query<string>(cmd, new { @Email = email }).FirstOrDefault(); IDictionary<string, string> fetchedUser = new Dictionary<string, string>(); fetchedUser.Add("email", email); fetchedUser.Add("passhash", passhash); return fetchedUser; } }
预期效果
调整完成后,接口返回的JSON将和你的预期完全一致,无多余的引号、参数值错乱问题:
{ "email": "test@test.com", "passhash": "12121212121212" }
内容的提问来源于stack exchange,提问作者Scottish Smile
相关产品推荐
相关产品推荐

